Python Checkers多跳不能正常工作

时间:2015-06-29 18:39:14

标签: python algorithm

我正在实现我的Python Checkers Game的最后一个功能,即要求用户进行多次跳转。对于捕获,我执行以下操作:

1 Check if the move is valid:
2     self.validatedMove = True (The move that has been made is valid.)
3     self.capture() (Captures the piece given a correct user move)
4     How would I implement multiple jumps? I have tried researching for captures
      and then calling the capture function until there are no more captures left.

但最终陷入无限循环!

#when Red piece is not a king and piece can jump right      
if (self.turn == 'Red' and self.jump == True and len(self.captureDirections) == 1 and self.captureDirection == 'right'):
if (self.newPosition[0] == self.position[0] + 2 and self.newPosition[1] == self.position[1] + 2):
    self.validatedMove = True
    self.capture()

    #Stuck in an infinite loop
    while (len(captureDirections) > 0):
        self.captureDirections = []
        self.search_capture()
        self.capture()

以下是完整代码:

from tkinter import *

class CheckerSquare(Canvas):

    def __init__(self, master, row, column, color):

        Canvas.__init__(self, master, width=50, height=50, bg=color)
        self.grid(row=row, column=column)

        self.position = (row, column)
        self.color = None
        self.isKing = False

        self.bind('<Button>', master.place_piece)

    def get_position(self):

        return self.position

    def get_color(self):

        return self.color

    def create_piece(self, color):

        self.create_oval(10,10,44,44,fill=color, outline=color) 
        self.color = color  

    def create_king(self):

        self.isKing = True
        self.create_text(10, 15, text="*", font=("Garamond", 14), fill="#80FF80")

    def is_king(self):

        return self.isKing

