Created
April 27, 2019 02:16
-
-
Save robinovitch61/871ad66641811d16bcc2a7f49b5e6050 to your computer and use it in GitHub Desktop.
RecurseTacToe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# IDEAS FOR COMPUTERIZED OPPONENT: | |
# [] Add prompt for 1 Player or 2 Player at start of game | |
# [] Based on number of players, override player selection with random computer selection | |
# [] Once random selection is working, add more intelligent computer selection (some ideas): | |
# * If computer could win game, it should win game | |
# * If computer can put board in state where next move it could win game, it should do that move | |
# * If computer can put board in state where next move it could win game REGARDLESS of human selection, do that move | |
# * Apply deep learning on millions of games of tic tac toe to become the ultimate RecurseTacToe algorithm (just kidding :D) | |
BOARD_TEMPLATE = ''' | |
{top_left} | {top_middle} | {top_right} | |
----------- | |
{middle_left} | {center} | {middle_right} | |
----------- | |
{bottom_left} | {bottom_middle} | {bottom_right} | |
''' | |
# Dictionary containing current state of the board | |
board_state = { | |
'top_left':' ', | |
'top_middle':' ', | |
'top_right':' ', | |
'middle_left':' ', | |
'center':' ', | |
'middle_right':' ', | |
'bottom_left':' ', | |
'bottom_middle':' ', | |
'bottom_right':' ', | |
} | |
# Define all the winning combinations | |
winning_combinations = ( | |
# left to rights | |
('top_left', 'top_middle', 'top_right'), | |
('middle_left', 'center', 'middle_right'), | |
('bottom_left', 'bottom_middle', 'bottom_right'), | |
# top to bottoms | |
('top_left', 'middle_left', 'bottom_left'), | |
('top_middle', 'center', 'bottom_middle'), | |
('top_right', 'middle_right', 'bottom_right'), | |
# diagonals | |
('top_left', 'center', 'bottom_right'), | |
('top_right', 'center', 'bottom_left'), | |
) | |
def get_player_symbols(): | |
"""Prompt for symbol selection. | |
Args: | |
None | |
Returns: | |
dict: mapping of player name ('Player 1' or 'Player 2') to symbol ('X' or 'O') | |
""" | |
p1_symbol = None | |
while p1_symbol not in ('X', 'O'): | |
p1_symbol = input("Player 1, type your symbol! X's or O's: ").upper() | |
if p1_symbol not in ('X', 'O'): | |
print("\nInvalid Choice: Please type either X's or O's.") | |
p2_symbol = 'O' if p1_symbol == 'X' else 'X' | |
print("Player 1 selected {}'s! That makes Player 2 {}'s.".format(p1_symbol, p2_symbol)) | |
player_dict = {'Player 1':p1_symbol, 'Player 2':p2_symbol} | |
return player_dict | |
def get_open_spots(): | |
"""Get the open spaces on the board given current board state. | |
Args: | |
None | |
Returns: | |
tuple: open space options | |
""" | |
return tuple([k.replace('_', ' ') for k,v in board_state.items() if v == ' ']) | |
def is_game_over(): | |
"""Check if game is over. | |
Args: | |
None | |
Returns: | |
bool: True if game over, False if game shall continue | |
""" | |
return not bool(len(get_open_spots())) | |
def won_game(): | |
"""Check if game has a winner. | |
Args: | |
None | |
Returns: | |
str or None: if winner exists, returns winner name ('Player 1' or 'Player 2') | |
else returns None | |
""" | |
for player, symbol in player_dict.items(): | |
for combination in winning_combinations: | |
if ( | |
board_state[combination[0]] == symbol | |
and board_state[combination[1]] == symbol | |
and board_state[combination[2]] == symbol | |
): | |
return player | |
return None | |
def play_turn(whos_turn): | |
"""Plays turn of tic tac toe and updates board_state. | |
Args: | |
whos_turn (str): name of player whos turn it is ('Player 1' or 'Player 2') | |
Returns: | |
None | |
""" | |
available = get_open_spots() | |
selection = None | |
while selection not in available: | |
current_board = BOARD_TEMPLATE.format(**board_state) | |
if len(available) == 1: | |
print('Last available option is {}!'.format(available[0])) | |
selection = available[0] | |
break | |
selection = input("\n{}'s turn ({}'s). Please type one of the following options:\n\n * {}\n{}\n{} ({}'s): ".format( | |
whos_turn, | |
player_dict[whos_turn], | |
'\n * '.join(available), | |
current_board, | |
whos_turn, | |
player_dict[whos_turn])).replace("'","") | |
if selection not in available: | |
print('Invalid or unavailable selection!') | |
board_state[selection.replace(' ', '_')] = player_dict[whos_turn] | |
print(BOARD_TEMPLATE.format(**board_state)) | |
return 'Player 2' if whos_turn == 'Player 1' else 'Player 1' | |
# Play game via command line | |
if __name__ == '__main__': | |
print('\n%%%%%%%%%%%%%%%%%%%%%%%%%%%') | |
print(' Welcome to RecurseTacToe! ') | |
print('%%%%%%%%%%%%%%%%%%%%%%%%%%%\n') | |
player_dict = get_player_symbols() | |
winner = None | |
whos_turn = 'Player 1' | |
while not is_game_over() and not winner: | |
whos_turn = play_turn(whos_turn) | |
winner = won_game() | |
if winner: | |
print("{} ({}'s) won! Nice job!".format(winner, player_dict[winner])) | |
else: | |
print("Tie game!") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment