Skip to content

Commit 515e76b

Browse files
authored
Merge pull request #8 from TanHongIT/js-minimax
create minimax algorithm
2 parents c23fb37 + 8ee69e8 commit 515e76b

1 file changed

Lines changed: 68 additions & 2 deletions

File tree

public/js/script.js

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

103106
function 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

Comments
 (0)