Skip to content

Instantly share code, notes, and snippets.

@ig0r-ferreira
Last active June 21, 2023 00:46
Show Gist options
  • Save ig0r-ferreira/0de8b2eff41372338f612398309fce90 to your computer and use it in GitHub Desktop.
Save ig0r-ferreira/0de8b2eff41372338f612398309fce90 to your computer and use it in GitHub Desktop.
Tic Tac Toe CLI game
import time
import random
ALIGN = 30
DIRECTIONS = [
[(1, 1), (2, 2), (3, 3)],
[(1, 3), (2, 2), (3, 1)],
[(1, 1), (1, 2), (1, 3)],
[(2, 1), (2, 2), (2, 3)],
[(3, 1), (3, 2), (3, 3)],
[(1, 1), (2, 1), (3, 1)],
[(1, 2), (2, 2), (3, 2)],
[(1, 3), (2, 3), (3, 3)],
]
def clear_console():
print("\033[H\033[J", end="")
def print_error(error):
print(f'\033[1;31m{error}\033[m')
def read_int(prompt):
while True:
try:
user_input = int(input(prompt).strip())
except ValueError:
print_error('Invalid input. Enter an integer.')
else:
if 4 > user_input > 0:
return user_input
print_error('Invalid input. Choose only 1, 2 or 3.')
def has_winner(player, game_board):
hit_sequence = player * 3
return any(
''.join(map(game_board.get, direction)) == hit_sequence
for direction in DIRECTIONS
)
def get_opponent(player):
return 'X' if player != 'X' else 'O'
def get_cpu_reaction(human_player, game_board):
cpu = get_opponent(human_player)
empty_positions = []
for direction in DIRECTIONS:
areas = list(map(game_board.get, direction))
if ' ' not in areas:
continue
if areas.count(cpu) == 2 or areas.count(human_player) == 2:
return direction[areas.index(' ')]
else:
empty_positions.append(direction[areas.index(' ')])
else:
return random.choice(empty_positions)
def read_human_symbol():
while True:
player = input('Will you be X or O? ').strip().upper()
if player in ('X', 'O'):
return player
print_error('You must choose X or O. Please try again.')
def read_player_move(game_board):
print()
while True:
row = read_int('Enter a row number: ')
column = read_int('Enter a columm number: ')
if game_board[row, column].isspace():
return row, column
print_error(
'A move has already been made to this position. Try another.'
)
def make_game_board():
return dict.fromkeys(
((x, y) for x in range(1, 4) for y in range(1, 4)), ' '
)
def show_game_board(table):
game_board = f"""
| |
{table[1, 1]} | {table[1, 2]} | {table[1, 3]}
______|_______|_______
| |
{table[2, 1]} | {table[2, 2]} | {table[2, 3]}
______|_______|_______
| |
{table[3, 1]} | {table[3, 2]} | {table[3, 3]}
| |
"""
print(game_board)
def mainloop(human_player, game_board):
current_player = human_player
moves = []
show_game_board(game_board)
while len(moves) < 9:
print(f'{current_player} plays now'.center(ALIGN))
if current_player == human_player:
position = read_player_move(game_board)
else:
time.sleep(1.5)
position = get_cpu_reaction(human_player, game_board)
game_board[position] = current_player
moves.append(position)
clear_console()
show_game_board(game_board)
if has_winner(current_player, game_board):
print(f'Player {current_player} wins!'.center(ALIGN))
break
current_player = get_opponent(current_player)
else:
print('Nobody won, game over.'.center(ALIGN))
def start_game():
clear_console()
print('Welcome a Tic Tack Toe game!\n')
mainloop(read_human_symbol(), make_game_board())
if __name__ == '__main__':
try:
start_game()
except KeyboardInterrupt:
print('\nGame interrupted.')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment