how to use numpy to shorten tic-tac-toe check

60 Views Asked by At

how to use numpy to shorten my code where i check if you win or not

i need to find a way to use numpy to fit into my code because its very long and hard. i check diag, horizontle and row but i need to find a way to shorten it with numpy

def checkHorizontle(board):
    global winner
    if board[0] == board[1] == board[2] and board[1] != "-":
        winner = board[0]
        return True
    elif board[3] == board[4] == board[5] and board[3] != "-":
        winner = board[3]
        return True
    elif board[6] == board[7] == board[8] and board[6] != "-":
        winner = board[6]
        return True

    
def checkRow(board):
    global winner
    if board[0] == board[3] == board[6] and board[0] != "-":
        winner = board[0]
        return True
    elif board[1] == board[4] == board[7] and board[1] != "-":
        winner = board[1]
        return True
    elif board[2] == board[5] == board[8] and board[2] != "-":
        winner = board[2]
        return True


def checkDiag(Board):
    global winner
    if board[0] == board[4] == board[8] and board[0] != "-":
        winner = board[0]
        return True
    elif board[2] == board[4] == board[6] and board[2] != "-":
        winner = board[2]
        return True

when i tried to find a sulution my mind just decided to quit. i know you could youe the magic square to find it and the numpy multiply fuction but i dont know how to

3

There are 3 best solutions below

0
Caridorc On

There is no need for numpy, you can use a simple loop:

WINNING_TRIPLETS = [ (0, 1, 2), (3, 4, 5), ...] # add all of them

for square1, square2, square3 in WINNING_TRIPLETS:
    if ...: # same logic as in your code, but only once with square1, square2, square3
2
mozway On

Assuming a board of this kind and wanting to check if X won:

board = np.array([['X', 'O', np.nan],
                  ['O', 'X', np.nan],
                  ['X', 'X', 'X']])

You can use 4 tests for rows, columns, and diagonals:

# check if any row is won
(board == 'X').all(axis=1).any()

# check if any column is won
(board == 'X').all(axis=0).any()

# check diagonals
diag1 = np.diagonal(board)
diag2 = np.diagonal(np.fliplr(board))
(diag1 == 'X').all() or (diag2 == 'X').all()

Use in a test:

if ((board == 'X').all(axis=1).any() 
   or (board == 'X').all(axis=0).any()
   or (np.diagonal(board) == 'X').all()
   or (np.diagonal(np.fliplr(board)) == 'X').all()
   ):
    print('X won')

If you want to check if any player won:

# check if any row is won
(board[0] == board[1:]).all(0).any()

# check if any column is won
(board[:, [0]] == board[:, 1:]).all(1).any()

# check diagonals
diag1 = np.diagonal(board)
diag2 = np.diagonal(np.fliplr(board))
(diag1[0] == diag1[1:]).all() or (diag2[0] == diag2[1:]).all()
0
trincot On

its very long and hard. ... i need to find a way to shorten it with numpy

If getting it short is your goal, you don't necessarily need numpy. Another idea is to represent the board as a string of nine characters (each is either "X", "O" or "."), and use a regex to test for a win.

That regex could be:

(\w)(\1\1(...)*$|..\1..\1|...\1...\1|.\1.\1..$)

An example implementation:

import re

class TicTacToe:
    def __init__(self):
        self.board = "........."

    def play(self, i):
        self.board = self.board[:i] + self.player() + self.board[i+1:]

    def player(self):
        return "OX"[self.board.count(".") % 2]

    def isdraw(self):
        return "." not in self.board
    
    def iswon(self):
        return bool(re.search(r"(\w)(\1\1(...)*$|..\1..\1|...\1...\1|.\1.\1..$)", self.board))
    
    def __repr__(self):
        return "\n".join(" ".join(self.board[i:i+3]) for i in range(0, 9, 3))

# demo
game = TicTacToe()
for move in 0, 4, 8, 2, 6, 3, 7:
    game.play(move)
print(game)
print("draw?", game.isdraw())
print("win?", game.iswon())