-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathGamePlayer.java
110 lines (99 loc) · 4.28 KB
/
GamePlayer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import java.util.ArrayList;
import java.util.Random;
import java.lang.*;
public class GamePlayer{
private int maxDepth;
private int playerDisc;
/*This class is all about the implementation of the Minimax algorithm. The maximizer works to get the highest score,
while the minimizer gets the lowest score by trying to counter moves. In our case, only the AI player makes moves
automatically using this algorithm, if the human player has chosen to play first, the min method is used to counter
the move, otherwise the max method is used throughout the game to take the initiative with the best possible move.
The two methods (max,min) do a DFS, searching for the best possible moves using getChinldren() and our two euretics
with evaluate(). We have also added a-b prunning inside these methods, in order to avoid searching all the branches
of the tree. Instead, if the algorith realizes that going down a branch won't result in a better move, then it will
ignore it completely.
*/
public GamePlayer(int maxDepth,int playerDisc)
{
this.maxDepth =maxDepth;
this.playerDisc =playerDisc;
}
public Move MiniMax(Board board){
if (playerDisc == Board.B){
return max(new Board(board) ,0,Integer.MIN_VALUE,Integer.MAX_VALUE);
}
else {
return min(new Board(board),0,Integer.MIN_VALUE,Integer.MAX_VALUE);
}
}
public Move max(Board board,int depth,int alpha,int beta){
Random r = new Random();
if ((board.isTerminal()) || (depth ==maxDepth)){
Move lastMove = new Move(board.getLastMove().getRow(),board.getLastMove().getCol(),board.evaluate());
return lastMove;
}
ArrayList<Board> children = new ArrayList<Board>(board.getChildren(Board.B));
Move maxMove = new Move(Integer.MIN_VALUE);
for (Board child : children){
Move move = min(child,depth+1,alpha,beta);
if (move.getValue()>=maxMove.getValue()){
if ((move.getValue()==maxMove.getValue())){
if (r.nextInt(2) == 0)
{
maxMove.setRow(child.getLastMove().getRow());
maxMove.setCol(child.getLastMove().getCol());
maxMove.setValue(move.getValue());
}
}
else
{
maxMove.setRow(child.getLastMove().getRow());
maxMove.setCol(child.getLastMove().getCol());
maxMove.setValue(move.getValue());
}
}
if(maxMove.getValue()>=beta){
return maxMove;}
alpha=Math.max(alpha, maxMove.getValue());
}
return maxMove;
}
public Move min(Board board, int depth,int alpha,int beta)
{
Random r = new Random();
if((board.isTerminal()) || (depth == maxDepth))
{
Move lastMove = new Move(board.getLastMove().getRow(), board.getLastMove().getCol(), board.evaluate());
return lastMove;
}
ArrayList<Board> children = new ArrayList<Board>(board.getChildren(Board.W));
Move minMove = new Move(Integer.MAX_VALUE);
for (Board child : children)
{
Move move = max(child, depth + 1,alpha,beta);
if(move.getValue() <= minMove.getValue())
{
if ((move.getValue() == minMove.getValue()))
{
if (r.nextInt(2) == 0)
{
minMove.setRow(child.getLastMove().getRow());
minMove.setCol(child.getLastMove().getCol());
minMove.setValue(move.getValue());
}
}
else
{
minMove.setRow(child.getLastMove().getRow());
minMove.setCol(child.getLastMove().getCol());
minMove.setValue(move.getValue());
}
if(minMove.getValue()<=alpha){
return minMove;
}
beta=Math.min(beta, minMove.getValue());
}
}
return minMove;
}
}