class CheckerGame(Frame):

    def __init__(self, master):

        Frame.__init__(self, master, bg='White') 
        self.grid()

        self.squares = {}

        self.turn = 'Red'

        self.clicks = 0
        self.position = ()
        self.newPosition = ()
        self.jump = False
        self.validatedMove = False

        self.captureDirection = None
        self.captureDirections = []

        self.over = False

        self.turnIcon = CheckerSquare(self, 9, 2, "#B8B8B8")
        self.turnIcon.grid()
        self.turnIcon.create_piece(self.turn)

        self.turnLabel = Label(self, text = "Turn: ", font = ('Courier New', 8), bg='White')
        self.turnLabel.grid(row=9, column=1)

        self.directionLabel = Label(self, text="", font = ('Courier New', 8), bg='White')
        self.directionLabel.grid(row=9, column=4, columnspan=4, sticky=W)

        # Create the checker squares on the board
        for row in range(8): 
           for col in range(8):
                if (row % 2 == 0 and col % 2 == 0 or row % 2 == 1 and col % 2 == 1):
                    self.squares[(row,col)] = CheckerSquare(self, row, col, 'blanched almond')
                else:
                    self.squares[(row,col)] = CheckerSquare(self, row, col, 'dark green')

        # Draw the red pieces
        for i in range(3):
            for n in range(4):
                if (i % 2 == 0):
                    self.squares[(i, 2*n+1)].create_piece('Red')
                else:
                    self.squares[(i,2*n)].create_piece('Red')

        # Draw the white pieces
        for i in range(5, 8):
            for n in range(4):
                if (i % 2 == 0): 
                    self.squares[(i,2*n+1)].create_piece('White')
                else:
                    self.squares[(i,2*n)].create_piece('White')

    def winnerCheck(self):
        #Detects winner if all pieces on red or white are gone
        redPieces = 0
        whitePieces = 0

        for row in range(8):
            for column in range(8):
                squareColor = self.squares[row, column].get_color()
                if (squareColor == 'Red'):
                    redPieces += 1
                if (squareColor == 'White'):
                    whitePieces += 1

        if (redPieces == 0 and self.turn == 'Red'): #No red pieces left - white wins
            self.over = True
            self.directionLabel["text"] = 'Game Over - White Wins!'

        if (whitePieces == 0 and self.turn == 'White'): #No white pieces left - red wins
            self.over = True
            self.directionLabel["text"] = 'Game Over - Red Wins!'

    def update(self, turn):
        self.squares[self.position].create_piece('dark green') #clears previous square
        self.squares[self.position].color = None #updates color
        self.squares[self.newPosition].create_piece(turn) #updates piece position
        self.validatedMove = True #move is valid

    def capture(self):

            if (len(self.captureDirections) == 1):

                if (self.squares[self.position].get_color() == 'Red' and self.captureDirection == 'right'):
                    self.update('Red')
                    self.squares[self.position[0]+1, self.position[1]+1] = CheckerSquare(self, self.position[0]+1, self.position[1]+1, 'dark green')
                    self.squares[self.position[0]+1, self.position[1]+1].color = None

                if (self.squares[self.position].get_color() == 'Red' and self.captureDirection == 'left'):
                    self.update('Red')
                    self.squares[self.position[0]+1, self.position[1]-1] = CheckerSquare(self, self.position[0]+1, self.position[1]-1, 'dark green')
                    self.squares[self.position[0]+1, self.position[1]-1].color = None

                if (self.squares[self.position].get_color() == 'White' and self.captureDirection == 'right'):
                    self.update('White')
                    self.squares[self.position[0]-1, self.position[1]+1] = CheckerSquare(self, self.position[0]-1, self.position[1]+1, 'dark green')
                    self.squares[self.position[0]-1, self.position[1]+1].color = None

                if (self.squares[self.position].get_color() == 'White' and self.captureDirection == 'left'):
                    self.update('White')
                    self.squares[self.position[0]-1, self.position[1]-1] = CheckerSquare(self, self.position[0]-1, self.position[1]-1, 'dark green')
                    self.squares[self.position[0]-1, self.position[1]-1].color = None

            if (len(self.captureDirections) == 2 and self.squares[self.position].is_king() == False):

                if (self.squares[self.position].get_color() == 'White'):
                    self.update('White')
                    if (self.position[0]>0 and self.position[1]<7 and self.squares[self.position[0]-1, self.position[1]+1].get_color() == 'Red'):
                        self.squares[self.position[0]-1, self.position[1]+1] = CheckerSquare(self, self.position[0]-1, self.position[1]+1, 'dark green')
                        self.squares[self.position[0]-1, self.position[1]+1].color = None

                    if (self.position[0]>0 and self.position[1]>0 and self.squares[self.position[0]-1, self.position[1]-1].get_color() == 'Red'):
                        self.squares[self.position[0]-1, self.position[1]-1] = CheckerSquare(self, self.position[0]-1, self.position[1]-1, 'dark green')
                        self.squares[self.position[0]-1, self.position[1]-1].color = None

                if (self.squares[self.position].get_color() == 'Red'):
                    self.update('Red')
                    if (self.position[0]<7 and self.position[1]<7 and self.squares[self.position[0]+1, self.position[1]+1].get_color() == 'White'):
                        self.squares[self.position[0]+1, self.position[1]+1] = CheckerSquare(self, self.position[0]+1, self.position[1]+1, 'dark green')
                        self.squares[self.position[0]+1, self.position[1]+1].color = None

                    if (self.position[0]<7 and self.position[1]>0 and self.squares[self.position[0]+1, self.position[1]-1].get_color() == 'White'):
                        self.squares[self.position[0]+1, self.position[1]-1] = CheckerSquare(self, self.position[0]+1, self.position[1]-1, 'dark green')
                        self.squares[self.position[0]+1, self.position[1]-1].color = None

            if (self.squares[self.position].is_king() == True):

                if (len(self.captureDirections) == 1):

                    if (self.squares[self.position].get_color() == 'White' and self.captureDirections[0] == 'backward right'):
                        self.update('White')
                        self.squares[self.position] = CheckerSquare(self, self.position[0], self.position[1], 'dark green')
                        self.squares[self.position[0]+1, self.position[1]+1] = CheckerSquare(self, self.position[0]+1, self.position[1]+1, 'dark green')
                        self.squares[self.position[0]+1, self.position[1]+1].color = None
                        self.squares[self.newPosition].create_king()

                    if (self.squares[self.position].get_color() == 'White' and self.captureDirections[0] == 'backward left'):
                        self.update('White')
                        self.squares[self.position] = CheckerSquare(self, self.position[0], self.position[1], 'dark green')
                        self.squares[self.position[0]+1, self.position[1]-1] = CheckerSquare(self, self.position[0]+1, self.position[1]-1, 'dark green')
                        self.squares[self.position[0]+1, self.position[1]-1].color = None
                        self.squares[self.newPosition].create_king()

                    if (self.squares[self.position].get_color() == 'Red' and self.captureDirections[0] == 'backward right'):
                        self.update('Red')
                        self.squares[self.position] = CheckerSquare(self, self.position[0], self.position[1], 'dark green')
                        self.squares[self.position[0]-1, self.position[1]+1] = CheckerSquare(self, self.position[0]-1, self.position[1]+1, 'dark green')
                        self.squares[self.position[0]-1, self.position[1]+1].color = None
                        self.squares[self.newPosition].create_king()

                    if (self.squares[self.position].get_color() == 'Red' and self.captureDirections[0] == 'backward left'):
                        self.update('Red')
                        self.squares[self.position] = CheckerSquare(self, self.position[0], self.position[1], 'dark green')
                        self.squares[self.position[0]-1, self.position[1]-1] = CheckerSquare(self, self.position[0]-1, self.position[1]-1, 'dark green')
                        self.squares[self.position[0]-1, self.position[1]-1].color = None
                        self.squares[self.newPosition].create_king()

            self.jump = False

    def search_capture(self):
        #Capture
        for row in range(8):
            for col in range(8):
                squareColor = self.squares[(row, col)].get_color()

                #Left Capture - Red
                if (self.turn == 'Red' and col >= 2 and row <= 5 and squareColor == 'Red' and self.squares[(row + 1, col - 1)].get_color() == 'White' and \
                    self.squares[(row + 2, col - 2)].get_color() == None):
                    self.captureDirection = 'left'
                    self.captureDirections.append('left')
                    self.jump = True

                #Right Capture - Red
                if (self.turn == 'Red' and col <= 5 and row <= 5 and squareColor == 'Red' and self.squares[(row + 1, col + 1)].get_color() == 'White' and \
                    self.squares[(row + 2, col + 2)].get_color() == None):
                    self.captureDirection = 'right'
                    self.captureDirections.append('right')
                    self.jump = True

                #Capture for Left - White 
                if self.turn == 'White' and col >= 2 and row >= 2 and squareColor == 'White' and self.squares[(row - 1, col - 1)].get_color() == 'Red' and \
                    self.squares[(row - 2, col - 2)].get_color() == None:
                    self.captureDirection = 'left'
                    self.captureDirections.append('left')
                    self.jump = True

                #Right Capture - White
                if (self.turn == 'White' and col <= 5 and row >= 2 and squareColor == 'White' and self.squares[(row - 1, col + 1)].get_color() == 'Red' and \
                    self.squares[(row - 2, col + 2)].get_color() == None):
                    self.captureDirection = 'right'
                    self.captureDirections.append('right')
                    self.jump = True

                if (self.squares[(row, col)].is_king() == True):

                    #Backwards Left Capture - Red King
                    if self.turn == 'Red' and col >= 2 and row >= 2 and squareColor == 'Red' and self.squares[(row - 1, col - 1)].get_color() == 'White' and \
                        self.squares[(row - 2, col - 2)].get_color() == None:
                        self.captureDirection = 'backward left'
                        self.captureDirections.append('backward left')
                        self.jump = True

                    #Backwards Right Capture - Red King
                    if (self.turn == 'Red' and col <= 5 and row >= 2 and squareColor == 'Red' and self.squares[(row - 1, col + 1)].get_color() == 'White' and \
                        self.squares[(row - 2, col + 2)].get_color() == None):
                        self.captureDirection = 'backward right'
                        self.captureDirections.append('backward right')
                        self.jump = True

                    #Backwards Left Capture - White King
                    if (self.turn == 'White' and col >= 2 and row <= 5 and squareColor == 'White' and self.squares[(row + 1, col - 1)].get_color() == 'Red' and \
                        self.squares[(row + 2, col - 2)].get_color() == None):
                        self.captureDirection = 'backward left'
                        self.captureDirections.append('backward left')
                        self.jump = True

                    #Backwards Right Capture - White King
                    if (self.turn == 'White' and col <= 5 and row <= 5 and squareColor == 'White' and self.squares[(row + 1, col + 1)].get_color() == 'Red' and \
                        self.squares[(row + 2, col + 2)].get_color() == None):
                        self.captureDirection = 'backward right'
                        self.captureDirections.append('backward right')
                        self.jump = True

    def place_piece(self, event):
        if (self.over == False):           
            self.validatedMove = False
            #Program needs to check the current move

            #Adds to number of clicks
            self.clicks += 1

            #First stage of click (selecting a piece)
            if (self.clicks % 2 == 1):
                self.captureDirections = []

                if event.widget.get_color() == 'Red' or event.widget.get_color() == 'White':
                    self.position = event.widget.get_position() #retrieve position of selected piece

                    if (self.turn == self.squares[self.position].get_color()):
                        self.squares[self.position]['highlightbackground'] = 'black' #outline
                    else:
                        self.directionLabel['text'] = "It is " + self.turn + "'s turn!"

                    self.search_capture()      

            else: #second stage of click (moves piece to selected position)
                self.newPosition = event.widget.get_position()

                self.squares[self.position]['highlightbackground'] = 'White' #clears outline

                #when Red piece is not a king and the piece cannot jump
                if (self.turn == 'Red' and self.jump == False):
                    if (self.newPosition[0] == self.position[0] + 1 and self.newPosition[1] == self.position[1] + 1 and self.squares[self.newPosition].get_color() == None \
                        or self.newPosition[0] == self.position[0] + 1 and self.newPosition[1] == self.position[1] - 1 and self.squares[self.newPosition].get_color()  == None):
                        self.update('Red')
                        self.directionLabel['text'] = "" #clears error message
                        self.validatedMove = True
                    else: 
                        self.directionLabel['text'] = "Invalid Move!" #error message

                #when White piece is not a king and piece cannot jump
                if (self.turn == 'White' and self.jump == False):
                    if (self.newPosition[0] == self.position[0] - 1 and self.newPosition[1] == self.position[1] + 1 and self.squares[self.newPosition].get_color() == None \
                        or self.newPosition[0] == self.position[0] - 1 and self.newPosition[1] == self.position[1] - 1 and self.squares[self.newPosition].get_color() == None):
                        self.update('White')
                        self.directionLabel['text'] = "" #clears error message
                        self.validatedMove = True
                    else:
                        self.directionLabel['text'] = "Invalid Move!" #error message

                #when Red piece is not a king and piece can jump right      
                if (self.turn == 'Red' and self.jump == True and len(self.captureDirections) == 1 and self.captureDirection == 'right'):
                    if (self.newPosition[0] == self.position[0] + 2 and self.newPosition[1] == self.position[1] + 2):
                        self.validatedMove = True
                        self.capture()

                        while (len(captureDirections) > 0):
                            self.captureDirections = []
                            self.search_capture()
                            self.capture()

                #when Red piece is not a king and piece can jump left
                if (self.turn == 'Red' and self.jump == True and len(self.captureDirections) == 1 and self.captureDirection == 'left'):
                    if (self.newPosition[0] == self.position[0] + 2 and self.newPosition[1] == self.position[1] - 2):
                        self.validatedMove = True
                        self.capture()

                #when White piece is not a king and piece can jump right
                if (self.turn == 'White' and self.jump == True and len(self.captureDirections) == 1 and self.captureDirection == 'right'):
                    if (self.newPosition[0] == self.position[0] - 2 and self.newPosition[1] == self.position[1] + 2):
                        self.validatedMove = True
                        self.capture()

                #when White piece is not a king and piece can jump left
                if (self.turn == 'White' and self.jump == True and len(self.captureDirections) == 1 and self.captureDirection == 'left'):
                    if (self.newPosition[0] == self.position[0] - 2 and self.newPosition[1] == self.position[1] - 2):
                        self.validatedMove = True
                        self.capture()

                #when White piece is not a king and can capture both directions
                if (self.turn == 'White' and self.jump == True and len(self.captureDirections) == 2):
                    if (self.newPosition[0] == self.position[0] - 2 and self.newPosition[1] == self.position[1] + 2 or self.newPosition[1] == self.position[1] - 2):
                        self.validatedMove = True
                        self.capture()

                #when Red piece is not a king and can capture both directions
                if (self.turn == 'Red' and self.jump == True and len(self.captureDirections) == 2):
                    if (self.newPosition[0] == self.position[0] + 2 and self.newPosition[1] == self.position[1] + 2 or self.newPosition[1] == self.position[1] - 2):
                        self.validatedMove = True
                        self.capture()

                if (self.squares[self.position].is_king() == True):

                    #when Red piece is a king and the piece cannot jump
                    if (self.turn == 'Red' and self.jump == False):
                        if (self.newPosition[0] == self.position[0] - 1 and self.newPosition[1] == self.position[1] + 1 and self.squares[self.newPosition].get_color() == None \
                            or self.newPosition[0] == self.position[0] - 1 and self.newPosition[1] == self.position[1] - 1 and self.squares[self.newPosition].get_color() == None):
                            self.update('Red')
                            self.squares[self.position] = CheckerSquare(self, self.position[0], self.position[1], 'dark green')
                            self.squares[self.newPosition].create_king()
                            self.directionLabel['text'] = "" #clears error message
                            self.validatedMove = True
                        else:
                            self.directionLabel['text'] = "Invalid Move!" #error message

                    #when White piece is a king and the piece cannot jump
                    if (self.turn == 'White' and self.jump == False):
                        if (self.newPosition[0] == self.position[0] + 1 and self.newPosition[1] == self.position[1] + 1 and self.squares[self.newPosition].get_color() == None \
                            or self.newPosition[0] == self.position[0] + 1 and self.newPosition[1] == self.position[1] - 1 and self.squares[self.newPosition].get_color()  == None):
                            self.update('White')
                            self.squares[self.position] = CheckerSquare(self, self.position[0], self.position[1], 'dark green')
                            self.squares[self.newPosition].create_king()
                            self.directionLabel['text'] = "" #clears error message
                            self.validatedMove = True
                        else:
                            self.directionLabel['text'] = "Invalid Move!" #error message

                    #when Red piece is a king and the piece can jump backward left
                    if (self.turn == 'Red' and self.jump == True and len(self.captureDirections) == 1 and self.captureDirection == 'backward left'):
                        self.capture()
                        self.validatedMove = True

                    #when Red piece is a king and the piece can jump backward right
                    if (self.turn == 'Red' and self.jump == True and len(self.captureDirections) == 1 and self.captureDirection == 'backward right'):
                        self.capture()
                        self.validatedMove = True

                    #when White piece is a king and the piece can jump backward left
                    if (self.turn == 'White' and self.jump == True and len(self.captureDirections) == 1 and self.captureDirection == 'backward left'):
                        self.capture()
                        self.validatedMove = True

                    #when White piece is a king and the piece can jump backward right
                    if (self.turn == 'White' and self.jump == True and len(self.captureDirections) == 1 and self.captureDirection == 'backward right'):
                        self.capture()
                        self.validatedMove = True

                #Checks for king
                if (self.turn == 'Red' and self.validatedMove == True and self.newPosition[0] == 7):
                    self.squares[self.newPosition].create_king()

                if (self.turn == 'White' and self.validatedMove == True and self.newPosition[0] == 0):
                    self.squares[self.newPosition].create_king()

                #changes turn
                if (self.validatedMove == True):
                    if (self.turn == 'Red'):
                        self.turn = 'White'

                    elif (self.turn == 'White'):
                        self.turn = 'Red'

                #updates player turn icon
                self.turnIcon.create_piece(self.turn)

                self.winnerCheck() #Checks for winner

def play_checkers():
    root = Tk() 
    root.title('Python Checkers')
    CG = CheckerGame(root) 
    CG.mainloop()

play_checkers() 

1 个答案:

答案 0 :(得分:2)

我用以下代码解决了这个问题:

if (len(self.captureDirections) > 0):
    self.validatedMove = False
    self.captureDirections = []
    self.search_capture()
    self.capture()

解决问题的关键是重置self.validatedMove to False,这样如果还有可能再次跳跃,游戏就不会切换到白方。