From 2e80090e1f8f7201fa61ba7d8b2cd9ea3ceeec0c Mon Sep 17 00:00:00 2001 From: speedybits Date: Sun, 3 Jan 2021 12:58:13 -0600 Subject: [PATCH] Support variable BOARD_ROWS & BOARD_COLS Modified code to support variable BOARD_ROWS and BOARD_COLS. If BOARD_ROWS!=BOARD_COLS then a win is from one side of the rectangle to the other. To get the AI to work, had to add 'savePolicy()' to the end of 'play'. --- .gitignore | 13 ++++++- TicTacToe/ticTacToe.py | 77 ++++++++++++++++++++++++++++-------------- 2 files changed, 64 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index 17c4683..826e396 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,15 @@ .idea */.ipynb_checkpoints .ipynb_checkpoints -*/__pycache__ \ No newline at end of file +*/__pycache__ +TicTacToe/.ticTacToe.py.un~ +TicTacToe/ticTacToe.py~ +TicTacToe/.ticTacToe.py.swp +TicTacToe/policy_p1 +TicTacToe/policy_p2 +TicTacToe/policy_p2 +TicTacToe/policy_p1 +TicTacToe/policy_p1 +TicTacToe/policy_p2 +TicTacToe/policy_p1 +TicTacToe/policy_p2 diff --git a/TicTacToe/ticTacToe.py b/TicTacToe/ticTacToe.py index 5e18039..c3cb5db 100644 --- a/TicTacToe/ticTacToe.py +++ b/TicTacToe/ticTacToe.py @@ -3,7 +3,12 @@ BOARD_ROWS = 3 BOARD_COLS = 3 - +NUM_DIAG = abs(BOARD_ROWS-BOARD_COLS)+1 +if (BOARD_ROWS < BOARD_COLS): + WINNING_COUNT_DIAG = BOARD_ROWS +else: + WINNING_COUNT_DIAG = BOARD_COLS + class State: def __init__(self, p1, p2): @@ -23,30 +28,45 @@ def getHash(self): def winner(self): # row for i in range(BOARD_ROWS): - if sum(self.board[i, :]) == 3: + if sum(self.board[i, :]) == BOARD_COLS: self.isEnd = True return 1 - if sum(self.board[i, :]) == -3: + if sum(self.board[i, :]) == (-1 * BOARD_COLS): self.isEnd = True return -1 # col for i in range(BOARD_COLS): - if sum(self.board[:, i]) == 3: + if sum(self.board[:, i]) == BOARD_ROWS: self.isEnd = True return 1 - if sum(self.board[:, i]) == -3: + if sum(self.board[:, i]) == (-1 * BOARD_ROWS): self.isEnd = True return -1 - # diagonal - diag_sum1 = sum([self.board[i, i] for i in range(BOARD_COLS)]) - diag_sum2 = sum([self.board[i, BOARD_COLS - i - 1] for i in range(BOARD_COLS)]) - diag_sum = max(abs(diag_sum1), abs(diag_sum2)) - if diag_sum == 3: + + # diag + for i in range(NUM_DIAG): + if (BOARD_ROWS < BOARD_COLS): + # \ Diagonals + # i selects offset from first diagonal + diag_sum1 = np.trace(self.board,i) + # / Diagonals + # Flip board so that we can calculate diagonals in other direction + diag_sum2 = np.trace((np.fliplr(self.board)),i) + else: + # / Diagonals + # Rotate 90 first, so that \ becomes / + # Note: In this case, offset 'i' starts from rightmost diagonal + diag_sum1 = np.trace((np.rot90(self.board)),i) + # \ Diagonals + # In this case we need to flip and then rotate! + diag_sum2 = np.trace((np.rot90(np.fliplr(self.board))),i) + + if ((diag_sum1==WINNING_COUNT_DIAG) or (diag_sum2==WINNING_COUNT_DIAG)): self.isEnd = True - if diag_sum1 == 3 or diag_sum2 == 3: - return 1 - else: - return -1 + return 1 + elif (diag_sum1==(-1 * WINNING_COUNT_DIAG) or (diag_sum2==(-1 * WINNING_COUNT_DIAG))): + self.isEnd = True + return -1 # tie # no available positions @@ -132,6 +152,8 @@ def play(self, rounds=100): self.p2.reset() self.reset() break + self.p1.savePolicy() + self.p2.savePolicy() # play with human def play2(self): @@ -170,19 +192,24 @@ def play2(self): def showBoard(self): # p1: x p2: o - for i in range(0, BOARD_ROWS): - print('-------------') + for i in range(0, (BOARD_ROWS+1)): out = '| ' for j in range(0, BOARD_COLS): - if self.board[i, j] == 1: - token = 'x' - if self.board[i, j] == -1: - token = 'o' - if self.board[i, j] == 0: - token = ' ' - out += token + ' | ' - print(out) - print('-------------') + print ('-', end='') + if (j==(BOARD_COLS-1)): + print ('----') + else: + print('---', end='') + if (i