From d475ede435018fc0a9289b1396c6891b7b22c72d Mon Sep 17 00:00:00 2001 From: root Date: Wed, 9 Jul 2025 15:24:51 +0200 Subject: initial commit --- tictactoe.py | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 tictactoe.py (limited to 'tictactoe.py') diff --git a/tictactoe.py b/tictactoe.py new file mode 100644 index 0000000..f6b2c70 --- /dev/null +++ b/tictactoe.py @@ -0,0 +1,131 @@ +import random + +board = ['1', '2', '3', '4', '5', '6', '7', '8', '9'] +wincombs = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6)) +player1 = 'x' +player2 = 'o' + +def render(board): + print(f''' + {board[0]} │ {board[1]} │ {board[2]} +───┼───┼─── + {board[3]} │ {board[4]} │ {board[5]} +───┼───┼─── + {board[6]} │ {board[7]} │ {board[8]}''') + +def evaluate(board): + for wincomb in wincombs: + if board[wincomb[0]] == board[wincomb[1]] == board[wincomb[2]] == player1: + return 1 + if board[wincomb[0]] == board[wincomb[1]] == board[wincomb[2]] == player2: + return -1 + if all(cell in {player1, player2} for cell in board): + return 0 + +def askmove(board): + for _ in range(3): # 3 attempts + userinput = input('\nWhere do you want to place your x? > ') + if userinput in {'1', '2', '3', '4', '5', '6', '7', '8', '9'}: + idx = int(userinput) - 1 + if board[idx] not in {player1, player2}: + return idx + print('\nInvalid input') + return askmove(board) + exit(0) + +def emptycells(board): + for cell in board: + if cell not in {player1, player2}: + yield cell + +def checkposition(board): + eval = evaluate(board) + if eval is not None: + render(board) + if eval == 0: + print('\nDRAW\n') + if eval == 1: + print(f'\n{player1} won the game!\n') + if eval == -1: + print(f'\n{player2} won the game!\n') + exit(0) + +def minimax(board, ismax, alpha = -float('inf'), beta = float('inf')): + + eval = evaluate(board) + if eval is not None: + return eval + + if ismax: + bestvalue = -float('inf') + for cell in emptycells(board): + idx = int(cell) - 1 + board[idx] = player1 + minimaxvalue = minimax(board, False, alpha, beta) + board[idx] = cell + if minimaxvalue > bestvalue: + bestvalue = minimaxvalue + alpha = max(alpha, bestvalue) + if alpha >= beta: + break + else: + bestvalue = float('inf') + for cell in emptycells(board): + idx = int(cell) - 1 + board[idx] = player2 + minimaxvalue = minimax(board, True, alpha, beta) + board[idx] = cell + if minimaxvalue < bestvalue: + bestvalue = minimaxvalue + beta = min(beta, bestvalue) + if alpha >= beta: + break + return bestvalue + +def bestmoves(board, ismax): + bestmovelist = [] + if ismax: + bestvalue = -float('inf') + for cell in emptycells(board): + idx = int(cell) - 1 + board[idx] = player1 + minimaxvalue = minimax(board, False) + board[idx] = cell + if minimaxvalue == bestvalue: + bestmovelist.append(cell) + elif minimaxvalue > bestvalue: + bestvalue = minimaxvalue + bestmovelist = [cell] + else: + bestvalue = float('inf') + for cell in emptycells(board): + idx = int(cell) - 1 + board[idx] = player2 + minimaxvalue = minimax(board, True) + board[idx] = cell + if minimaxvalue == bestvalue: + bestmovelist.append(cell) + elif minimaxvalue < bestvalue: + bestvalue = minimaxvalue + bestmovelist = [cell] + return bestmovelist + +import time + +if __name__ == '__main__': + while True: + starttime = time.time() + bestmoves_list = bestmoves(board, False) + computermove = random.choice(bestmoves_list) + exectime = time.time() - starttime + print('exectime >', exectime) + input() + render(board) + usermove = askmove(board) + board[usermove] = player1 + checkposition(board) + bestmoves_list = bestmoves(board, False) + computermove = random.choice(bestmoves_list) + idx = int(computermove) - 1 + board[idx] = player2 + checkposition(board) \ No newline at end of file -- cgit v1.2.3