1+ package Others ;
2+
3+ import java .util .Arrays ;
4+ import java .util .Random ;
5+
6+ /**
7+ * MiniMax is an algorithm used int artificial intelligence and game theory for
8+ * minimizing the possible loss for the worst case scenario.
9+ *
10+ * See more (https://en.wikipedia.org/wiki/Minimax,
11+ * https://www.geeksforgeeks.org/minimax-algorithm-in-game-theory-set-1-introduction/).
12+ *
13+ * @author aitofi (https://github.com/aitorfi)
14+ */
15+ public class MiniMaxAlgorithm {
16+ /**
17+ * Game tree represented as an int array containing scores. Each array element
18+ * is a leaf node.
19+ */
20+ private int [] scores ;
21+ private int height ;
22+
23+ /**
24+ * Initializes the scores with 8 random leaf nodes
25+ */
26+ public MiniMaxAlgorithm () {
27+ scores = getRandomScores (3 , 99 );
28+ height = log2 (scores .length );
29+ }
30+
31+ public static void main (String [] args ) {
32+ MiniMaxAlgorithm miniMaxAlgorith = new MiniMaxAlgorithm ();
33+ boolean isMaximizer = true ; // Specifies the player that goes first.
34+ boolean verbose = true ; // True to show each players choices.
35+ int bestScore ;
36+
37+ bestScore = miniMaxAlgorith .miniMax (0 , isMaximizer , 0 , verbose );
38+
39+ if (verbose ) {
40+ System .out .println ();
41+ }
42+
43+ System .out .println (Arrays .toString (miniMaxAlgorith .getScores ()));
44+ System .out .println (
45+ "The best score for " + (isMaximizer ? "Maximizer" : "Minimizer" ) + " is " + String .valueOf (bestScore ));
46+ }
47+
48+ /**
49+ * Returns the optimal score assuming that both players play their best.
50+ *
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.
55+ * @return The optimal score for the player that made the first move.
56+ */
57+ public int miniMax (int depth , boolean isMaximizer , int index , boolean verbose ) {
58+ int bestScore , score1 , score2 ;
59+
60+ if (depth == height ) { // Leaf node reached.
61+ return scores [index ];
62+ }
63+
64+ score1 = miniMax (depth + 1 , !isMaximizer , index * 2 , verbose );
65+ score2 = miniMax (depth + 1 , !isMaximizer , (index * 2 ) + 1 , verbose );
66+
67+ if (isMaximizer ) {
68+ // Maximizer player wants to get the maximum possible score.
69+ bestScore = Math .max (score1 , score2 );
70+ } else {
71+ // Minimizer player wants to get the minimum possible score.
72+ bestScore = Math .min (score1 , score2 );
73+ }
74+
75+ // Leaf nodes can be sequentially inspected by
76+ // recurssively multiplying (0 * 2) and ((0 * 2) + 1):
77+ // (0 x 2) = 0; ((0 x 2) + 1) = 1
78+ // (1 x 2) = 2; ((1 x 2) + 1) = 3
79+ // (2 x 2) = 4; ((2 x 2) + 1) = 5 ...
80+
81+ if (verbose ) {
82+ System .out .println (String .format ("From %02d and %02d, %s chooses %02d" , score1 , score2 ,
83+ (isMaximizer ? "Maximizer" : "Minimizer" ), bestScore ));
84+ }
85+
86+ return bestScore ;
87+ }
88+
89+ /**
90+ * Returns an array of random numbers which lenght is a power of 2.
91+ *
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.
95+ */
96+ public static int [] getRandomScores (int size , int maxScore ) {
97+ int [] randomScores = new int [(int ) Math .pow (2 , size )];
98+ Random rand = new Random ();
99+
100+ for (int a : randomScores ) {
101+ a = rand .nextInt (maxScore ) + 1 ;
102+ }
103+
104+ return randomScores ;
105+ }
106+
107+ // A utility function to find Log n in base 2
108+ private int log2 (int n ) {
109+ return (n == 1 ) ? 0 : log2 (n / 2 ) + 1 ;
110+ }
111+
112+ public void setScores (int [] scores ) {
113+ if (scores .length % 1 == 0 ) {
114+ this .scores = scores ;
115+ height = log2 (this .scores .length );
116+ } else {
117+ System .out .println ("The number of scores must be a power of 2." );
118+ }
119+ }
120+
121+ public int [] getScores () {
122+ return scores ;
123+ }
124+
125+ public int getHeight () {
126+ return height ;
127+ }
128+ }
0 commit comments