×

Stone Game in Java

In this tutorial, we will learn to design a stone game in Java. First of all, we will understand what is this game all about. We will grasp it through various examples.

This game is all about choosing the stone with the highest value. The stones are located in a row for which an input array is provided. The task of choosing the stones of the maximum values is assigned to two players. The player who collects stones of the maximum value is the winner of the game. Player 1 will play first, followed by player 2, and so on. A player can choose either 1 or 2, or 3 stones at once. The stones have to be selected from the left side only. The player must pick at least one stone. Our job is to choose which player will win the game if both players play optimally.

Example 1:

int arr1[] = {5, 4, 10, 19}

Output: The Match between player 1 and player2 is a draw

Explanation: Since stones are chosen from the left side and at max, only three stones are chosen, player 1 can only choose stones 1, 2 & 3. Thus, the total values of the stones chosen are5 + 4 + 10 = 19. Now, it is the turn of player 2. Player 2 can choose only stone 4, whose value is 19. Thus, both players getanidentical value. Hence, it is a draw.

Example 2:

int arr2[] = {10, -2, -2, 8}

Output: Player 1 is the winner of the game.

Explanation:  Player 1 picks only the first stone from the left and leaves the remaining. Thus, player 1 has anoverall value of 10. Now comes the turn of player 2 to choose the stones. Since players can only choose stones from the left; Hence, player 2 has to pick stones off the values -2, -2, and 8. Thus, the overall value picked by player 2 is -2 + -2 + 8 = 4, which is less than 8. Hence, player 1 is the winner.

Example 3:

int arr3[] = {-8, 3, 4, 4}

Output: Player 2 is the winner of the game.

Explanation: To maximize the value, player 1 picks stones numbered 1, 2, and 3. Thus, collecting the maximum value of -8 + 3 + 4 = -1. Now, only one stone is left that is picked by player 2. The stone is of the value 4, which is more than player 1. Thus, player 2 is the winner of the game.

Example 4:

int arr4[] = {3, 4, 0, 4, 5, 7, 4}

Output: Player 1 is the winner of the game.

Explanation: To gain the maximum value, player 1 chooses the stones numbered 1 and 2 only. Thus, collecting the maximum value of 3 + 4 = 7. Now comes the turn of player 2, and player 2 picks stones of the values 0, 4, and 5. Here the total values 0 + 4 + 5 = 9. Again, the turn of player 1 arrives, and player 1 picks values 7 and 4. Thus, the total values collected by player 1 is 3 + 7 + 4 = 14, which is greater than 9. Hence, player 1 is the winner of the game.

Implementation

Approach 1: Using Recursion

In this approach, every possible case for the player is considered.

The cases can be:

  1. Only one stone is picked by a player.
  2. Two stones are picked.
  3. All three stones are picked by a player.

The final value is the maximum or the highest value collected by the player.

Now, let us see a program for the same.

A Java Program

