Last active
October 14, 2021 07:18
-
-
Save SyntaxError843/08f52a20c355dbc31351a3db6ce2245d to your computer and use it in GitHub Desktop.
TicTacToe
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
# Tic Tac Toe | |
import os; | |
import random; | |
import time; | |
# Initialize player vs bot mode [Make true to play against a very stupid bot] | |
is_pve = True; | |
# Initialize rows count | |
rows_count = 3; | |
# Initialize cells per row count | |
cells_per_row = 3; | |
# Initialize board | |
board = [ str(x) for x in range( 1, (rows_count * cells_per_row + 1) ) ]; | |
# Initialize players | |
players = [ | |
'X', | |
'O', | |
]; | |
# Initialize current player | |
current_player = players[0]; | |
# Initialize bot player [bot is player 'O'] | |
bot_player = players[1]; | |
# Register a move on the board | |
def board_make_move( position:str ) : | |
# Get list of available spaces | |
available_spaces = [ x for x in board if x.isdigit() ]; | |
# Check if the position is available on the board | |
if ( position in available_spaces ) : | |
board[ int(position) - 1 ] = current_player; | |
return True; | |
else : | |
return False; | |
# Bot AI | |
def bot_bust_a_move() : | |
# Flag to check if bot already made a move | |
bot_already_made_move = False; | |
# Get opponenet player | |
opponent_player = players[ 0 if bot_player == players[1] else 1 ]; | |
# Get list of available spaces | |
available_spaces = [ x for x in board if x.isdigit() ]; | |
# Get list of preferred spaces | |
preferred_spaces = [ '1', '3', '5', '7', '9' ]; | |
# If the player is about to win attempt to stop them | |
# And if the bot is about to win then tell it | |
# In Rows | |
for i in range( rows_count ) : | |
current_row = board[ (i*3):(i*3+3) ]; | |
if ( len( [ x for x in current_row if x == opponent_player ] ) == 2 and not bot_already_made_move ) : | |
bot_already_made_move = board_make_move( [ x for x in current_row if x != opponent_player ][0] ); | |
elif ( len( [ x for x in current_row if x == bot_player ] ) == 2 and not bot_already_made_move ) : | |
bot_already_made_move = board_make_move( [ x for x in current_row if x != bot_player ][0] ); | |
# In Columns | |
for i in range( cells_per_row ) : | |
current_column = [ board[i], board[i+3], board[i+6] ]; | |
if ( len( [ x for x in current_column if x == opponent_player ] ) == 2 and not bot_already_made_move ) : | |
bot_already_made_move = board_make_move( [ x for x in current_column if x != opponent_player ][0] ); | |
elif ( len( [ x for x in current_column if x == bot_player ] ) == 2 and not bot_already_made_move ) : | |
bot_already_made_move = board_make_move( [ x for x in current_column if x != bot_player ][0] ); | |
# Diagonals | |
first_diagonal = [ board[0], board[4], board[8] ]; | |
second_diagonal = [ board[2], board[4], board[6] ]; | |
for diagonal in [ first_diagonal, second_diagonal ] : | |
if ( len( [ x for x in diagonal if x == opponent_player ] ) == 2 and not bot_already_made_move ) : | |
bot_already_made_move = board_make_move( [ x for x in diagonal if x != opponent_player ][0] ); | |
elif ( len( [ x for x in diagonal if x == bot_player ] ) == 2 and not bot_already_made_move ) : | |
bot_already_made_move = board_make_move( [ x for x in diagonal if x != bot_player ][0] ); | |
# Next if the player isn't about to win then check if a preferred space is available | |
if not bot_already_made_move : | |
# Priorities the middle spot | |
if ( '5' in available_spaces ) : bot_already_made_move = board_make_move( '5' ); | |
# Otherwise pick a preferred spot randomly | |
else : bot_already_made_move = board_make_move( preferred_spaces[ random.randint(0, len(preferred_spaces)-1) ] ); | |
# Lastly if the bot still haven't made a move yet then make one randomly | |
if not bot_already_made_move : bot_already_made_move = board_make_move( available_spaces[ random.randint(0, len(available_spaces)-1) ] ); | |
# Method to check if it's the bots turn | |
def is_bot_turn() : | |
return is_pve and current_player == bot_player; | |
# Function to clear console | |
clear_console = lambda: os.system('cls' if os.name in ('nt', 'dos') else 'clear'); | |
# Function to switch between players | |
def switch_player() : | |
global current_player; | |
current_player = players[ 1 if players.index( current_player ) == 0 else 0 ]; | |
# Method to print title | |
def print_title() : | |
print( '-'*5 + ' TIC TAC TOE ' + '-'*5 + '\n' ); | |
# Function to draw board | |
def draw_board() : | |
# Loop through rows | |
for row in range( rows_count ) : | |
# Print a whitespace at the beginning of the line | |
print( ' ', end='' ); | |
# Loop through cells | |
for cell in range( cells_per_row ) : | |
# print cell with right border if cell is not the last one | |
print( board[ cell + ( row * cells_per_row ) ] + ( ' | ' if cell < (cells_per_row - 1) else '' ), end='' ); | |
# At the end of a row print a line of separators | |
# If the row is not the last one | |
# Otherwise print new line | |
if ( row < ( rows_count - 1 ) ) : print( '\n' + '-'*(3 * cells_per_row + (cells_per_row-1)) ); | |
else : print( '\n' ); | |
# Display results | |
def print_results() : | |
# Initialize display text | |
display_text = ''; | |
# Initialize bot text | |
bot_text = ' [BOT]' if is_bot_turn() else ''; | |
# If the game is over then display winner | |
if ( is_game_over() == True ) : | |
display_text = f'\'{current_player}\'{bot_text} Has Won!'; | |
# Check if game is tied | |
elif ( is_game_over() == 'tie' ) : | |
display_text = 'TIE!'; | |
# Otherwise show current player | |
else : display_text = f'Current Player: \'{current_player}\'{bot_text}'; | |
print( display_text + '\n' ); | |
# Get user input | |
def get_user_input() : | |
# Check if it's the bots' turn | |
if not is_bot_turn() : | |
# Get user input | |
user_input = input( 'Input a position on the board: ' ); | |
# Validate user input and register move | |
while( not board_make_move( user_input ) ) : | |
user_input = input( 'Please enter a number that is on the board: ' ); | |
else : | |
# Update the board for the bot with a delay | |
print( 'The bot is thinking (he\'s very stupid)...' ); | |
time.sleep(1); | |
bot_bust_a_move(); | |
# Switch current player if game is not over | |
if not is_game_over() : switch_player(); | |
# Method to determine is game is over | |
def is_game_over() : | |
# Initialize game over flag | |
is_game_over = False; | |
# A TicTacToe game is completed when a player symbol is | |
# Place on three aligning spaces on the board whether | |
# Horizontally, Vertically, Or Diagonally | |
if ( | |
all( symbol == board[0] for symbol in board[ :3 ] ) | |
or all( symbol == board[3] for symbol in board[ 3:6 ] ) | |
or all( symbol == board[6] for symbol in board[ 6:9 ] ) | |
or ( | |
( board[0] == board[3] and board[0] == board[6] ) | |
or ( board[1] == board[4] and board[1] == board[7] ) | |
or ( board[2] == board[5] and board[2] == board[8] ) | |
) | |
or ( | |
( board[0] == board[4] and board[0] == board[8] ) | |
or ( board[2] == board[4] and board[2] == board[6] ) | |
) | |
) : is_game_over = True; | |
else : | |
# Check if game is tied | |
is_game_over = 'tie' if all( symbol.isalpha() for symbol in board ) else False; | |
return is_game_over; | |
# Method to display game interface | |
def start_game() : | |
while ( True ) : | |
# Clear console | |
clear_console(); | |
# Display title | |
print_title(); | |
# Draw the board with results | |
draw_board(); | |
# Display results | |
print_results(); | |
# Get user input if game is not over yet | |
if ( not is_game_over() ) : | |
# Get user input | |
get_user_input(); | |
else : | |
# Break if the game is over | |
break; | |
# Start game | |
start_game(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment