Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions Others/MiniMaxAlgorithm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package 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 " + String.valueOf(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, score1, 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.println(String.format("From %02d and %02d, %s chooses %02d", 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 a : randomScores) {
a = 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;
}
}