119 lines
3 KiB
Python
119 lines
3 KiB
Python
# implement a simple text based tic-tac-toe game
|
|
import numpy as np
|
|
|
|
class TicTacToe():
|
|
|
|
def __init__(self, size=(3,3)):
|
|
self.size = size
|
|
self.board = np.zeros(size, dtype=int)
|
|
self.player = 1 # the player whoes turn it is to play
|
|
self.winner = 0 # the winner, 0 for draw
|
|
self.done = 0 # if the game is done or not
|
|
self.turn = 0 # the current turn, maximum is 9
|
|
|
|
def input_is_valid(self, move):
|
|
"""
|
|
Check if the move one of the the players want to take is a valid move in
|
|
the current situation.
|
|
|
|
The move is valid if there is nothing where the player want to draw and
|
|
if the move is inside the grid.
|
|
"""
|
|
|
|
# todo catch error if out of bounds
|
|
unraveled_index = np.unravel_index(move, self.size)
|
|
|
|
if self.board[unraveled_index] == 0:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def update_board(self, move):
|
|
"""
|
|
Update board if move is valid
|
|
"""
|
|
|
|
if self.input_is_valid(move):
|
|
unraveled_index = np.unravel_index(move, self.size)
|
|
self.board[unraveled_index] = self.player
|
|
|
|
# change player
|
|
self.player = 3 - self.player
|
|
|
|
# update turn counter
|
|
self.turn += 1
|
|
|
|
def check_win(self):
|
|
"""
|
|
Check if the current board is in a winning position.
|
|
Return 0 if it is not and the player id (1 or 2) if it is.
|
|
"""
|
|
|
|
# impossible to win in less than 5 moves
|
|
if self.turn < 5:
|
|
return 0
|
|
|
|
# check rows
|
|
rows = self.board
|
|
for r in rows:
|
|
if (r == 1).all():
|
|
self.winner = 1
|
|
if (r == 2).all():
|
|
self.winner = 2
|
|
|
|
# check columns
|
|
columns = self.board.T
|
|
for c in columns:
|
|
if (c == 1).all():
|
|
self.winner = 1
|
|
if (c == 2).all():
|
|
self.winner = 2
|
|
|
|
# check diagonals
|
|
diagonals = [self.board.diagonal(), np.fliplr(self.board).diagonal()]
|
|
for d in diagonals:
|
|
if (d == 1).all():
|
|
self.winner = 1
|
|
if (d == 2).all():
|
|
self.winner = 2
|
|
|
|
# handle draw
|
|
if self.turn == 9:
|
|
self.done = 1
|
|
|
|
# if someone won
|
|
if self.winner != 0:
|
|
self.done = 1
|
|
|
|
# if no winning conidition has been found
|
|
return self.winner
|
|
|
|
def display_board(self):
|
|
"""
|
|
Display a humanly readable board.
|
|
|
|
Example:
|
|
+---+---+---+
|
|
| X | O | |
|
|
+---+---+---+
|
|
| O | X | |
|
|
+---+---+---+
|
|
| X | | O |
|
|
+---+---+---+
|
|
"""
|
|
|
|
line_decorator = "+---+---+---+"
|
|
board_decorator = "| {} | {} | {} |"
|
|
|
|
convert = {0: " ", 1: "X", 2: "O"}
|
|
|
|
for r in self.board:
|
|
print(line_decorator)
|
|
|
|
L = []
|
|
for i in r:
|
|
L.append(convert[i])
|
|
|
|
print(board_decorator.format(*L))
|
|
|
|
print(line_decorator)
|