Requirements:The Minimax algorithm in game theory,Evaluation function in game theory
Let's combine what we've learned so far about the minimax and the estimator to write a real tic-tac-toeDO(AArtificiallyIintelligence) playing the perfect game. This artificial intelligence takes into account all possible scenarios and makes the optimal move.
Find the best move:
We will introduce a new function calledfindBestMove(). This feature evaluates all available movesminimax()and then returns the best move the maximizer can make. The pseudocode is as follows:
functionfindBestMove(array):bestMove = NULLfor everyoneboardmove: if current move is better than bestMove bestMove = current movereturnbest move
Minimum:
To check if the current traffic is better than the best, we use helpminimax()A function that considers all possible play paths and returns the best value for that move, assuming the opponent is also playing optimally
Code for maximizing and minimizingminimax()the function is similarfindBestMove(), the only difference is that it returns a value instead of a move. Here is the pseudocode:
functionminimax(Board, Tiefe, isMaximizingPlayer):IThe current state of the array is the final state:returnplate valueIisMaximizingPlayer: bestVal = -INFINITYfor everyoneMove Panel: Value = Minimax(Panel, Depth+1, False) BestVal = Max( BestVal, Value)returnbestValInside: bestVal = +INFINITEfor everyoneMove panel: Value = Minimax(Panel, Depth+1, True) BestVal = Min(BestVal, Value)returnbestVal
GameOver Status Function:
It is used to check if the game is over and to make sure there are no more moves leftisMovesLeft()Function. This is a simple direct function that checks if a train is available or not and returns true or false accordingly. The pseudocode is as follows:
functionisMovesLeft(table):for everyonepanel cell:IThe current cell is empty:returnis saidreturnimproperly
Improving our AI:
The final step is to make our AI a little smarter. Even if the next AI plays perfectly, it may decide a move that will lead to a slower win or a faster loss. Let's take an example and explain it.
Suppose X can win the game in two ways from a given state of the board.
- MoveA: X can win in 2 moves
- MoveB: X can win in 4 moves
Our evaluation function returns +10 for both movesAIB. Although the movementAis better because it provides faster win rate that our AI can pickBSometimes. To solve this problem, we subtract the depth value from the estimated result. This means that if he wins, he chooses the one that requires as few moves as possible, and if he loses, he tries to extend the game and play as many moves as possible. So the new estimate will be
- MoveAwill be +10 - 2 = 8
- MoveBwill be +10 - 4 = 6
Now since movingAhas a higher score compared to moveBOur artificial intelligence will choose the moveAabout the movementsB. The same goes for the minimizer. Instead of subtracting the depth, we add the depth value because the minimizer always tries to get as negative a value as possible. We can subtract the depth inside or outside the estimator. It's good everywhere. I decided to do it outside the office. The pseudocode implementation is as follows.
IMaximizer won:returnWIN_SCORE – dubinaotherwise ifMinimizer won:returnLOOSE_SCORE + dubin
Recommended practice
Another optimal move in Tic Tac Toe
try it!
Below is an implementation of the above idea.
C++
// C++ program to find the next optimal move
// Player
#to contain
use
Imenski-Raum
standard;
built
Move
{
int
row column;
};
char
player =
'X'
, opponent =
„Ö”
;
// This function returns true if there is an offset
// stay on board. Returns false if
// There are no more moves to play.
bool
isMovesLeft(
char
Board [3] [3])
{
Do
(
int
i = 0; i<3; i++)
Do
(
int
j = 0; j<3; j++)
I
(table[i][j]==
„_”
)
return
is said
;
return
improperly
;
}
// This is the evaluation function mentioned
// in the previous article (http://goo.gl/sJgv68)
int
treasure (
char
b[3][3])
{
// Check rows for X or O profit.
Do
(
int
edit = 0; rot<3; rot++)
{
I
(b[red][0]==b[red][1] &&
b[red][1]==b[red][2])
{
I
(b[row][0]==player)
return
+10;
Inside
I
(b[red][0]==opponent)
return
-10;
}
}
// Check columns for X or O gain.
Do
(
int
column = 0; column<3; column++)
{
I
(b[0][column]==b[1][column] &&
b[1][kol]==b[2][kol])
{
I
(b[0][col]==player)
return
+10;
Inside
I
(b[0][col]==opponent)
return
-10;
}
}
// Check diagonals for X or O win.
I
(b[0][0]==b[1][1] && b[1][1]==b[2][2])
{
I
(b[0][0]==player)
return
+10;
Inside
I
(b[0][0]==opponent)
return
-10;
}
I
(b[0][2]==b[1][1] && b[1][1]==b[2][0])
{
I
(b[0][2]==player)
return
+10;
Inside
I
(b[0][2]==opponent)
return
-10;
}
// Otherwise, if none of them won, return 0
return
0;
}
// This is the minimax function. It takes everything into account
// Possible ways the game can go and come back
// board value
int
minimum tax (
char
Brett[3][3],
int
Depth,
bool
jeMax)
{
int
result = stake (array);
// If Maximizer won the game, give it to him
// estimated result
I
(Score == 10)
return
to achieve;
// If Minimizer won the game, give it back to him
// estimated result
I
(Score == -10)
return
to achieve;
// If then there are no more moves or winners
// there is a tie
I
(isMovesLeft(board)==
improperly
)
return
0;
// If this move is a maximizer
I
(is max.)
{
int
best = -1000;
// loop through all cells
Do
(
int
i = 0; i<3; i++)
{
Do
(
int
j = 0; j<3; j++)
{
// Check if the cell is empty
I
(table[i][j]==
„_”
)
{
// Take a step
board[i][j] = player;
// call and select minimax recursively
// maximum value
best = maximum (best,
minimax(slab, depth+1, !isMax) );
// Undo move
Brett[i][j] =
„_”
;
}
}
}
return
best;
}
// When this minimizer moves
Inside
{
int
best = 1000;
// loop through all cells
Do
(
int
i = 0; i<3; i++)
{
Do
(
int
j = 0; j<3; j++)
{
// Check if the cell is empty
I
(table[i][j]==
„_”
)
{
// Take a step
array[i][j] = opponent;
// call and select minimax recursively
// minimum value
best = min(best,
minimax(slab, depth+1, !isMax));
// Undo move
Brett[i][j] =
„_”
;
}
}
}
return
best;
}
}
// This returns the player the best possible move
move findBestMove(
char
Board [3] [3])
{
int
best value = -1000;
make the best move;
best move.row = -1;
best move.col = -1;
// Go through all the cells and evaluate the minimax function for
// all empty cells. And return the cell with the optimum
// Wert.
Do
(
int
i = 0; i<3; i++)
{
Do
(
int
j = 0; j<3; j++)
{
// Check if the cell is empty
I
(table[i][j]==
„_”
)
{
// Take a step
board[i][j] = player;
// Calculate an estimator for it
// Move.
int
moveVal = minimax(width, 0,
improperly
);
// Undo move
Brett[i][j] =
„_”
;
// If the value of the current move
// more than best value then update
// the best/
I
(moveVal > bestVal)
{
best move.row = i;
best move.col = j;
bestvalue = transfervalue;
}
}
}
}
print
(
"The value of the best move is: %d\n\n"
,
bestVal);
return
best move;
}
// At the driver's
int
mainly()
{
char
Brett[3][3] =
{
{
'X'
,
„Ö”
,
'X'
},
{
„Ö”
,
„Ö”
,
'X'
},
{
„_”
,
„_”
,
„_”
}
};
Move Best Move = findBest Move(table);
print
(
"The optimal move is:\n"
);
print
(
„REDACT: %d COL: %d\n\n“
, bestMove.row,
bestMove.col );
return
0;
}
Java
// Java search program
// the next optimal move for the player
Class
GFG
{
static
Class
Move
{
int
row column;
};
static
char
player =
'X'
, opponent =
„Ö”
;
// This function returns true if there is an offset
// stay on board. Returns false if
// There are no more moves to play.
static
Boolean is a move to the left(
char
Planks[][])
{
Do
(
int
i =
0
; i <
3
; i++)
Do
(
int
j =
0
; j <
3
; j++)
I
(table[i][j] ==
„_”
)
return
is said
;
return
improperly
;
}
// This is the evaluation function mentioned
// in the previous article (http://goo.gl/sJgv68)
static
int
treasure (
char
B[][])
{
// Check rows for X or O profit.
Do
(
int
rot =
0
; line <
3
; rot ++)
{
I
(brew][
0
] == b[rot][
1
] &&
brew][
1
] == b[rot][
2
])
{
I
(brew][
0
] == player)
return
+
10
;
Inside
I
(brew][
0
] == opponent)
return
-
10
;
}
}
// Check columns for X or O gain.
Do
(
int
column =
0
; column <
3
; column++)
{
I
(B[
0
[kol] == b[
1
[Division] &&
B[
1
[kol] == b[
2
[kol])
{
I
(B[
0
[column] == player)
return
+
10
;
Inside
I
(B[
0
][col] == opponent)
return
-
10
;
}
}
// Check diagonals for X or O win.
I
(B[
0
][
0
] == b[
1
][
1
] && B[
1
][
1
] == b[
2
][
2
])
{
I
(B[
0
][
0
] == player)
return
+
10
;
Inside
I
(B[
0
][
0
] == opponent)
return
-
10
;
}
I
(B[
0
][
2
] == b[
1
][
1
] && B[
1
][
1
] == b[
2
][
0
])
{
I
(B[
0
][
2
] == player)
return
+
10
;
Inside
I
(B[
0
][
2
] == opponent)
return
-
10
;
}
// Otherwise, if none of them won, return 0
return
0
;
}
// This is the minimax function. It takes everything into account
// Possible ways the game can go and come back
// board value
static
int
minimum tax (
char
boards[][],
int
depth, logical value is maximum)
{
int
result = stake (array);
// If Maximizer won the game
// returns his/her estimated score
I
(Result ==
10
)
return
to achieve;
// If Minimizer won the game
// returns his/her estimated score
I
(Result == -
10
)
return
to achieve;
// if there are no more trains i
// No winner, then it's a tie
I
(isMovesLeft(board) ==
improperly
)
return
0
;
// If this move is a maximizer
I
(is max.)
{
int
best = -
1000
;
// loop through all cells
Do
(
int
i =
0
; i <
3
; i++)
{
Do
(
int
j =
0
; j <
3
; j++)
{
// Check if the cell is empty
I
(table[i][j]==
„_”
)
{
// Take a step
board[i][j] = player;
// call and select minimax recursively
// maximum value
best = Math.max(best, minimax(array,
depth +
1
, !jeMax));
// Undo move
Brett[i][j] =
„_”
;
}
}
}
return
best;
}
// When this minimizer moves
Inside
{
int
best =
1000
;
// loop through all cells
Do
(
int
i =
0
; i <
3
; i++)
{
Do
(
int
j =
0
; j <
3
; j++)
{
// Check if the cell is empty
I
(table[i][j] ==
„_”
)
{
// Take a step
array[i][j] = opponent;
// call and select minimax recursively
// minimum value
best = Math.min(best, minimax(array,
depth +
1
, !jeMax));
// Undo move
Brett[i][j] =
„_”
;
}
}
}
return
best;
}
}
// This will give the best possible result
// move instead of player
static
move findBestMove(
char
Planks[][])
{
int
best value=-
1000
;
Scroll best Scroll =
new
move();
bestMove.row = -
1
;
bestMove.col = -
1
;
// Iterate through all the cells and evaluate the minimax function
// for all empty cells. And return the cell
// with the optimal value.
Do
(
int
i =
0
; i <
3
; i++)
{
Do
(
int
j =
0
; j <
3
; j++)
{
// Check if the cell is empty
I
(table[i][j] ==
„_”
)
{
// Take a step
board[i][j] = player;
// Calculate an estimator for it
// Move.
int
moveVal = minimax(width,
0
,
improperly
);
// Undo move
Brett[i][j] =
„_”
;
// If the value of the current move
// more than best value then update
// the best/
I
(moveVal > bestVal)
{
best move.row = i;
best move.col = j;
bestvalue = transfervalue;
}
}
}
}
System.out.printf(
"Best Moving Value"
+
"Ha: %d\n\n"
, bestVal);
return
best move;
}
// At the driver's
public
static
cancel
main (String[]-Argument)
{
char
Brett[][] = {{
'X'
,
„Ö”
,
'X'
},
{
„Ö”
,
„Ö”
,
'X'
},
{
„_”
,
„_”
,
„_”
}};
Move Best Move = findBest Move(table);
System.out.printf(
"The optimal move is:\n"
);
System.out.printf(
„REDACT: %d COL: %d\n\n“
,
bestMove.wiersz, bestMove.col );
}
}
// This code was created by PrinciRaj1992
Python3
# Python3 program to find the next optimal move for the player
player, opponent
=
'X'
,
„Ö”
# This function returns true if there is an offset
# stay on board. Returns false if
# No more moves to play.
pok
isMovesLeft(board) :
Do
I
u
Area
(
3
) :
Do
J
u
Area
(
3
) :
I
(Table[i][j]
=
=
„_”
) :
return
It is said
return
improperly
# This is the evaluation function mentioned
# in the previous article (http://goo.gl/sJgv68)
pok
Rate (b):
# Check lines for X or O win.
Do
Rot
u
Area
(
3
) :
I
(brew][
0
]
=
=
brew][
1
]
I
brew][
1
]
=
=
brew][
2
]):
I
(brew][
0
]
=
=
Player) :
return
10
Elif
(brew][
0
]
=
=
Opponent):
return
-
10
# Check columns for X or O gain.
Do
kol
u
Area
(
3
) :
I
(B[
0
][pass]
=
=
B[
1
][pass]
I
B[
1
][pass]
=
=
B[
2
[kol]):
I
(B[
0
][pass]
=
=
Player) :
return
10
Elif
(B[
0
][pass]
=
=
Opponent):
return
-
10
# Check diagonals for X or O win.
I
(B[
0
][
0
]
=
=
B[
1
][
1
]
I
B[
1
][
1
]
=
=
B[
2
][
2
]):
I
(B[
0
][
0
]
=
=
Player) :
return
10
Elif
(B[
0
][
0
]
=
=
Opponent):
return
-
10
I
(B[
0
][
2
]
=
=
B[
1
][
1
]
I
B[
1
][
1
]
=
=
B[
2
][
0
]):
I
(B[
0
][
2
]
=
=
Player) :
return
10
Elif
(B[
0
][
2
]
=
=
Opponent):
return
-
10
# Otherwise, if none of them won, return 0
return
0
# This is the minimax function. It takes everything into account
# possible ways to exit and return the game
# array value
pok
minimax(slab; depth; isMax) :
to achieve
=
Tariff (meal)
# If Maximizer won the game, pay him
# estimated result
I
(to achieve
=
=
10
) :
return
to achieve
# If Minimizer won the game, return it
# estimated result
I
(to achieve
=
=
-
10
) :
return
to achieve
# When there are no more moves and no winners
# to remis
I
(swipe left (panel)
=
=
improperly
) :
return
0
# If it is a maximizing move
I
(jeMax):
best
=
-
1000
# View all cells
Do
I
u
Area
(
3
) :
Do
J
u
Area
(
3
) :
# Check if the cell is empty
I
(Table[i][j]
=
=
„_”
) :
# Take a step
Brett[i][j]
=
player
# Call and select minimax recursively
# maximum value
best
=
maks
(best, minimax (board,
depth
+
1
,
This is
Maks))
# Undo move
Brett[i][j]
=
„_”
return
best
# When will this minimizer be moved
Inside
:
best
=
1000
# View all cells
Do
I
u
Area
(
3
) :
Do
J
u
Area
(
3
) :
# Check if the cell is empty
I
(Table[i][j]
=
=
„_”
) :
# Take a step
Brett[i][j]
=
Opponent
# Call and select minimax recursively
# minimum value
best
=
Minimum
(preferably, minimax(board, depth
+
1
,
This is
Maks))
# Undo move
Brett[i][j]
=
„_”
return
best
# Returns the player the best possible move
pok
findBestMove(board):
bestVal
=
-
1000
best move
=
(
-
1
,
-
1
)
# Go through all the cells and evaluate the minimax function for
# all blank cells. And return the cell with the optimum
# Wert.
Do
I
u
Area
(
3
) :
Do
J
u
Area
(
3
) :
# Check if the cell is empty
I
(Table[i][j]
=
=
„_”
) :
# Take a step
Brett[i][j]
=
player
# Calculate the estimator for this
# Move.
ruchWal
=
Minimax(plate,
0
,
improperly
)
# Undo move
Brett[i][j]
=
„_”
# If the value of the current move
# more than best value then update
#rather/
I
(moveVal > bestVal):
best move
=
(me J)
bestVal
=
ruchWal
print
(
"The value of the best move is:"
, best value)
print
()
return
best move
# On the driver's door
boards
=
[
[
'X'
,
„Ö”
,
'X'
],
[
„Ö”
,
„Ö”
,
'X'
],
[
„_”
,
„_”
,
„_”
]
]
best move
=
findBestMove (table)
print
(
"The optimal move is:"
)
print
(
"ROT:"
, best move[
0
],
"PASS:"
, best move[
1
])
# This code was submitted by divyesh072019
C#
// search program in C#
// the next optimal move for the player
use
System;
use
System.Collections.Generic;
Class
GFG
{
Class
Move
{
public
int
row column;
};
static
char
player =
'X'
, opponent =
„Ö”
;
// This function returns true if there is an offset
// stay on board. Returns false if
// There are no more moves to play.
static
Boolean is a move to the left(
char
[,] boards)
{
Do
(
int
i = 0; i < 3; i++)
Do
(
int
j = 0; d < 3; j++)
I
(table[i, j] ==
„_”
)
return
is said
;
return
improperly
;
}
// This is the evaluation function mentioned
// in the previous article (http://goo.gl/sJgv68)
static
int
treasure (
char
[,]B)
{
// Check rows for X or O profit.
Do
(
int
row = 0; line < 3; line++)
{
I
(b[rotation, 0] == b[rotation, 1] &&
b[rotation, 1] == b[rotation, 2])
{
I
(b[row, 0] == player)
return
+10;
Inside
I
(b[red, 0] == protivnik)
return
-10;
}
}
// Check columns for X or O gain.
Do
(
int
column = 0; column < 3; column++)
{
I
(b[0, column] == b[1, column] &&
b[1, column] == b[2, column])
{
I
(b[0, col] == player)
return
+10;
Inside
I
(b[0, col] == opponent)
return
-10;
}
}
// Check diagonals for X or O win.
I
(b[0, 0] == b[1, 1] && b[1, 1] == b[2, 2])
{
I
(b[0, 0] == player)
return
+10;
Inside
I
(b[0, 0] == opponent)
return
-10;
}
I
(b[0, 2] == b[1, 1] && b[1, 1] == b[2, 0])
{
I
(b[0, 2] == player)
return
+10;
Inside
I
(b[0, 2] == opponent)
return
-10;
}
// Otherwise, if none of them won, return 0
return
0;
}
// This is the minimax function. It takes everything into account
// Possible ways the game can go and come back
// board value
static
int
minimum tax (
char
[,]Boards,
int
depth, logical value is maximum)
{
int
result = stake (array);
// If Maximizer won the game
// returns his/her estimated score
I
(Score == 10)
return
to achieve;
// If Minimizer won the game
// returns his/her estimated score
I
(Score == -10)
return
to achieve;
// if there are no more trains i
// No winner, then it's a tie
I
(isMovesLeft(board) ==
improperly
)
return
0;
// If this move is a maximizer
I
(is max.)
{
int
best = -1000;
// loop through all cells
Do
(
int
i = 0; i < 3; i++)
{
Do
(
int
j = 0; d < 3; j++)
{
// Check if the cell is empty
I
(table[i, j] ==
„_”
)
{
// Take a step
board[i,j] = player;
// call and select minimax recursively
// maximum value
best = Math.Max(best, minimax(array,
dubina + 1, !isMax));
// Undo move
Brett[i, j] =
„_”
;
}
}
}
return
best;
}
// When this minimizer moves
Inside
{
int
best = 1000;
// loop through all cells
Do
(
int
i = 0; i < 3; i++)
{
Do
(
int
j = 0; d < 3; j++)
{
// Check if the cell is empty
I
(table[i, j] ==
„_”
)
{
// Take a step
board[i,j] = opponent;
// call and select minimax recursively
// minimum value
best = Math.Min(best, minimax(array,
dubina + 1, !isMax));
// Undo move
Brett[i, j] =
„_”
;
}
}
}
return
best;
}
}
// This will give the best possible result
// move instead of player
static
move findBestMove(
char
[,] boards)
{
int
best value = -1000;
Scroll best Scroll =
new
move();
best move.row = -1;
best move.col = -1;
// Iterate through all the cells and evaluate the minimax function
// for all empty cells. And return the cell
// with the optimal value.
Do
(
int
i = 0; i < 3; i++)
{
Do
(
int
j = 0; d < 3; j++)
{
// Check if the cell is empty
I
(table[i, j] ==
„_”
)
{
// Take a step
board[i,j] = player;
// Calculate an estimator for it
// Move.
int
moveVal = minimax(width, 0,
improperly
);
// Undo move
Brett[i, j] =
„_”
;
// If the value of the current move
// more than best value then update
// the best/
I
(moveVal > bestVal)
{
best move.row = i;
best move.col = j;
bestvalue = transfervalue;
}
}
}
}
Console.Write(
"Best Moving Value"
+
"Ty: {0}\n\n"
, bestVal);
return
best move;
}
// At the driver's
public
static
cancel
Main(String[] argumenty)
{
char
[,]table = {{
'X'
,
„Ö”
,
'X'
},
{
„Ö”
,
„Ö”
,
'X'
},
{
„_”
,
„_”
,
„_”
}};
Move Best Move = findBest Move(table);
Console.Write(
"The optimal move is:\n"
);
Console.Write(
"READ: {0} COLOR: {1}\n\n"
,
bestMove.wiersz, bestMove.col );
}
}
// This code was submitted by 29AjayKumar
JavaScript
// JavaScript search engine
// the next optimal move for the player
class movement
{
Constructor()
{
row, buddy;
}
}
let the player =
'X'
, opponent =
„Ö”
;
// This function returns true if there is an offset
// stay on board. Returns false if
// There are no more moves to play.
function
moves to the left (platter)
{
Do
(six i = 0; i < 3; i++)
Do
(six j = 0; j < 3; j++)
I
(table[i][j] ==
„_”
)
return
is said
;
return
improperly
;
}
// This is the evaluation function mentioned
// in the previous article (http://goo.gl/sJgv68)
function
rate (b)
{
// Check rows for X or O profit.
Do
(let row = 0; row < 3; row++)
{
I
(b[red][0] == b[red][1] &&
b[red][1] == b[red][2])
{
I
(b[row][0] == player)
return
+10;
Inside
I
(b[red][0] == opponent)
return
-10;
}
}
// Check columns for X or O gain.
Do
(kol = 0; kol < 3; kol++)
{
I
(b[0][kol] == b[1][kol] &&
b[1][kol] == b[2][kol])
{
I
(b[0][col] == player)
return
+10;
Inside
I
(b[0][col] == opponent)
return
-10;
}
}
// Check diagonals for X or O win.
I
(b[0][0] == b[1][1] && b[1][1] == b[2][2])
{
I
(b[0][0] == player)
return
+10;
Inside
I
(b[0][0] == opponent)
return
-10;
}
I
(b[0][2] == b[1][1] &&
b[1][1] == b[2][0])
{
I
(b[0][2] == player)
return
+10;
Inside
I
(b[0][2] == opponent)
return
-10;
}
// Else if none of them exist
// won and returned 0
return
0;
}
// This is the minimax function. This
// consider all possible paths
// The game can go and come back
// board value
function
minimax(plate, depth, isMax)
{
let result = stake (array);
// If Maximizer won the game
// returns his/her estimated score
I
(Score == 10)
return
to achieve;
// If Minimizer won the game
// returns his/her estimated score
I
(Score == -10)
return
to achieve;
// if there are no more trains i
// No winner, then it's a tie
I
(isMovesLeft(board) ==
improperly
)
return
0;
// If this move is a maximizer
I
(is max.)
{
let best = -1000;
// loop through all cells
Do
(six i = 0; i < 3; i++)
{
Do
(six j = 0; j < 3; j++)
{
// Check if the cell is empty
I
(table[i][j]=='_
')
{
// Take a step
board[i][j] = player;
// call minimax recursively
// and choose the largest value
best = Math.max(best, minimax(array,
dubina + 1, !isMax));
// Undo move
table[i][j] = '
_
';
}
}
}
return the best;
}
// If this minimizer
with the movement
Inside
{
be the best = 1000;
// loop through all cells
Do
(six i = 0; i < 3; i++)
{
Do
(six j = 0; j < 3; j++)
{
// Check if the cell is empty
I
(table[i][j] ==
„_”
)
{
// Take a step
array[i][j] = opponent;
// call minimax recursively i
// Choose the minimum value
best = Math.min(best, minimax(array,
dubina + 1, !isMax));
// Undo move
Brett[i][j] =
„_”
;
}
}
}
return
best;
}
}
// This will give the best possible result
// move instead of player
function
findBestMove (table)
{
let bestVal = -1000;
let the best move =
new
move();
best move.row = -1;
best move.col = -1;
// Go through all cells, evaluate
// The Minimax function is empty for everything
// stations. And return the cell
// with the optimal value.
Do
(six i = 0; i < 3; i++)
{
Do
(six j = 0; j < 3; j++)
{
// Check if the cell is empty
I
(table[i][j] ==
„_”
)
{
// Take a step
board[i][j] = player;
// Calculate the estimator
// for this move.
let moveVal = minimax(array, 0,
improperly
);
// Undo move
Brett[i][j] =
„_”
;
// If the value of the current move
// is therefore more than the best value
// The best update
I
(moveVal > bestVal)
{
best move.row = i;
best move.col = j;
bestvalue = transfervalue;
}
}
}
}
document.write(
"Best Moving Value"
+
"Is:"
, the best Val +
"
");
return
best move;
}
// At the driver's
let on board = [ [
'X'
,
„Ö”
,
'X'
],
[
„Ö”
,
„Ö”
,
'X'
],
[
„_”
,
„_”
,
„_”
] ];
let best move = find best move (array);
document.write(
"The optimal move is:
");
document.write(
"THE LINE: "
+ bestMove.row +
"PASS:"
+ bestMove.col +
"
");
// This code was created by rag2127
Exit:
The value of the best move is: 10 The optimal move is: ROW: 2 COL: 2
Explanation:
This image shows all the possible paths the game can take based on the state of the motherboard. It is often mentionedgame tree.
The three possible scenarios in the example above are:
- Go left: When X plays [2.0]. Then O[2,1] plays and wins the game. The value of this move is -10
- central train: When X plays [2,1]. O then plays [2,2], resulting in a draw. The value of this move is 0
- The right move: When X plays [2,2]. Then he will win the match. The value of this move is +10;
Remember, while X has the potential to win by playing middle move, O will never allow it, choosing a draw instead.
Therefore, the best choice for X is to play [2,2], which guarantees him a win.
We encourage our readers to try different inputs and understand why the AI chose this move. Minimax can confuse developers because it thinks several steps ahead, and sometimes it's very difficult to get it right. Note that this implementation of the minimax algorithm can be applied to any two-player board game with minor changes to the board structure and how moves are repeated. Also, sometimes minimax cannot calculate every possible game state for complex games like chess. So we only count to a certain depth and use the estimator to calculate the value of the board.
Stay tuned for an article next week where we discuss thisAlpha Beta cutThis can drastically reduce the time it takes for the minimax to traverse the game tree.
This article was written byAkshay L Aradhya. If you like GeeksforGeeks and want to contribute, you can also contribute to the articlewrite.geeksforgeeks.orgor send your article to review-team@geeksforgeeks.org. See how your article looks on the GeeksforGeeks homepage and help other geeks.
Write a comment if you find something wrong or want to share more information on the topic discussed above.
My personal notes Arrow_drop_up
Last actualisation: February 20, 2023
As an article
save article