tic-tac-toe-rl/game.py
2021-05-17 00:50:03 +02:00

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)