public class StoneGame
{  
    private int compute(int i, int[] num)  
    {  
        //computing the size of the array  
        int size = num.length;  


        // dealing with the base case  
if(i>= size)  
        {  
            return 0;  
        }  
        // if the player picks only one stone  
        int one = Integer.MIN_VALUE;  
        // if the player picks two stones  
        int two = Integer.MIN_VALUE;  
        // if the player picks three stones  
        int three = Integer.MIN_VALUE;  
        // picked one stone and performed the   
        // further computation  
        one = num[i] - compute(i + 1, num);  
if((i + 1) < size)  
        {  
            // picked two stones at a time and performing   
            // the further computation  
            two = num[i] + num[i + 1] - compute(i + 2, num);  
        }  
if((i + 2) < size)  
        {  
            // picked 3 stones at a time and further calculations are being performed 


            three = num[i] + num[i + 1] + num[i + 2] - compute(i + 3, num);  
        }  
        // picking the stone with maximum values between one, two, and three  
        return Math.max(one, Math.max(two, three));  
    }  
    public int stoneGameSoln(int[] stoneVal)   
    {  
        int res = compute(0, stoneVal);  
if(res == 0)  
        {  
            // if 0 is returned, means its a draw  
            return 0;  
        }  
if(res > 0)  
        {  
            // return value 1 means player 1 is the winner of the game  
            return 1;  
        }  
        //  return value 2 means player 2 is the winner of the game  
        return 2;  
    }  
    // beginning of the main method  
public static void main(String[] argvs)   
{  
// creation of an object of the class StoneGame
StoneGameobj = new StoneGame();  


int arr1[] = {6, 4, 10, 18};  
int size = arr1.length;  
System.out.println("Among the stones having the following values: ");  
for(int j = 0; j < size; j++)  
{  
System.out.print(arr1[j] + " ");  
}  
System.out.println();  
int res = obj.stoneGameSoln(arr1);  
if(res == 0)  
{  
System.out.println("The match between Player 1 and Player 2 is a DRAW");  
}  
else if(res == 1)  
{  
System.out.println("Player 1 is the winner of the game.");  
}  
else   
{  
System.out.println("Player 2 is the winner of the game.");  
}  
System.out.println();  


int arr2[] = {9, -2, -2, 8};  
size = arr2.length;  
System. out.println("Among the stones having the following values:");  
for(int i = 0; i< size; i++)  
{  
System.out.print(arr2[i] + " ");  
}  
System.out.println();  
res = obj.stoneGameSoln(arr2);  
if(res == 0)  
{  
System. out.println("The match between Player 1 and Player 2 is a DRAW");  
}  
else if(res == 1)  
{  
System.out.println("Player 1 is the winner of the game.");  
}  
else   
{  
System.out.println("Player 2 is the winner of the game.");  
}  
System.out.println();  


int arr3[] = {-8, 3, 7, 4};  
size = arr3.length;  
System. out.println("Among the stones having the following values:");  
for(int i = 0; i< size; i++)  
{  
System.out.print(arr3[i] + " ");  
}  
System.out.println();  
res = obj.stoneGameSoln(arr3);  
if(res == 0)  
{  
System. out.println("The match between Player 1 and Player 2 is a DRAW");  
}  
else if(res == 1)  
{  
System.out.println("Player 1 is the winner of the game.");  
}  
else   
{  
System.out.println("Player 2 is the winner of the game.");  
}  
System.out.println();  


int arr4[] = {11, 22, 0, 33, 66, 77, 44};  
size = arr4.length;  
System.out.println("Among the stones having the following values: ");  
for(int j = 0; j < size; j++)  
{  
System.out.print(arr4[j] + " ");  
}  
System.out.println();  
res = obj.stoneGameSoln(arr4);  
if(res == 0)  
{  
System.out.println("The match between Player 1 and Player 2 is a DRAW");  
}  
else if(res == 1)  
{  
System.out.println("Player 1 is the winner of the game.");  
}  
else   
{  
System.out.println("Player 2 is the winner of the game.");  
}  
}  
}  

Output:

Stone Game in Java

Explanation: This program has exponential time complexity;thus, it is not practical to use this approach for a larger number of inputs.

Approach 2: Dynamic Programming

