-
Notifications
You must be signed in to change notification settings - Fork 19.7k
/
Copy pathMiniMaxAlgorithm.java
128 lines (107 loc) · 4.06 KB
/
MiniMaxAlgorithm.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package com.thealgorithms.others;
import java.util.Arrays;
import java.util.Random;
/**
* MiniMax is an algorithm used int artificial intelligence and game theory for
* minimizing the possible loss for the worst case scenario.
*
* See more (https://en.wikipedia.org/wiki/Minimax,
* https://www.geeksforgeeks.org/minimax-algorithm-in-game-theory-set-1-introduction/).
*
* @author aitofi (https://github.com/aitorfi)
*/
public class MiniMaxAlgorithm {
/**
* Game tree represented as an int array containing scores. Each array
* element is a leaf node.
*/
private int[] scores;
private int height;
/**
* Initializes the scores with 8 random leaf nodes
*/
public MiniMaxAlgorithm() {
scores = getRandomScores(3, 99);
height = log2(scores.length);
}
public static void main(String[] args) {
MiniMaxAlgorithm miniMaxAlgorith = new MiniMaxAlgorithm();
boolean isMaximizer = true; // Specifies the player that goes first.
boolean verbose = true; // True to show each players choices.
int bestScore;
bestScore = miniMaxAlgorith.miniMax(0, isMaximizer, 0, verbose);
if (verbose) {
System.out.println();
}
System.out.println(Arrays.toString(miniMaxAlgorith.getScores()));
System.out.println("The best score for " + (isMaximizer ? "Maximizer" : "Minimizer") + " is " + bestScore);
}
/**
* Returns the optimal score assuming that both players play their best.
*
* @param depth Indicates how deep we are into the game tree.
* @param isMaximizer True if it is maximizers turn; otherwise false.
* @param index Index of the leaf node that is being evaluated.
* @param verbose True to show each players choices.
* @return The optimal score for the player that made the first move.
*/
public int miniMax(int depth, boolean isMaximizer, int index, boolean verbose) {
int bestScore;
int score1;
int score2;
if (depth == height) { // Leaf node reached.
return scores[index];
}
score1 = miniMax(depth + 1, !isMaximizer, index * 2, verbose);
score2 = miniMax(depth + 1, !isMaximizer, (index * 2) + 1, verbose);
if (isMaximizer) {
// Maximizer player wants to get the maximum possible score.
bestScore = Math.max(score1, score2);
} else {
// Minimizer player wants to get the minimum possible score.
bestScore = Math.min(score1, score2);
}
// Leaf nodes can be sequentially inspected by
// recurssively multiplying (0 * 2) and ((0 * 2) + 1):
// (0 x 2) = 0; ((0 x 2) + 1) = 1
// (1 x 2) = 2; ((1 x 2) + 1) = 3
// (2 x 2) = 4; ((2 x 2) + 1) = 5 ...
if (verbose) {
System.out.printf("From %02d and %02d, %s chooses %02d%n", score1, score2, (isMaximizer ? "Maximizer" : "Minimizer"), bestScore);
}
return bestScore;
}
/**
* Returns an array of random numbers which lenght is a power of 2.
*
* @param size The power of 2 that will determine the lenght of the array.
* @param maxScore The maximum possible score.
* @return An array of random numbers.
*/
public static int[] getRandomScores(int size, int maxScore) {
int[] randomScores = new int[(int) Math.pow(2, size)];
Random rand = new Random();
for (int i = 0; i < randomScores.length; i++) {
randomScores[i] = rand.nextInt(maxScore) + 1;
}
return randomScores;
}
// A utility function to find Log n in base 2
private int log2(int n) {
return (n == 1) ? 0 : log2(n / 2) + 1;
}
public void setScores(int[] scores) {
if (scores.length % 1 == 0) {
this.scores = scores;
height = log2(this.scores.length);
} else {
System.out.println("The number of scores must be a power of 2.");
}
}
public int[] getScores() {
return scores;
}
public int getHeight() {
return height;
}
}