Last active
July 5, 2021 02:49
-
-
Save raheelrjunaid/925f61a541c872184c7c0497c300031a to your computer and use it in GitHub Desktop.
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 by Raheel Junaid | |
# Date Finished: July 4th | |
# Full YouTube Series: https://youtube.com/playlist?list=PL3ZaFz0_yUh4KSXM8qXyPjxr_j5uxcG4E | |
# This Version is commented | |
from random import randint | |
class Game: | |
def __init__(self) -> None: | |
self.board = [[None for i in range(3)] for i in range(3)] # Generate empty board | |
def display_board(self, numbers=None): | |
# Determine which (if any) numbers to show | |
# Compact two conditionals in one (pep8 column restriction) | |
show_numbers_x = True if numbers == 'x' or numbers == 'both' else False | |
show_numbers_y = True if numbers == 'y' or numbers == 'both' else False | |
for row_count, row in enumerate(self.board): | |
# Print line seperator for every row | |
if row_count != 0: | |
print(f'\n {"-" * 10}') | |
for col_count, col in enumerate(row): | |
# Show the numbers on the left if requested | |
if col_count == 0 and show_numbers_x: | |
print(str(row_count + 1), ' ', end="") | |
elif col_count == 0: | |
print(' ', end="") | |
# None values are symbolic, reassign to empty space | |
col = ' ' if col is None else col | |
print(col, end="") | |
# Add a divider between the first two columns | |
if col_count != 2: | |
print(" | ", end="") | |
# The last row should show a new line | |
if row_count == 2: | |
if show_numbers_y: # Show properly spaced numbers if requested | |
print("\n\n 1 2 3", end="") | |
print('\n') | |
def place_piece(self, piece, x_pos, y_pos): | |
self.board[x_pos][y_pos] = piece | |
# Determine if all elements in a given list are equal | |
all_equal = lambda iterable: iterable.count(iterable[0]) == len(iterable) | |
# Return a list of all pieces on the board | |
def all_pieces(board): | |
all_pieces = list() | |
for row in range(3): | |
for column in range(3): | |
all_pieces.append(board[row][column]) | |
return all_pieces | |
# Check whether a certain axis (or diagonal) has the same pieces) | |
def check_win(board): | |
# Check for a tie | |
if all(all_pieces(game.board)): | |
return 'tie' | |
# Check all rows | |
for row in board: | |
if all_equal(row) and all(row): | |
return 'win' | |
# Check all columns | |
for i in range(3): | |
column = [board[0][i], board[1][i], board[2][i]] | |
if all_equal(column) and all(column): | |
return 'win' | |
# Check both diagonals | |
tl_br = [board[0][0], board[1][1], board[2][2]] | |
tr_bl = [board[0][2], board[1][1], board[2][0]] | |
for cross in [tl_br, tr_bl]: | |
if all_equal(cross) and all(cross): | |
return 'win' | |
# Return if the game is still playable | |
return False | |
def play(piece): | |
print(f"{piece.upper()}'s turn.") | |
# O is always computers move | |
if piece == 'o': | |
move = computerMove(game.board) | |
game.place_piece('o', move[0], move[1]) | |
else: | |
# Accept coordinates for piece placement | |
game.display_board(numbers='y') | |
y_pos = int(input("Choose Y Position: ")) - 1 | |
game.display_board(numbers='x') | |
x_pos = int(input("Choose X Position: ")) - 1 | |
# Ensure the location isn't already occupied | |
if game.board[x_pos][y_pos] == None: | |
game.place_piece(piece, x_pos, y_pos) | |
else: | |
print("A piece is already there, please try again.") | |
play(piece) | |
def computerMove(board): | |
# Test whether there could be a winner | |
# Check every unoccupied column | |
for row_count, row in enumerate(board): | |
for col_count, column in enumerate(row): | |
if column == None: | |
# Toggle between both players to see if someone is going to win | |
for piece in ['x', 'o']: | |
board[row_count][col_count] = piece | |
if check_win(board) == 'win': | |
# Place a piece in that position if a winner is possible | |
return row_count, col_count | |
board[row_count][col_count] = None | |
# Random Move | |
random_move = [randint(0, 2), randint(0, 2)] | |
# Check if the random location is occupied | |
while board[random_move[0]][random_move[1]] != None: | |
random_move = [randint(0,2), randint(0, 2)] | |
return random_move | |
# Main program (very little error-handling) | |
game = Game() | |
while True: | |
for piece in ['x', 'o']: # Take turns playing the game | |
play(piece) | |
result = check_win(game.board) | |
if result == 'win' or result == 'tie': | |
game.display_board() | |
# Print line seperator | |
print('-' * 20) | |
if result == 'win': | |
print(piece.upper(), 'WINS!') | |
else: | |
print('Tie') | |
print('-' * 20) | |
restart = input('Play again [y/n]? ') | |
if restart.lower() == 'n': | |
break | |
game = Game() # Empty the board |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment