Last active
April 22, 2020 07:17
-
-
Save wadefletch/d709e6468b5c5449198b4df55e0d8bb9 to your computer and use it in GitHub Desktop.
tic-tac-toe.py
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
# TODO maybe reimplement with curses? | |
import random | |
import time | |
from typing import List, Union | |
class Board: | |
def __init__(self, size=3, player_char='\033[92mX\033[0m', computer_char='\033[91mO\033[0m'): | |
self.size = size | |
self.array = self.get_board(self.size) | |
self.player_char = player_char | |
self.computer_char = computer_char | |
@staticmethod | |
def get_board(size: int) -> List[str]: | |
return [' ' for _ in range(size ** 2)] | |
def move(self, player: str, square: int): | |
# square filled | |
if self.array[square - 1] != ' ': | |
return False | |
self.array[square - 1] = self.player_char if player == 'player' else self.computer_char | |
return True | |
@property | |
def winner(self) -> Union[str, None]: | |
# horizontal row | |
for y in range(0, self.size ** 2, self.size): | |
if all([self.array[x] == self.player_char for x in range(y, y + self.size, 1)]): | |
return 'Player' | |
if all([self.array[x] == self.computer_char for x in range(y, y + self.size, 1)]): | |
return 'Computer' | |
# vertical row | |
for y in range(self.size): | |
if all([self.array[x] == self.player_char for x in range(y, self.size ** 2, self.size)]): | |
return 'Player' | |
if all([self.array[x] == self.computer_char for x in range(y, self.size ** 2, self.size)]): | |
return 'Computer' | |
# top left to bottom right diagonal | |
if all([self.array[x] == self.player_char for x in range(0, self.size ** 2, self.size + 1)]): | |
return 'Player' | |
if all([self.array[x] == self.computer_char for x in range(0, self.size ** 2, self.size + 1)]): | |
return 'Computer' | |
# top right to bottom left diagonal | |
if all([self.array[x] == self.player_char for x in range(self.size - 1, self.size ** 2 - 1, self.size - 1)]): | |
return 'Player' | |
if all([self.array[x] == self.computer_char for x in [0]]): | |
return 'Computer' | |
return None | |
def show(self, numbers=False): | |
"""Nicely print the board.""" | |
number = 1 | |
print('tic-tac-toe // by \033[1m\033[94m@wadefletch\033[0m') | |
print() | |
print('----' * self.size + '-') | |
for row in range(0, self.size ** 2, self.size): | |
print('| ', end='') | |
for q in range(row, row + self.size, 1): | |
if self.array[q] == ' ' and numbers: | |
print(number, end=' | ') | |
else: | |
print(self.array[q], end=' | ') | |
number += 1 | |
print() | |
print('----' * self.size + '-') | |
print() | |
def possible_moves(self): | |
return [x for x in range(len(self.array)) if self.array[x] == ' '] | |
def get_random_valid_move(self): | |
return random.choice(self.possible_moves()) + 1 | |
def clear_term(): | |
print('\x1b[2j\033c\x1bc') | |
if __name__ in '__main__': | |
b = Board(3) | |
while not b.winner: | |
clear_term() | |
b.show(numbers=True) | |
move = input('Player move? (q to quit): ') | |
if move == 'q': | |
exit(0) | |
b.move('player', int(move)) | |
clear_term() | |
b.show(numbers=True) | |
print('Computer thinking (simulated)...') | |
time.sleep(random.random()*2) | |
b.move('computer', b.get_random_valid_move()) | |
clear_term() | |
b.show() | |
print(f'Winner: {b.winner}!') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment