PLAYER_1 = 1 PLAYER_2 = 2 class NoughtsAndCrosses(object): """Basic implementation of Noughts and Crosses""" WIN_COMBOS = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]] EMPTY_BOARD = ["1", "2", "3", "4", "5", "6", "7", "8", "9"] def __init__(self): self.current_board = self.EMPTY_BOARD.copy() self.current_player = PLAYER_1 # game always starts with PLAYER_1 self.player_names = {} self.player_markers = { PLAYER_1: "", PLAYER_2: "", } def _print_board(self): """Prints the current board""" print("--- Noughts and Crosses ---") print(f'{self.current_board[0]} : {self.current_board[1]} : {self.current_board[2]}') print("..........") print(f'{self.current_board[3]} : {self.current_board[4]} : {self.current_board[5]}') print("..........") print(f'{self.current_board[6]} : {self.current_board[7]} : {self.current_board[8]}') def play(self): self._print_welcome_message() self._get_player_names() self._get_player_markers() while True: self._let_current_player_move() if self._player_has_won(self.current_player): print(f"{self.player_names[self.current_player]}, you have won!") break elif self._check_if_board_is_full(): print(f"Stalemate - End of game") break self._switch_current_player() def _let_current_player_move(self): print("Hi", self.player_names[self.current_player]) while True: chosen_board_index = self._get_next_move() if self._location_is_taken(chosen_board_index): print('>>> Position taken, try again!') continue else: self._update_board(chosen_board_index) self._print_board() break def _update_board(self, chosen_board_index): self.current_board[chosen_board_index] = self.player_markers[self.current_player] @staticmethod def _print_welcome_message(): print("*" * 50) print("Welcome to our Noughts and Crosses Game!") print("*" * 50) def _get_player_names(self): self.player_names[1] = input("Enter the name of the first player:\n> ") self.player_names[2] = input("Enter the name of the second player:\n> ") def _get_player_markers(self): self.player_markers[PLAYER_1] = input(f"{self.player_names[PLAYER_1]}, choose your marker (X/O):\n> ").upper() while self.player_markers[PLAYER_1] not in ["X", "O"]: print('>>> Invalid marker! Please choose either "X" or "O".') self.player_markers[PLAYER_1] = input(f"{self.player_names[PLAYER_1]}, choose your marker (X/O):\n> ").upper() self.player_markers[PLAYER_2] = "X" if self.player_markers[PLAYER_1] == "O" else "O" def _switch_current_player(self): if self.current_player == PLAYER_1: self.current_player = PLAYER_2 else: self.current_player = PLAYER_1 def _location_is_taken(self, board_index): return self.current_board[board_index] in self.player_markers.values() def _check_if_board_is_full(self): return True if all(marker in self.player_markers.values() for marker in self.current_board) else False def _player_has_won(self, player): for win_combo in self.WIN_COMBOS: if set(win_combo) <= set(self._get_player_locations(player)): return True return False # if no winning combinations were found def _get_player_locations(self, player): return [index for index, marker in enumerate(self.current_board) if marker == self.player_markers[player]] @staticmethod def _get_next_move(): while True: chosen_location = input("Cross location (choose 1 - 9):\n> ") if not chosen_location.isdigit() or int(chosen_location) not in range(1, 10): print('>>> Invalid input!') continue else: chosen_location = int(chosen_location) - 1 # adjust for array index to start at 0 not 1 return chosen_location if __name__ == '__main__': NoughtsAndCrosses().play()
- PLAYER_1 = 1
- PLAYER_2 = 2
- class NoughtsAndCrosses(object):
- """Basic implementation of Noughts and Crosses"""
- WIN_COMBOS = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]]
- EMPTY_BOARD = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
- def __init__(self):
- self.current_board = self.EMPTY_BOARD.copy()
- self.current_player = PLAYER_1 # game always starts with PLAYER_1
- self.player_names = {}
self.location_lists = {PLAYER_1: [],PLAYER_2: []}- self.player_markers = {
PLAYER_1: "X",PLAYER_2: "O",- PLAYER_1: "",
- PLAYER_2: "",
- }
- def _print_board(self):
- """Prints the current board"""
- print("--- Noughts and Crosses ---")
- print(f'{self.current_board[0]} : {self.current_board[1]} : {self.current_board[2]}')
- print("..........")
- print(f'{self.current_board[3]} : {self.current_board[4]} : {self.current_board[5]}')
- print("..........")
- print(f'{self.current_board[6]} : {self.current_board[7]} : {self.current_board[8]}')
- def play(self):
- self._print_welcome_message()
- self._get_player_names()
- self._get_player_markers()
- while True:
- self._let_current_player_move()
- if self._player_has_won(self.current_player):
- print(f"{self.player_names[self.current_player]}, you have won!")
- break
- elif self._check_if_board_is_full():
- print(f"Stalemate - End of game")
- break
- self._switch_current_player()
- def _let_current_player_move(self):
- print("Hi", self.player_names[self.current_player])
- while True:
- chosen_board_index = self._get_next_move()
- if self._location_is_taken(chosen_board_index):
- print('>>> Position taken, try again!')
- continue
- else:
self._update_board_and_location_lists(chosen_board_index)- self._update_board(chosen_board_index)
- self._print_board()
- break
def _update_board_and_location_lists(self, chosen_board_index):- def _update_board(self, chosen_board_index):
- self.current_board[chosen_board_index] = self.player_markers[self.current_player]
self.location_lists[self.current_player].append(chosen_board_index)- @staticmethod
- def _print_welcome_message():
- print("*" * 50)
- print("Welcome to our Noughts and Crosses Game!")
- print("*" * 50)
- def _get_player_names(self):
- self.player_names[1] = input("Enter the name of the first player:\n> ")
- self.player_names[2] = input("Enter the name of the second player:\n> ")
- def _get_player_markers(self):
- self.player_markers[PLAYER_1] = input(f"{self.player_names[PLAYER_1]}, choose your marker (X/O):\n> ").upper()
- while self.player_markers[PLAYER_1] not in ["X", "O"]:
- print('>>> Invalid marker! Please choose either "X" or "O".')
- self.player_markers[PLAYER_1] = input(f"{self.player_names[PLAYER_1]}, choose your marker (X/O):\n> ").upper()
- self.player_markers[PLAYER_2] = "X" if self.player_markers[PLAYER_1] == "O" else "O"
- def _switch_current_player(self):
- if self.current_player == PLAYER_1:
- self.current_player = PLAYER_2
- else:
- self.current_player = PLAYER_1
- def _location_is_taken(self, board_index):
- return self.current_board[board_index] in self.player_markers.values()
- def _check_if_board_is_full(self):
return True if len(self.location_lists[PLAYER_1] + self.location_lists[PLAYER_2]) == 9 else False- return True if all(marker in self.player_markers.values() for marker in self.current_board) else False
- def _player_has_won(self, player):
- for win_combo in self.WIN_COMBOS:
if set(win_combo) <= set(self.location_lists[player]):- if set(win_combo) <= set(self._get_player_locations(player)):
- return True
return False # if no winning combinations was found- return False # if no winning combinations were found
- def _get_player_locations(self, player):
- return [index for index, marker in enumerate(self.current_board) if marker == self.player_markers[player]]
- @staticmethod
- def _get_next_move():
- while True:
chosen_location = input("Cross location(choose 1 - 9):> ")if not chosen_location.isdigit() or int(chosen_location) not in range(10):- chosen_location = input("Cross location (choose 1 - 9):
- > ")
- if not chosen_location.isdigit() or int(chosen_location) not in range(1, 10):
- print('>>> Invalid input!')
- continue
- else:
- chosen_location = int(chosen_location) - 1 # adjust for array index to start at 0 not 1
- return chosen_location
- if __name__ == '__main__':
- NoughtsAndCrosses().play()