Advertisement
SigmaBoy456

Python ConsoleApp AI Tictactoe minimax Algo (Fixed)

Mar 13th, 2025
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.64 KB | None | 0 0
  1. #Must Install The Lib Below:
  2. # 1 -> pip install pyfiglet
  3. # Lib
  4. from random import randint
  5. from math import inf
  6. from pyfiglet import figlet_format
  7. from os import system
  8. class tictactoe:
  9.     def __init__(self):
  10.         self.Board = [
  11.             [1, 2, 3],
  12.             [4, 5, 6],
  13.             [7, 8, 9]
  14.         ]
  15.         self.Player = None
  16.         self.AI = None
  17.         self.PrevPlayed = None
  18.         self.Turn = None
  19.         self.Diff = None
  20.     def DrawBoard(self):
  21.         print("-"*14)
  22.         for i in range(3):
  23.             print(f"| {self.Board[i][0]} | {self.Board[i][1]} | {self.Board[i][2]} | ")
  24.         print("-"*14)
  25.     def ChooseTeam(self):
  26.         while True:
  27.             n = input("Choose You Team (O or X) : ").upper()
  28.             vaildTeam = ["O", "X"]
  29.             if n not in vaildTeam:
  30.                 print("Invaild Team")
  31.                 continue
  32.             self.Player = n
  33.             self.AI = "O" if n == "X" else "X"
  34.             break
  35.     def SelectDiff(self):
  36.         while True:
  37.             n = input("Select You Diff for AI\ne: Easy\nm: Meduim\nh: Hard\ninput Here : ").lower()
  38.             vaildDiff = ["e", "m", "h"]
  39.             if n not in vaildDiff:
  40.                 print("Invaild Diff")
  41.                 continue
  42.             self.Diff = n
  43.             break
  44.     def StartTurn(self):
  45.         n = randint(1, 2)
  46.         self.Turn = self.Player if n == 1 else self.AI
  47.     def IsTie(self) -> bool:
  48.         return all([type(self.Board[i][j]) != int for i in range(3) for j in range(3)])
  49.     def IsGameOver(self) -> bool:
  50.         for i in range(3):
  51.             if self.Board[i][0] == self.Board[i][1] and self.Board[i][1] == self.Board[i][2]:
  52.                 return True
  53.             elif self.Board[0][i] == self.Board[1][i] and self.Board[1][i] == self.Board[2][i]:
  54.                 return True
  55.         if self.Board[0][0] == self.Board[1][1] and self.Board[1][1] == self.Board[2][2]:
  56.             return True
  57.         elif self.Board[0][2] == self.Board[1][1] and self.Board[1][1] == self.Board[2][0]:
  58.             return True
  59.         return False
  60.     def IsAbleFill(self, row : int, col : int) -> bool:
  61.         return type(self.Board[row][col]) == int
  62.     def PlayerFill(self, row : int, col : int):
  63.         if self.IsAbleFill(row, col):
  64.             self.Board[row][col] = self.Player
  65.         else:
  66.             return
  67.     # AI Algorithm/ Hard Mode/ Meduim Mode/ Easy Mode
  68.     def EasyAIFill(self):
  69.         ava = [[i, j] for i in range(3) for j in range(3) if self.IsAbleFill(i, j)]
  70.         avaSpot = ava[randint(0, len(ava)-1)]
  71.         self.Board[avaSpot[0]][avaSpot[1]] = self.AI
  72.     def FindAvaSpot(self, symbol : str):
  73.         for i in range(3):
  74.             if self.Board[i][0] == symbol and self.Board[i][1] == symbol and self.IsAbleFill(i, 2):
  75.                 return [i, 2]
  76.             elif self.Board[i][2] == symbol and self.Board[i][1] == symbol and self.IsAbleFill(i, 0):
  77.                 return [i, 0]
  78.             elif self.Board[0][i] == symbol and self.Board[1][i] == symbol and self.IsAbleFill(2, i):
  79.                 return [2, i]
  80.             elif self.Board[2][i] == symbol and self.Board[1][i] == symbol and self.IsAbleFill(0, i):
  81.                 return [0, i]
  82.             elif self.Board[i][0] == symbol and self.Board[i][2] == symbol and self.IsAbleFill(i, 1):
  83.                 return [i, 1]
  84.             elif self.Board[0][i] == symbol and self.Board[2][i] == symbol and self.IsAbleFill(1, i):
  85.                 return [1, i]
  86.         if self.Board[0][0] == symbol and self.Board[1][1] == symbol and self.IsAbleFill(2, 2):
  87.             return [0, 0]
  88.         elif self.Board[2][2] == symbol and self.Board[1][1] == symbol and self.Board[0][0]:
  89.             return [2, 2]
  90.         elif self.Board[0][2] == symbol and self.Board[1][1] == symbol and self.IsAbleFill(2, 0):
  91.             return [2, 0]
  92.         elif self.Board[2][0] == symbol and self.Board[1][1] == symbol and self.IsAbleFill(0, 2):
  93.             return [0, 2]
  94.         return []
  95.     def MiniMaxCheckWinner(self) -> str:
  96.         for i in range(3):
  97.             if self.Board[i][0] == self.Board[i][1] and self.Board[i][1] == self.Board[i][2]:
  98.                 return self.Board[i][0]
  99.             elif self.Board[0][i] == self.Board[1][i] and self.Board[1][i] == self.Board[2][i]:
  100.                 return self.Board[0][i]
  101.         if self.Board[0][0] == self.Board[1][1] and self.Board[2][2]:
  102.             return self.Board[0][0]
  103.         elif self.Board[0][2] == self.Board[1][1] and self.Board[2][0]:
  104.             return self.Board[0][2]
  105.         return None
  106.     # The Algorithm of MiniMax (Might Slow)
  107.     def MiniMax(self, ismaxing : bool, alpha : int, beta : int) -> int:
  108.         if self.MiniMaxCheckWinner() == self.AI:
  109.             return 1
  110.         if self.MiniMaxCheckWinner() == self.Player:
  111.             return -1
  112.         if self.IsTie():
  113.             return 0
  114.         if ismaxing:
  115.             maxscore = -inf
  116.             for i in range(3):
  117.                 for j in range(3):
  118.                     if self.IsAbleFill:
  119.                         temp = self.Board[i][j]
  120.                         self.Board[i][j] = self.AI
  121.                         score = self.MiniMax(False, alpha, beta)
  122.                         maxscore = max(score, maxscore)
  123.                         self.Board[i][j] = temp
  124.                         alpha = max(alpha, score)
  125.                         if beta <= alpha:
  126.                             break
  127.             return maxscore
  128.         else:
  129.             minscore = inf
  130.             for i in range(3):
  131.                 for j in range(3):
  132.                     if self.IsAbleFill(i, j):
  133.                         temp = self.Board[i][j]
  134.                         self.Board[i][j] = self.Player
  135.                         score = self.MiniMax(True, alpha, beta)
  136.                         minscore = min(score, minscore)
  137.                         self.Board[i][j] = temp
  138.                         beta = min(beta, score)
  139.                         if beta <= alpha:
  140.                             break
  141.             return minscore
  142.     def AIFill(self):
  143.         match self.Diff:
  144.             case "e":
  145.                 self.EasyAIFill()
  146.             case "m":
  147.                 WinSpot = self.FindAvaSpot(self.AI)
  148.                 if WinSpot:
  149.                     self.Board[WinSpot[0]][WinSpot[1]] = self.AI
  150.                     return
  151.                 BlockSpot = self.FindAvaSpot(self.Player)
  152.                 if BlockSpot:
  153.                     self.Board[BlockSpot[0]][BlockSpot[1]] = self.AI
  154.                     return
  155.                 for i in range(3):
  156.                     for j in range(3):
  157.                         if self.IsAbleFill(i, j):
  158.                             self.Board[i][j] = self.AI
  159.                             return
  160.             case "h":
  161.                 bestscore = -inf
  162.                 bestfill = None
  163.                 for i in range(3):
  164.                     for j in range(3):
  165.                         if self.IsAbleFill(i, j):
  166.                             temp = self.Board[i][j]
  167.                             self.Board[i][j] = self.AI
  168.                             score = self.MiniMax(False, -inf, inf)
  169.                             if score > bestscore:
  170.                                 bestscore = score
  171.                                 bestfill = [i, j]
  172.                             self.Board[i][j] = temp
  173.                 if bestfill:
  174.                     self.Board[bestfill[0]][bestfill[1]] = self.AI
  175.     def AutoPlayRound(self):
  176.         match self.Turn:
  177.             case self.Player:
  178.                 while True:
  179.                     row, col = None, None
  180.                     plrcin = int(input(f"Player Turn! Currently Player is : {self.Player}\n Choose Board to Fill in From 1-9\n input Here : "))
  181.                     if plrcin > 9 or plrcin < 1 or not plrcin:
  182.                         print("invaild input")
  183.                         continue
  184.                     if plrcin <= 3:
  185.                         row, col = 0, plrcin - 1
  186.                         if not self.IsAbleFill(row, col):
  187.                             print("Board Already Filled Choose Another To Fill")
  188.                             continue
  189.                         self.PlayerFill(row, col)
  190.                         break
  191.                     elif plrcin <= 6:
  192.                         row, col = 1, plrcin - 4
  193.                         if not self.IsAbleFill(row, col):
  194.                             print("Board Already Filled Choose Another To Fill")
  195.                             continue
  196.                         self.PlayerFill(row, col)
  197.                         break
  198.                     elif plrcin <= 9:
  199.                         row, col = 2, plrcin - 7
  200.                         if not self.IsAbleFill(row, col):
  201.                             print("Board Already Filled Choose Another To Fill")
  202.                             continue
  203.                         self.PlayerFill(row, col)
  204.                         break
  205.                 self.PrevPlayed = self.Player
  206.                 self.Turn = self.AI
  207.             case self.AI:
  208.                 print("AI Turn!..AI Is Thinking And Choosing..")
  209.                 self.AIFill()
  210.                 self.PrevPlayed = self.AI
  211.                 self.Turn = self.Player
  212.     def StartGame(self):
  213.         self.ChooseTeam()
  214.         self.SelectDiff()
  215.         self.StartTurn()
  216.         while True:
  217.             self.DrawBoard()
  218.             if self.IsGameOver():
  219.                 print(f"Game Over Winner : {self.PrevPlayed}")
  220.                 break
  221.             if self.IsTie():
  222.                 print("Game Tie!")
  223.                 break
  224.             self.AutoPlayRound()
  225. #Test Result
  226. if __name__ == "__main__":
  227.     print(figlet_format("TicTacToe..."))
  228.     ttt1 = tictactoe()
  229.     ttt1.StartGame()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement