11class NycharanXOGame :
22 def __init__ (self ):
33 self .game_dim = 3
4- self .game_space = [[None for _ in range (self .game_dim )] for _ in range (self .game_dim )]
5- self .players = [0 , 1 ]
4+ self .game_space = [[" " for _ in range (self .game_dim )] for _ in range (self .game_dim )]
5+ self .players = ["X" , "O" ]
66 self .player_turn = 0
7+ self .players_score = {self .players [0 ] : 0 , self .players [1 ] : 0 }
8+
9+ def show_game (self ):
10+ for row in self .game_space :
11+ print (" | " .join (row ))
12+ print ("-" * (self .game_dim * 3 - 1 ))
713
814 def reset (self ):
9- self .game_space = [[None for _ in range (self .game_dim )] for _ in range (self .game_dim )]
15+ self .game_space = [[" " for _ in range (self .game_dim )] for _ in range (self .game_dim )]
16+ self .players_score = {self .players [0 ] : 0 , self .players [1 ] : 0 }
1017 self .player_turn = 0
1118
12- def fetch_game (self ):
13- def calc_score (line ):
14- for i in range (len (line ) - 1 ):
19+ def switch_player (self ):
20+ self .player_turn = 1 - self .player_turn
21+
22+ def calc_score (self ):
23+ self .players_score = {self .players [0 ] : 0 , self .players [1 ] : 0 }
24+
25+ def count_score (line ):
26+ for player in self .players :
1527 score = 0
1628 counter = 0
1729
18- if line [i ] == line [i + 1 ] == self .player_turn :
19- counter += 1
20- else :
21- if counter > 2 :
22- score += (counter - 2 ) + (counter - 3 )
23- return score
30+ for i in range (len (line ) - 1 ):
31+ if line [i ] == line [i + 1 ] == player :
32+ counter += 1
33+ else :
34+ if counter > 2 :
35+ score += (counter - 2 ) + (counter - 3 )
36+ counter = 0
37+ self .players_score [player ] += score
2438
2539 for i in range (self .game_dim ):
26- calc_score (self .game_space [i ])
27- calc_score ([j [i ] for j in self .game_space ])
40+ count_score (self .game_space [i ])
41+ count_score ([j [i ] for j in self .game_space ])
2842
2943 for k in range (2 * self .game_dim - 1 ):
30- calc_score ([self .game_space [i ][j ] for i in range (self .game_dim ) if 0 <= (j := k - i ) < self .game_dim ])
31- calc_score ([self .game_space [i ][j ] for i in range (self .game_dim ) if 0 <= (j := i + k - self .game_dim + 1 ) < self .game_dim ])
32-
33- for row in self .game_space :
34- if None in row :
35- return None
36-
37- return "Tie"
44+ count_score ([self .game_space [i ][j ] for i in range (self .game_dim ) if 0 <= (j := k - i ) < self .game_dim ])
45+ count_score ([self .game_space [i ][j ] for i in range (self .game_dim ) if 0 <= (j := i + k - self .game_dim + 1 ) < self .game_dim ])
3846
39- def apply_move (self , row , col ):
40- if self . game_space [ row ][ col ] != None :
41- raise ValueError ( "square is taken before make another move!" )
42-
43- self .game_space [row ][col ] = self .players [self .player_turn ]
44-
45- def switch_player ( self ):
46- self . player_turn = 1 - self . player_turn
47+ def make_move (self , row , col ):
48+ def check_validation () :
49+ return 0 <= row < self . game_dim and 0 <= col < self . game_dim and self . game_space [ row ][ col ] == " "
50+ if check_validation ():
51+ self .game_space [row ][col ] = self .players [self .player_turn ]
52+ self . calc_score ()
53+ return True
54+ return 'Invalid input Try again!'
4755
4856 def best_approach (self ):
49- def minimax (game_space , maximize ):
50- winner = self .check_winner ()
51- if winner == self .players [1 ]:
52- return 1
53- elif winner == self .players [0 ]:
54- return - 1
55- elif winner == "Tie" :
56- return 0
57-
57+ def minimax (maximize = True , alpha = float ('-inf' ), beta = float ('inf' ), depth = 6 ):
58+ for row in self .game_space :
59+ if " " not in row :
60+ return self .players_score [self .players [0 ]] - self .players_score [self .players [1 ]]
61+
5862 if maximize :
5963 max_score = float ('-inf' )
6064 for i in range (self .game_dim ):
6165 for j in range (self .game_dim ):
62- if game_space [i ][j ] == None :
63- game_space [i ][j ] = self .players [1 ]
64- score = minimax (game_space , False )
65- game_space [i ][j ] = None
66+ if self .game_space [i ][j ] == " " :
67+ self .game_space [i ][j ] = self .players [1 ]
68+ self .calc_score ()
69+ score = minimax (False , alpha , beta , depth + 1 )
70+ self .game_space [i ][j ] = " "
71+ self .calc_score ()
6672 max_score = max (max_score , score )
73+ alpha = max (alpha , score )
74+ if beta <= alpha :
75+ break
6776 return max_score
6877 else :
69- max_score = float ('- inf' )
78+ max_score = float ('inf' )
7079 for i in range (self .game_dim ):
7180 for j in range (self .game_dim ):
72- if game_space [i ][j ] == None :
73- game_space [i ][j ] = self .players [0 ]
74- score = minimax (game_space , True )
75- game_space [i ][j ] = None
81+ if self .game_space [i ][j ] == " " :
82+ self .game_space [i ][j ] = self .players [0 ]
83+ self .calc_score ()
84+ score = minimax (True , alpha , beta , depth + 1 )
85+ self .game_space [i ][j ] = " "
86+ self .calc_score ()
7687 max_score = min (max_score , score )
88+ beta = min (beta , score )
89+ if beta <= alpha :
90+ break
7791 return max_score
7892
7993 max_score = float ('-inf' )
80- max_move = (- 1 , - 1 )
94+ best_move = (- 1 , - 1 )
8195 for i in range (self .game_dim ):
8296 for j in range (self .game_dim ):
83- if self .game_space [i ][j ] == None :
97+ if self .game_space [i ][j ] == " " :
8498 self .game_space [i ][j ] = self .players [1 ]
85- score = minimax (self .game_space , False )
86- self .game_space [i ][j ] = None
99+ self .calc_score ()
100+ score = minimax (False , float ('-inf' ), float ('inf' ), 0 )
101+ self .game_space [i ][j ] = " "
102+ self .calc_score ()
87103 if score > max_score :
88104 max_score = score
89- max_move = (i , j )
90- return max_move
105+ best_move = (i , j )
106+ return best_move
107+
108+ # Game
109+ if __name__ == "__main__" :
110+ game = NycharanXOGame ()
111+
112+ while True :
113+ game .show_game ()
114+ print (f"Scores: X = { game .players_score ["X" ]} , O = { game .players_score ["O" ]} " )
115+
116+ if game .player_turn == 0 :
117+ print ("X's turn." )
118+ row , col = map (int , input (f"Enter row and column (0-{ game .game_dim - 1 } , space-separated): " ).split ())
119+ game .make_move (row , col )
120+ game .switch_player ()
121+ else :
122+ print ("O's turn." )
123+ row , col = game .best_approach ()
124+ game .make_move (row , col )
125+ print (f"Machine chooses: { row } , { col } " )
126+ game .switch_player ()
91127
92- game = NycharanXOGame ()
128+ if " " not in [cell for row in game .game_space for cell in row ]:
129+ print ("Game is over!" )
130+ game .show_game ()
131+ print (f"Final Scores: X = { game .players_score ["X" ]} , O = { game .players_score ["O" ]} " )
132+ winner = "Tie" if game .players_score ["X" ] == game .players_score ["O" ] else "X" if game .players_score ["X" ] > game .players_score ["O" ] else "O"
133+ print (f"Winner is: { winner } " )
134+ break
0 commit comments