Skip to content

Commit a57c0c5

Browse files
authored
Merge branch 'master' into spiral-matrix-improve
2 parents 900a54d + 7fb4c8d commit a57c0c5

File tree

2 files changed

+237
-98
lines changed

2 files changed

+237
-98
lines changed

src/main/java/com/thealgorithms/others/MiniMaxAlgorithm.java

Lines changed: 106 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,54 +4,99 @@
44
import java.util.Random;
55

66
/**
7-
* MiniMax is an algorithm used int artificial intelligence and game theory for
8-
* minimizing the possible loss for the worst case scenario.
7+
* MiniMax is an algorithm used in artificial intelligence and game theory for
8+
* minimizing the possible loss for the worst case scenario. It is commonly used
9+
* in two-player turn-based games such as Tic-Tac-Toe, Chess, and Checkers.
910
*
10-
* See more (https://en.wikipedia.org/wiki/Minimax,
11-
* https://www.geeksforgeeks.org/minimax-algorithm-in-game-theory-set-1-introduction/).
11+
* <p>
12+
* The algorithm simulates all possible moves in a game tree and chooses the
13+
* move that minimizes the maximum possible loss. The algorithm assumes both
14+
* players play optimally.
15+
*
16+
* <p>
17+
* Time Complexity: O(b^d) where b is the branching factor and d is the depth
18+
* <p>
19+
* Space Complexity: O(d) for the recursive call stack
20+
*
21+
* <p>
22+
* See more:
23+
* <ul>
24+
* <li><a href="https://en.wikipedia.org/wiki/Minimax">Wikipedia - Minimax</a>
25+
* <li><a href=
26+
* "https://www.geeksforgeeks.org/minimax-algorithm-in-game-theory-set-1-introduction/">
27+
* GeeksforGeeks - Minimax Algorithm</a>
28+
* </ul>
1229
*
1330
* @author aitofi (https://github.com/aitorfi)
1431
*/
15-
public class MiniMaxAlgorithm {
32+
public final class MiniMaxAlgorithm {
33+
34+
private static final Random RANDOM = new Random();
1635

1736
/**
1837
* Game tree represented as an int array containing scores. Each array
19-
* element is a leaf node.
38+
* element is a leaf node. The array length must be a power of 2.
2039
*/
2140
private int[] scores;
41+
42+
/**
43+
* The height of the game tree, calculated as log2(scores.length).
44+
*/
2245
private int height;
2346

2447
/**
25-
* Initializes the scores with 8 random leaf nodes
48+
* Initializes the MiniMaxAlgorithm with 8 random leaf nodes (2^3 = 8).
49+
* Each score is a random integer between 1 and 99 inclusive.
2650
*/
2751
public MiniMaxAlgorithm() {
28-
scores = getRandomScores(3, 99);
29-
height = log2(scores.length);
52+
this(getRandomScores(3, 99));
53+
}
54+
55+
/**
56+
* Initializes the MiniMaxAlgorithm with the provided scores.
57+
*
58+
* @param scores An array of scores representing leaf nodes. The length must be
59+
* a power of 2.
60+
* @throws IllegalArgumentException if the scores array length is not a power of
61+
* 2
62+
*/
63+
public MiniMaxAlgorithm(int[] scores) {
64+
if (!isPowerOfTwo(scores.length)) {
65+
throw new IllegalArgumentException("The number of scores must be a power of 2.");
66+
}
67+
this.scores = Arrays.copyOf(scores, scores.length);
68+
this.height = log2(scores.length);
3069
}
3170

71+
/**
72+
* Demonstrates the MiniMax algorithm with a random game tree.
73+
*
74+
* @param args Command line arguments (not used)
75+
*/
3276
public static void main(String[] args) {
33-
MiniMaxAlgorithm miniMaxAlgorith = new MiniMaxAlgorithm();
77+
MiniMaxAlgorithm miniMaxAlgorithm = new MiniMaxAlgorithm();
3478
boolean isMaximizer = true; // Specifies the player that goes first.
35-
boolean verbose = true; // True to show each players choices.
3679
int bestScore;
3780

38-
bestScore = miniMaxAlgorith.miniMax(0, isMaximizer, 0, verbose);
81+
bestScore = miniMaxAlgorithm.miniMax(0, isMaximizer, 0, true);
3982

40-
if (verbose) {
41-
System.out.println();
42-
}
43-
44-
System.out.println(Arrays.toString(miniMaxAlgorith.getScores()));
83+
System.out.println();
84+
System.out.println(Arrays.toString(miniMaxAlgorithm.getScores()));
4585
System.out.println("The best score for " + (isMaximizer ? "Maximizer" : "Minimizer") + " is " + bestScore);
4686
}
4787

4888
/**
4989
* Returns the optimal score assuming that both players play their best.
5090
*
51-
* @param depth Indicates how deep we are into the game tree.
52-
* @param isMaximizer True if it is maximizers turn; otherwise false.
53-
* @param index Index of the leaf node that is being evaluated.
54-
* @param verbose True to show each players choices.
91+
* <p>
92+
* This method recursively evaluates the game tree using the minimax algorithm.
93+
* At each level, the maximizer tries to maximize the score while the minimizer
94+
* tries to minimize it.
95+
*
96+
* @param depth The current depth in the game tree (0 at root).
97+
* @param isMaximizer True if it is the maximizer's turn; false for minimizer.
98+
* @param index Index of the current node in the game tree.
99+
* @param verbose True to print each player's choice during evaluation.
55100
* @return The optimal score for the player that made the first move.
56101
*/
57102
public int miniMax(int depth, boolean isMaximizer, int index, boolean verbose) {
@@ -75,7 +120,7 @@ public int miniMax(int depth, boolean isMaximizer, int index, boolean verbose) {
75120
}
76121

77122
// Leaf nodes can be sequentially inspected by
78-
// recurssively multiplying (0 * 2) and ((0 * 2) + 1):
123+
// recursively multiplying (0 * 2) and ((0 * 2) + 1):
79124
// (0 x 2) = 0; ((0 x 2) + 1) = 1
80125
// (1 x 2) = 2; ((1 x 2) + 1) = 3
81126
// (2 x 2) = 4; ((2 x 2) + 1) = 5 ...
@@ -87,46 +132,73 @@ public int miniMax(int depth, boolean isMaximizer, int index, boolean verbose) {
87132
}
88133

89134
/**
90-
* Returns an array of random numbers which lenght is a power of 2.
135+
* Returns an array of random numbers whose length is a power of 2.
91136
*
92-
* @param size The power of 2 that will determine the lenght of the array.
93-
* @param maxScore The maximum possible score.
94-
* @return An array of random numbers.
137+
* @param size The power of 2 that will determine the length of the array
138+
* (array length = 2^size).
139+
* @param maxScore The maximum possible score (scores will be between 1 and
140+
* maxScore inclusive).
141+
* @return An array of random numbers with length 2^size.
95142
*/
96143
public static int[] getRandomScores(int size, int maxScore) {
97144
int[] randomScores = new int[(int) Math.pow(2, size)];
98-
Random rand = new Random();
99145

100146
for (int i = 0; i < randomScores.length; i++) {
101-
randomScores[i] = rand.nextInt(maxScore) + 1;
147+
randomScores[i] = RANDOM.nextInt(maxScore) + 1;
102148
}
103149

104150
return randomScores;
105151
}
106152

107-
// A utility function to find Log n in base 2
153+
/**
154+
* Calculates the logarithm base 2 of a number.
155+
*
156+
* @param n The number to calculate log2 for (must be a power of 2).
157+
* @return The log2 of n.
158+
*/
108159
private int log2(int n) {
109160
return (n == 1) ? 0 : log2(n / 2) + 1;
110161
}
111162

112-
// A utility function to check if a number is a power of 2
163+
/**
164+
* Checks if a number is a power of 2.
165+
*
166+
* @param n The number to check.
167+
* @return True if n is a power of 2, false otherwise.
168+
*/
113169
private boolean isPowerOfTwo(int n) {
114170
return n > 0 && (n & (n - 1)) == 0;
115171
}
116172

173+
/**
174+
* Sets the scores array for the game tree.
175+
*
176+
* @param scores The array of scores. Length must be a power of 2.
177+
* @throws IllegalArgumentException if the scores array length is not a power of
178+
* 2
179+
*/
117180
public void setScores(int[] scores) {
118181
if (!isPowerOfTwo(scores.length)) {
119-
System.out.println("The number of scores must be a power of 2.");
120-
return;
182+
throw new IllegalArgumentException("The number of scores must be a power of 2.");
121183
}
122-
this.scores = scores;
184+
this.scores = Arrays.copyOf(scores, scores.length);
123185
height = log2(this.scores.length);
124186
}
125187

188+
/**
189+
* Returns a copy of the scores array.
190+
*
191+
* @return A copy of the scores array.
192+
*/
126193
public int[] getScores() {
127-
return scores;
194+
return Arrays.copyOf(scores, scores.length);
128195
}
129196

197+
/**
198+
* Returns the height of the game tree.
199+
*
200+
* @return The height of the game tree (log2 of the number of leaf nodes).
201+
*/
130202
public int getHeight() {
131203
return height;
132204
}

0 commit comments

Comments
 (0)