×

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

Java Garbage Collection Interview Questions

One of the key areas of Java is garbage collection. Garbage collection enables apps to manage memory automatically. Interviewers frequently ask inquiries about garbage collection. Q1: What is the purpose of...

6 minutes read.

How to convert double to String in Java

How to Convert double to String in Java It is used when we want to convert double primitive to String type. There are two methods to convert double to String. Using String.valueOf()...

2 minutes read.

String Pool in Java

String Pool in Java: String is one of the most important discussed topics in Java. There are a lot of concepts related to the String and one of them is...

5 minutes read.

Salesman Problem in Java

The Traveling Salesman Problem determines the shortest path that visits each city approximately once and loops back to the starting location. Another Java problem that is most like the Traveling...

5 minutes read.

Java Clone Array

We frequently need to copy an array to back up its original components. We have a few unique numbers and strings, including Armstrong numbers, palindrome numbers, and palindrome strings. To...

4 minutes read.

Switch Case Program in Java

Switch Case Program in Java The switch case program in Java controls which code snippet gets executed on the basis of the value of the expression mentioned in the switch statement....

22 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.

Array Programs in Java

Array Programs in Java: An array is a data structure that stores similar elements in a contiguous memory location. In Java, an array is an object that stores the same...

7 minutes read.

How to convert String to String array in Java

A String in Java is a thing that indicates a collection of letters. We must include the String class from java.lang package if we want to be using strings. An...

5 minutes read.

Java Enhanced For Loop (For-each Loop)

JAVA ENHANCED FOR LOOP The enhanced for loop is also called the for-each loop and has some advantages over the regular for loop. A for-each loop is designed to cycle through...

4 minutes read.

Java String getBytes() method

getBytes() method returns sequence of bytes. Syntax: There are three variants of getBytes() method: public byte[] getBytes()        public byte[] getBytes(String charsetName) public byte[] getBytes(Charset charset) Returns: It returns sequence of bytes. Java String getBytes() Example...

2 minutes read.

Java Math.multiplyExact() method in Java

Java has an inbuilt math function called Math.multiplyExact() that returns the sum of the parameters. If the result exceeds an integer, an exception is thrown. There is no need to...

2 minutes read.

Insertion Sort in Java

Insertion Sort in Java Insertion sort in Java is a simple sorting algorithm that works in the same way as we hold cards in hand. Insertion sort does the sorting element-by-element,...

3 minutes read.

Split String into String Array in Java

The String split() technique returns a variety of divided strings after the strategy parts the given String around matches of a given normal articulation containing the delimiters. The ordinary articulation...

4 minutes read.

How to Convert Object to String in Java

How to Convert Object to String in Java You can convert any Object to String in Java whether it is a user-defined class, StringBuilder or StringBuffer, etc. There are two methods...

2 minutes read.

Why are generics used in Java

Java has a feature called generics that allows you to make a class, interface, and function accepting any (reference) type as a parameter. In other words, it is the idea...

4 minutes read.

Java Integer toUnsignedString() method

The toUnsignedString() method of Java Integer class returns a string representation of the argument as an unsigned decimal value. The second syntax returns a string representation of the given argument as...

2 minutes read.

Minimum Window Subsequence in Java

In this article, you will be very well acknowledged about the minimum window subsequence, what is the approach and how it is implemented. The example program is also executed and...

4 minutes read.

How to run Java Program?

How to run Java Program In this section, we will learn how to write, compile and run a Java program in Command Promptusing notepad. In order to run a Java program, we...

2 minutes read.

Java RMI

What is RMI in Java? A framework for developing distributed Java applications is provided by the RMI (Remote Method Invocation) API. An object can call methods on an object running in...

4 minutes read.