@@ -11,28 +11,31 @@ pub struct AIMinMax {
1111
1212impl AIMinMax {
1313 pub fn new ( ) -> Self {
14- AIMinMax {
15- ai_player : None
14+ AIMinMax { ai_player : None }
15+ }
16+
17+ fn ai_player ( & self ) -> PlayerID {
18+ self . ai_player
19+ . expect ( "self.ai_player should be set by game_start()" )
20+ }
21+
22+ fn opponent ( & self ) -> PlayerID {
23+ match self . ai_player ( ) {
24+ PlayerID :: Player1 => PlayerID :: Player2 ,
25+ PlayerID :: Player2 => PlayerID :: Player1 ,
1626 }
1727 }
1828
1929 /// Minimax algorithm implementation
20- fn minimax (
21- & self ,
22- mut grid : Grid ,
23- depth : i32 ,
24- is_maximizing : bool ,
25- ai_player : PlayerID ,
26- opponent : PlayerID ,
27- ) -> i32 {
30+ fn minimax ( & self , mut grid : Grid , depth : i32 , is_maximizing : bool ) -> i32 {
2831 // Check if there is a winner yet
2932 match grid:: is_there_a_win ( grid) {
3033 // If AI has won, return score minus depth to prefer quicker wins
31- Some ( winner) if winner == ai_player => {
34+ Some ( winner) if winner == self . ai_player ( ) => {
3235 return 10 - depth;
3336 }
3437 // If opponent has won, return score plus depth to delay losses
35- Some ( winner ) if winner == opponent => {
38+ Some ( _ ) => {
3639 return -10 + depth;
3740 }
3841 _ => { }
@@ -48,8 +51,8 @@ impl AIMinMax {
4851
4952 for i in 0 ..9 {
5053 if grid[ i] . is_none ( ) {
51- grid[ i] = Some ( ai_player) ;
52- let value = self . minimax ( grid, depth + 1 , false , ai_player , opponent ) ;
54+ grid[ i] = self . ai_player ;
55+ let value = self . minimax ( grid, depth + 1 , false ) ;
5356 grid[ i] = None ;
5457 best = best. max ( value) ;
5558 }
@@ -60,8 +63,8 @@ impl AIMinMax {
6063
6164 for i in 0 ..9 {
6265 if grid[ i] . is_none ( ) {
63- grid[ i] = Some ( opponent) ;
64- let value = self . minimax ( grid, depth + 1 , true , ai_player , opponent ) ;
66+ grid[ i] = Some ( self . opponent ( ) ) ;
67+ let value = self . minimax ( grid, depth + 1 , true ) ;
6568 grid[ i] = None ;
6669 best = best. min ( value) ;
6770 }
@@ -71,20 +74,15 @@ impl AIMinMax {
7174 }
7275
7376 /// Find the best move using minimax algorithm
74- fn find_best_move ( & self , mut grid : Grid , ai_player : PlayerID ) -> Option < Position > {
77+ fn find_best_move ( & self , mut grid : Grid ) -> Option < Position > {
7578 let mut best_val = i32:: MIN ;
7679 let mut best_move = None ;
7780
78- let opponent = match ai_player {
79- PlayerID :: Player1 => PlayerID :: Player2 ,
80- PlayerID :: Player2 => PlayerID :: Player1 ,
81- } ;
82-
8381 for i in 0 ..9 {
8482 if grid[ i] . is_none ( ) {
85- grid[ i] = Some ( ai_player) ; // Simulate AI move
83+ grid[ i] = self . ai_player ; // Simulate AI move
8684 // After AI move, it's opponent's turn (so start with minimizing)
87- let move_val = self . minimax ( grid, 0 , false , ai_player , opponent ) ;
85+ let move_val = self . minimax ( grid, 0 , false ) ;
8886 grid[ i] = None ; // Reset move
8987
9088 if move_val > best_val {
@@ -104,7 +102,7 @@ impl PlayerBehavior for AIMinMax {
104102 }
105103
106104 fn play ( & mut self , grid : Grid ) -> crate :: Result < Position > {
107- if let Some ( best_move) = self . find_best_move ( grid, self . ai_player . expect ( "self.ai_player should be set by game_start()" ) ) {
105+ if let Some ( best_move) = self . find_best_move ( grid) {
108106 Ok ( best_move)
109107 } else {
110108 Err ( crate :: types:: Error :: Other (
0 commit comments