@@ -96,8 +96,11 @@ function emptySquares() {
9696 return origBoard . filter ( s => typeof s == 'number' ) ;
9797}
9898
99- function bestSpot ( ) { //Find all blank cells and get first element from blank cell. So the AI will always play the first slot
100- return emptySquares ( ) [ 0 ] ;
99+ function bestSpot ( ) {
100+ // //Find all blank cells and get first element from blank cell. So the AI will always play the first slot
101+ // return emptySquares()[0];
102+
103+ return minimax ( origBoard , aiPlayer ) . index ;
101104}
102105
103106function checkTie ( ) {
@@ -110,4 +113,67 @@ function checkTie() {
110113 return true ;
111114 }
112115 return false ;
116+ }
117+
118+ function minimax ( newBoard , player ) {
119+ // find the indexes of the available spots in the board and set them to a variable called availSpots
120+ var availSpots = emptySquares ( ) ;
121+
122+ // check terminal states
123+ if ( checkWin ( newBoard , oPlayer ) ) {
124+ return { score : - 10 } ; // O win
125+ } else if ( checkWin ( newBoard , aiPlayer ) ) {
126+ return { score : 10 } ; // X win
127+ } else if ( availSpots . length === 0 ) {
128+ return { score : 0 } ; // tie
129+ }
130+ // Next, you need to collect the scores from each of the empty spots to evaluate later.
131+ var moves = [ ] ;
132+ // Therefore, make an array called moves and loop through empty spots while collecting each move’s index and score in an object called move.
133+ for ( var i = 0 ; i < availSpots . length ; i ++ ) {
134+ var move = { } ;
135+ // Then, set the index number of the empty spot that was stored as a number in the origBoard to the index property of the move object
136+ move . index = newBoard [ availSpots [ i ] ] ;
137+ // set the empty spot on the newboard to the current player
138+ newBoard [ availSpots [ i ] ] = player ;
139+
140+ // store the object resulted from the minimax function call that includes a score property to the score property of the move object.
141+ if ( player == aiPlayer ) {
142+ var result = minimax ( newBoard , oPlayer ) ;
143+ move . score = result . score ;
144+ } else {
145+ var result = minimax ( newBoard , aiPlayer ) ;
146+ move . score = result . score ;
147+ }
148+
149+ newBoard [ availSpots [ i ] ] = move . index ;
150+
151+ // minimax reset new board to what it was before and pushes the move object to the moves aray
152+ moves . push ( move ) ;
153+ }
154+
155+ // Then, the minimax algorithm needs to evaluate the best move in the moves array
156+ var bestMove ;
157+ // It should choose the move with the highest score when AI is playing and the move with the lowest score when the human is playing. So...
158+ if ( player === aiPlayer ) {
159+ // If the player is aiPlayer, it sets a variable called bestScore to a very low number and loops through the moves array,
160+ var bestScore = - 10000 ;
161+ for ( var i = 0 ; i < moves . length ; i ++ ) {
162+ // if a move has a higher score than bestScore, the algorithm stores that move
163+ if ( moves [ i ] . score > bestScore ) {
164+ bestScore = moves [ i ] . score ;
165+ bestMove = i ; // In case there are moves with similar score, only the first one will be stored.
166+ }
167+ }
168+ } else {
169+ var bestScore = 10000 ;
170+ for ( var i = 0 ; i < moves . length ; i ++ ) {
171+ if ( moves [ i ] . score < bestScore ) {
172+ bestScore = moves [ i ] . score ;
173+ bestMove = i ;
174+ }
175+ }
176+ }
177+
178+ return moves [ bestMove ] ;
113179}
0 commit comments