summaryrefslogtreecommitdiff
path: root/tictactoe.py
diff options
context:
space:
mode:
authorroot <root@annapurna.annapurna.fitness>2025-07-09 15:24:51 +0200
committerroot <root@annapurna.annapurna.fitness>2025-07-09 15:24:51 +0200
commitd475ede435018fc0a9289b1396c6891b7b22c72d (patch)
tree8360b88861a966f768be6df5645ca092ad3e8ca6 /tictactoe.py
initial commitHEADmaster
Diffstat (limited to 'tictactoe.py')
-rw-r--r--tictactoe.py131
1 files changed, 131 insertions, 0 deletions
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