Try   HackMD

TicTacToe 完整Code

Game.py的完整Code

from player import RandomComputerPlayer, HumanPlayer import time class TicTacToe: def __init__(self): self.board = [' ' for _ in range(9)] # we'll use a single list to represent 3x3 board self.current_winner = None # keep track of winner def print_board(self): # get the rows for row in [self.board[i*3:(i+1)*3] for i in range(3)]: # 0,1,2 3,4,5 6,7,8 print('|' + ' | '.join(row) + '|') @staticmethod def print_board_nums(): # it's going to print 0 | 1 | 2 , etc (tell us what number corresponds to what position) number_board = [[str(i) for i in range(j*3, (j+1)*3)] for j in range(3)] # [ [0,1,2],[3,4,5],[6,7,8] ] for row in number_board: print('|' + ' | '.join(row) + '|') def available_moves(self): # it'll return [] moves = [] for (i,spot) in enumerate(self.board): # ['x', 'x', 'o'] -> [(0, 'x'), (1, 'x'), (2, 'o')] if spot ==' ': moves.append(i) return moves # You can also use this: # return [i for i, spot in enumerate(self.board) if spot == ' '] def empty_squares(self): return ' ' in self.board def num_empty_squares(self): return self.board.count(' ') def make_move(self, square, letter): # If valid move, them make the move (assign square to letter) # then return True. If invalid, then return False. if self.board[square] ==' ': self.board[square] = letter if self.winner(square, letter): self.current_winner = letter return True return False def winner(self, square, letter): # wins if 3 in a row anythere. We have to check all of these # first we check the row row_ind = square // 3 row = self.board[row_ind*3 : (row_ind+1)*3] if all([spot == letter for spot in row]): return True # check column col_ind = square % 3 column = [self.board[col_ind+i*3] for i in range(3)] if all([spot == letter for spot in column]): return True # check diagonals # but if the square is an even umber(0, 2, 4, 6, 8) # these are the only moves possible to win a diagonal if square % 2 == 0: diagonal1 = [self.board[i] for i in [0, 4, 8]] # left to right diagonal if all([spot == letter for spot in diagonal1]): return True diagonal2 = [self.board[i] for i in [2, 4, 6]] # right to left diagonal if all([spot == letter for spot in diagonal2]): return True # If all of them fail return False def play(game, x_player, o_player, print_game = True): # return the winner of the game(the letter)! or None for a tie if print_game: game.print_board_nums() letter = 'X' #starting letter # iterate while the game still has empty squares #(we don't have to worry about winner because we'll just return that # which breaks the loop) while game.empty_squares(): # get the move from the appropriate player if letter == 'O': square = o_player.get_move(game) else: square = x_player.get_move(game) if game.make_move(square, letter): print(letter + f' makes a move to square {square}') game.print_board() print('') # just empty line if game.current_winner != None: if print_game: print(letter + ' wins!') return letter # switch player if letter == 'X': letter = 'O' else: letter = 'X' # or you can also use this # letter = 'O' if letter =='X' else 'X' # add a tiny pause time.sleep(0.8) if print_game: print('It\'s a tie!') if __name__ == '__main__': x_player = HumanPlayer('x') o_player = RandomComputerPlayer('o') # o_player = HumanPlayer('o') t = TicTacToe() play(t, x_player, o_player, print_game=True)

Player.py的完整Code

import random class Player: def __init__(self, letter): # letter is x or o self.letter = letter # we want all players to get their next move def get_move(self, game): pass class RandomComputerPlayer(Player): def __init__(self, letter): super().__init__(letter) def get_move(self, game): # get a random valid spot for our next move square = random.choice(game.available_moves()) return square class HumanPlayer(Player): def __init__(self, letter): super().__init__(letter) def get_move(self, game): valid_square = False val = None while not valid_square: square = input(self.letter + '\'s turn. Input move(0-8): ') # we're going to check that this is a correct value by tring cast #it to an integer, and if it's not, then we say it's invalid. # If that spot is not available on the board, we also say it's invalid. # try and except can deal with specific errors that happen. # Right here we use them to fix ValueError problems caused by square and val try: val = int(square) if val not in game.available_moves(): raise ValueError valid_square = True # If these are successful, then hurray! except ValueError: print('Invalid square. Try again.') return val