public class StoneGame1   
{  
public int stoneGameSoln(int storeArr[])   
{  


int size = storeArr.length;  
int dp[] = new int[size];  
// it contains the sum of the values of   
// the stones of the array stoneArr
int sums[] = new int[size + 1];  
for (int j = 0; j < size; j++)   
{  
sums[j + 1] = sums[j] + storeArr[j];  
}  
dp[size - 1] = storeArr[size - 1];  
if (size > 1)   
{  
dp[size - 2] = storeArr[size - 2] + Math.max(storeArr[size - 1], 0);  
for (int j = size - 3; j >= 0; j--)   
{  
dp[j] = Integer.MIN_VALUE;  
for (int k = 1; k <= 3; k++)   
{  
// total_score contains the sum of the values of the  
// stone earned by the player  
// for k = 1 only 1 stone is picked  
// for k = 2, 2 stones are picked 
// for k = 3, 3 stones are picked 
int total_score = sums[j + k] - sums[j];  
int a1 = j + k + 1 <size ?dp[j + k + 1] : 0;  
int a2 = j + k + 2 <size ?dp[j + k + 2] : 0;  
int a3 = j + k + 3 <size ?dp[j + k + 3] : 0;  
// the players are playing optimally. Thus, 
// the minimum between a1, a2, a3  is to be picked
dp[j] = Math.max(dp[j], total_score + Math.min(a1, Math.min(a2, a3)));  
}  
}  
}  
if ((2 * dp[0]) > sums[size])   
{  
return 1;  
}  
else if ((2 * dp[0]) < sums[size])   
{  
return 2;  
}  
else   
{  
return 0;  
}  
}  
// beginning of the main method  
public static void main(String[] argvs)   
{  
// creation of an object of the class named StoneGame1  
StoneGame1 obj = new StoneGame1();  


int arr1[] = {6, 4, 10, 18};   
int size = arr1.length;  
System.out.println("Among the stones having the following values:");  
for(int i = 0; i< size; i++)  
{  
System.out.print(arr1[i] + " ");  
}  
System.out.println();  
int res = obj.stoneGameSoln(arr1);  
if(res == 0)  
{  
System.out.println("There is a tie between player 1 and player 2");  
}  
else if(res == 1)  
{  
System.out.println("Player 1 is the winner of the game.");  
}  
else   
{  
System.out.println("Player 2 is the winner of the game.");  
}  
System.out.println();  


int arr2[] = {9, -2, -2, 8};  
size = arr2.length;  
System.out.println("Among the stones having the following values:");  
for(int i = 0; i< size; i++)  
{  
System.out.print(arr2[i] + " ");  
}  
System.out.println();  
res = obj.stoneGameSoln(arr2);  
if(res == 0)  
{  
System.out.println("There is a tie between player 1 and player 2");  
}  
else if(res == 1)  
{  
System.out.println("Player 1 is the winner of the game.");  
}  
else   
{  
System.out.println("Player 2 is the winner of the game.");  
}  
System.out.println();  


int arr3[] = {-8, 3, 7, 4};   
size = arr3.length;  
System.out.println("Among the stones having the following values:");  
for(int i = 0; i< size; i++)  
{  
System.out.print(arr3[i] + " ");  
}  
System.out.println();  
res = obj.stoneGameSoln(arr3);  
if(res == 0)  
{  
System.out.println("There is a tie between player 1 and player 2");  
}  
else if(res == 1)  
{  
System.out.println("Player 1 is the winner of the game.");  
}  
else   
{  
System.out.println("Player 2 is the winner of the game.");  
}  
System.out.println();  


int arr4[] = {11, 22, 0, 33, 66, 77, 44};   
size = arr4.length;  
System. out.println("Among the stones having the following values:");  
for(int i = 0; i< size; i++)  
{  
System.out.print(arr4[i] + " ");  
}  
System.out.println();  
res = obj.stoneGameSoln(arr4);  
if(res == 0)  
{  
System.out.println("There is a tie between player 1 and player 2");  
}  
else if(res == 1)  
{  
System.out.println("Player 1 is the winner of the game.");  
}  
else   
{  
System.out.println("Player 2 is the winner of the game.");  
}  
}  
}  

Output:

Stone Game in Java

Explanation: The time complexity of the program is O(3 * N). The space complexity here is O(2N). N represents the total number of elements present in the stone array.

The space complexity can be optimized by using variables instead of arrays in a program.

Approach 3: Optimising the space complexity

public class StoneGame
{  
public int stoneGameSoln(int storeArr[])   
{  
// calculating the length of the array  
int size = storeArr.length;  
int first1 = 0; // contains the result  
int second2 = 0;  
int third3 = 0;  
for(int j = size - 1; j >= 0; j--)  
{  
// one for picking only 1 stone  
int one = Integer.MIN_VALUE;  
// two for picking 2 stones  
int two = Integer.MIN_VALUE;  
// three for picking 3 stones  
int three = Integer.MIN_VALUE;  
one = storeArr[j]- first1;  
if((j + 1) < size)  
{  
two = storeArr[j] + storeArr[j + 1] - second2;  
}  
if((j + 2) < size)  
{  
three = storeArr[j] + storeArr[j + 1] + storeArr[j + 2] - third3;  
}  
int t = Math.max(one, Math.max(two, three));  
third3 = second2;  
second2 = first1;  
first1 = t;  
}  
if(first1 == 0)   
{  
return 0;  
}  
else if(first1 > 0)   
{  
return 1;  
}  
else   
{  
return 2;  
}  
}  
    // beginning of the main method  
public static void main(String[] argvs)   
{  
// creation of an object of the class named StoneGame
StoneGameobj = new StoneGame();  


int arr1[] = {6, 4, 10, 18};   
int size = arr1.length;  


System.out.println("Among the stones having the following values: ");  
for(int i = 0; i< size; i++)  
{  
System.out.print(arr1[i] + " ");  
}  
System.out.println();  
int res = obj.stoneGameSoln(arr1);  
if(res == 0)  
{  
System.out.println("The match between Player 1 and Player 2 is a DRAW");  
}  
else if(res == 1)  
{  
System.out.println("Player 1 is the winner of the game.");  
}  
else   
{  
System.out.println("Player 2 is the winner of the game.");  
}  
System.out.println();  


int arr2[] = {9, -2, -2, 8};   
size = arr2.length;  
System.out.println(" Among the stones having the following values:");  
for(int i = 0; i< size; i++)  
{  
System.out.print(arr2[i] + " ");  
}  
System.out.println();  
res = obj.stoneGameSoln(arr2);  
if(res == 0)  
{  
System.out.println("The match between Player 1 and Player 2 is a DRAW");  
}  
else if(res == 1)  
{  
System.out.println("Player 1 is the winner of the game.");  
}  
else   
{  
System.out.println("Player 2 is the winner of the game.");  
}  
System.out.println();  


int arr3[] = {-8, 3, 7, 4};    
size = arr3.length;  
System.out.println("Among the stones having the following values: ");  
for(int i = 0; i< size; i++)  
{  
System.out.print(arr3[i] + " ");  
}  
System.out.println();  
res = obj.stoneGameSoln(arr3);  
if(res == 0)  
{  
System.out.println("The match between Player 1 and Player 2 is a DRAW");  
}  
else if(res == 1)  
{  
System.out.println("Player 1 is the winner of the game.");  
}  
else   
{  
System.out.println("Player 2 is the winner of the game.");  
}  
System.out.println();  


int arr4[] = {11, 22, 0, 33, 66, 77, 44};    
size = arr4.length;  
System.out.println("Among the stones having the following values: ");  
for(int i = 0; i< size; i++)  
{  
System.out.print(arr4[i] + " ");  
}  
System.out.println();  
res = obj.stoneGameSoln(arr4);  
if(res == 0)  
{  
System.out.println("The match between Player 1 and Player 2 is a DRAW");  
}  
else if(res == 1)  
{  
System.out.println("Player 1 is the winner of the game.");  
}  
else   
{  
System.out.println("Player 2 is the winner of the game.");  
}  
}  
}  

Output:

Stone Game in Java

Explanation: The space complexity of this program is O(1) due to the usage of variables instead of arrays and the time complexity is O(3 * N).


Related Topics

Automorphic Number Program in Java

We will learn about automorphic numbers through examples in this article, and we'll also make Java programmes that can determine whether a specific number was automorphic or not. What is an...

3 minutes read.

Java String equals() method

equals() method compares two string based on the their content. Syntax public boolean equals(Objects anObject) parameter anObject: Object to be compared with the current String. Returns It returns true when the current String is equivalent to...

1 minute read.

DatabaseMetaData in Java

The Data about another data is called Meta data. The DatabaseMetaData interface has the meta data of the database present in the system. It consists of database product name, total...

2 minutes read.

Java Integer decode() method

The decode() method of Integer class decodes a String into an Integer. It can accept decimal, hexadecimal and octal numbers. Syntax public static Integer decode(String nm) throws NumberFormatException Parameters The parameter ‘nm’ represents the...

2 minutes read.

Permutation Coefficient in Java

In this tutorial, we will get familiar with the permutation coefficient in Java.  We will understand it through examples and see different approaches to solving the problem. A permutation is a...

5 minutes read.

Java Garbage Collection

Java Garbage Collection In Java, unreferenced objects are treated like garbage. The process of reclaiming the unused memory during runtime automatically is known as the Java Garbage Collection.In other words, the...

4 minutes read.

Java Integer compareTo() method

The compareTo() method of Integer class compares two Integer objects numerically. Syntax public static int compareTo(int anotherInteger) Parameters The parameter ‘anotherInteger’ represents the Integer to be compared. Specified by This method is specified by compareTo in...

2 minutes read.

Majority Element in Java

It's an extremely intriguing question that is commonly asked in job interviews at prestigious IT firms like The Google, Amazon, TCS, and The Accenture, etc. By figuring out the solution, one may...

10 minutes read.

Constructor Overloading in Java

In Java, constructors can be overloaded just like methods. The idea of having multiple constructors with various parameter sets so that each function Object()  can carry out a particular task...

3 minutes read.

Find next greater number with same set of digits in Java

It contains a number (num). Finding the smallest number that has the same number of elements as num that is also larger than num is the task at hand. If...

8 minutes read.

Java BufferedWriter

BufferWriter Class: It is used to write the data more efficiently. This class is present in the java.io package, it inherits the data from the Writer class. Writer class is...

4 minutes read.

Ternary Operator in Java

In some cases, the if...else expression in Java can be replaced by a ternary operator. Visit the Java if...else statement first before learning about the ternary operator. Ternary operator in Java A...

3 minutes read.

Best Java IDE

Applications for desktop, workplace, smartphone, and the internet can be created using Java, one of the most popular programming languages. Java will undoubtedly be a popular programming language for so...

5 minutes read.

Java Boolean parseBoolean() Method

The parseBoolean() method of Boolean class returns a Boolean value for the specified String argument. It returns true if and only if string’s value is equal to “true”, else it...

1 minute read.

Difference Between Thread.start() and Thread.run()

In the Java programming language, the multi-threading concept consists of the start() and run() methods. Thread.start(): The thread's execution is initiated by invoking the start() method. The start() method operates two threads...

4 minutes read.

Model Class in Java

In this section, we will be acknowledged about the model class in Java, its purpose and its uses. Also, we will learn how is this created and leveraged in java. Model...

4 minutes read.

Non-primitive data types in Java

The kind of data stored in the variable is determined by its type. The type describes the data category (different sizes and values). These are not already built into the devices....

4 minutes read.

Rectangular Numbers in Java

In this tutorial, we will understand the meaning of a rectangular number in Java with the aid of examples, illustrations, and implementations. It is one of the popular coding interview...

3 minutes read.

How to Assign Static Value to Date in Java?

In this tutorial, we will learn certain ways to assign a static value to a date in java. We will see the limitation of each method that will lead to...

3 minutes read.

What is the ambiguity problem in Java?

The ambiguity problem in Java occurs when a method or constructor is overloaded with two or more methods with the same name but different parameters. This can confuse when multiple...

6 minutes read.