10 Replies - 18357 Views - Last Post: 19 June 2010 - 06:09 PM Rate Topic: -----

#1 Guest_Deja*


Reputation:

Nim Game Java

Posted 19 June 2010 - 01:56 PM

The task

Design and implement a Nim class and a NimGame application to allow two human players to play the game of Nim. The game starts with four piles of stones. The first pile has 3 stones, the second pile has 5 stones, the third pile has 7 stones, and the last pile has 9 stones. The players take turns removing stones. On a single turn a player may only take stones from a single pile. A player may not take more than half the pile, except when its the last stone in the pile. The loser of the game is the player to take the very last stone.


What I'm having troubles with is that it's not displaying the winner at the end of the game, and I have noticed when I get to the 2nd 3rd and 4th piles, when I enter 1 to take 1 stone away that it takes like 3 away instead. Any help or suggestions is appreciated! Thanks!

package nimgame;

import java.util.Scanner;

public class NimGame
{
    public static void main(String[] args)
    {

        //Declare variables
        int player = 1;
        int pile = 0;
        int stones = 0;
        int counter = 0;
        int move;

        //Scanner 
        Scanner input = new Scanner(System.in);

        NimClass myAssistant = new NimClass();
        myAssistant.displayBoard();

        //Begin loop
        while(counter == 0)
        {
        //Choose pile you want to remove stones from.
        System.out.print("Player " + player + " Please enter the pile you wish" +
                         " to remove from. (1, 2, 3 or 4)\n");
        pile = input.nextInt();
        myAssistant.playerMove(pile, stones);

        //Enter # of stones you want to remove.
        System.out.print("Player " + player + " Please enter the amount of" +
                          " stones you wish to remove\n");
        stones = input.nextInt();
        myAssistant.playerMove(pile, stones);

            //Determine what player is entering the values.
            if (player == 1)
                player = 2;
            else
                player = 1;

             //Display board / determine the winner of the game.
             myAssistant.displayBoard();
             myAssistant.determineWinner();


            if (myAssistant.determineWinner() != -1)
                counter = 1;

        }


    }
}





package nimgame;

public class NimClass
{
    //Declare varaiables
    private int [] _board;

    
    public NimClass()
    {
        //Determing # of stones in each pile at the beginning.
        _board = new int [4];
        _board[0] = 3;
        _board[1] = 5;
        _board[2] = 7;
        _board[3] = 9;

        System.out.println("Welcome to the Game of Nim\n" +
                           "You'll need to first pick a pile\n" +
                           "Then select how many stones you wish to remove\n");
    }


   //Display the game board
    public void displayBoard()
    {
        for(int row = 0; row < 4; row++)
        {
            if(_board[row] == 0)
                System.out.print("    0    ");
            else
                System.out.print("     " + _board[row] + "   ");
        }
            //Print out the piles
            System.out.println("\n  Pile 1   Pile 2   Pile 3   Pile 4\n");

    }

    //Determine the player's moves
    public boolean playerMove (int pile, int stones)
    {
      if ((pile < 1) || (pile > _board.length))
      {
          return false;
      }

        if (_board[pile - 1] >= stones)
        {
          _board[pile - 1] -= stones;
          return true;
        }
     else
        {
          return false;
        }
    }


    //Determine the winner of the game
    public int determineWinner()
    {
        boolean complete = true;
        int winner = -1;

        //Checking the piles to see if they're empty.
        if((_board[0] == 0) && ( _board[1]== 0) && ( _board[2]==0) && ( _board[3]==0))
        winner = _board[0];

        if(complete == false && winner == 1)
        {
            //Display the results of player 1 winning.
            System.out.println("Player 1 Wins!");
            winner = 0;
        }

        if(complete == false && winner == 2)
        {
            //Display the results of player 2 winning.
            System.out.println("Player 2 Wins!");
            winner = 0;
        }
        return winner;

    }
}



Is This A Good Question/Topic? 1

Replies To: Nim Game Java

#2 eZACKe  Icon User is offline

  • Garbage Collector

Reputation: 120
  • View blog
  • Posts: 1,278
  • Joined: 01-June 09

Re: Nim Game Java

Posted 19 June 2010 - 03:08 PM

Figured out the reason it is subtracting the wrong values from the piles. You do this:
while(counter == 0)
        {
        //Choose pile you want to remove stones from.
        System.out.print("Player " + player + " Please enter the pile you wish" +
                         " to remove from. (1, 2, 3 or 4)\n");
        pile = input.nextInt();
        myAssistant.playerMove(pile, stones);

        //Enter # of stones you want to remove.
        System.out.print("Player " + player + " Please enter the amount of" +
                          " stones you wish to remove\n");
        stones = input.nextInt();
        myAssistant.playerMove(pile, stones);



There is no need to call the playerMove method twice. Just do it like this:
 //Choose pile you want to remove stones from.
        System.out.print("Player " + player + " Please enter the pile you wish" +
                         " to remove from. (1, 2, 3 or 4)\n");
        pile = input.nextInt();//get a pile number
      
        //Enter # of stones you want to remove.
        System.out.print("Player " + player + " Please enter the amount of" +
                          " stones you wish to remove\n");
        stones = input.nextInt();
        myAssistant.playerMove(pile, stones);



Working on the other problem now, will post when I figure it out.

Also, you do know that this game is far from complete if you want all the rules you specified, right? You do nothing about only being able to take a certain amount from each pile. As is, you can take every stone from any pile whenever you want.. no limitations.


Edit:

Here's a fix to the problem of the game not telling you who the winner is. Your problem was the variable complete was never going to be false (by the way I really feel like the complete should start false and go to true if the game is over, but whatever you want).

Also, why you were assigning winner to _board[0], I will never understand. That means you were setting it to 0 no matter what. Yet another reason it would never enter the if statement. Here's the fix (I commented lines that have to do with this fix in caps):

NimGame class:
import java.util.Scanner;

public class NimGame
{
	public static int player = 1;//THIS IS A FIX

	
    public static void main(String[] args)
    {

        //Declare variables
        //TOOK player AWAY HERE AND MADE IT GLOBAL STATIC
        int pile = 0;//which pile to pick from
        int stones = 0;//how many stones to pick
        int counter = 0;//if the game is over or not -> 0 not over
        int move;

        //Scanner 
        Scanner input = new Scanner(System.in);

        NimClass myAssistant = new NimClass();
        myAssistant.displayBoard();//board gets set up

        //Begin loop
        while(counter == 0)
        {
        //Choose pile you want to remove stones from.
        System.out.print("Player " + player + " Please enter the pile you wish" +
                         " to remove from. (1, 2, 3 or 4)\n");
        pile = input.nextInt();//get a pile number
      
        //Enter # of stones you want to remove.
        System.out.print("Player " + player + " Please enter the amount of" +
                          " stones you wish to remove\n");
        stones = input.nextInt();
        
        
        myAssistant.playerMove(pile, stones);
        

        
        

            //Determine what player is entering the values.
            if (player == 1)
                player = 2;
            else
                player = 1;

             //Display board / determine the winner of the game.
             myAssistant.displayBoard();
             myAssistant.determineWinner();


            if (myAssistant.determineWinner() != -1)
                counter = 1;

        }
        
       
       
        }
    
   
    


    }



NimClass class:
public class NimClass
{
    //Declare varaiables
    private int [] _board;//the board for the game -> just an array

    
    public NimClass()
    {
    	
    	NimGame nimGame;//ADDED THIS SO WE CAN DETERMINE WHAT PLAYER IT CURRENTLY IS
        //Determing # of stones in each pile at the beginning.
        _board = new int [4];
        _board[0] = 3;//pile 1 - 3 stones
        _board[1] = 5;//pile 2 - 5 stones
        _board[2] = 7;//pile 3 - 7 stones
        _board[3] = 9;//pile 4 - 9 stones

        System.out.println("Welcome to the Game of Nim\n" +
                           "You'll need to first pick a pile\n" +
                           "Then select how many stones you wish to remove\n");
    }


   //Display the game board
    public void displayBoard()//just setting up the board with default values
    {
        for(int row = 0; row < 4; row++)
        {
            if(_board[row] == 0)
                System.out.print("    0    ");
            else
                System.out.print("     " + _board[row] + "   ");
        }
            //Print out the piles
            System.out.println("\n  Pile 1   Pile 2   Pile 3   Pile 4\n");

    }

    //Determine the player's moves
    public boolean playerMove (int pile, int stones)
    {
      if ((pile < 1) || (pile > _board.length))
      {
          return false;//user specified wrong pile
      }

        if (_board[pile - 1] >= stones)
        {
          _board[pile - 1] -= stones;
          return true;
        }
     else
        {
          return false;
        }
    }


    //Determine the winner of the game
    public int determineWinner()
    {
        boolean complete = true;
        int winner = -1;

        //Checking the piles to see if they're empty.
        if((_board[0] == 0) && ( _board[1]== 0) && ( _board[2]==0) && ( _board[3]==0))
        {
        	winner = NimGame.player;//FIXED THIS HERE
        	complete = false;//MADE CHANGE HERE!
        }

        if(complete == false && winner == 1)
        {
            //Display the results of player 1 winning.
            System.out.println("Player 1 Wins!");
            winner = 0;
        }

        if(complete == false && winner == 2)
        {
            //Display the results of player 2 winning.
            System.out.println("Player 2 Wins!");
            winner = 0;
        }
        return winner;

    }
}



Well there you have it, now you have the full code working for what you've implemented so far. Hope you learned some new things through my comments.



Now you can get going on the other elements of the game: like setting limits on how much the player can take from a pile at a time. Good luck!



EDIT:

The
NimGame nimGame;
at the top of the second class is not needed.

This post has been edited by eZACKe: 19 June 2010 - 03:45 PM

Was This Post Helpful? 2
  • +
  • -

#3 deja  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 19-June 10

Re: Nim Game Java

Posted 19 June 2010 - 03:43 PM

the littlest things screw up the whole program, thank you for finding that. I took out the extra call method. The subtracting is working now.. Looking over the other stuff now.
Was This Post Helpful? 0
  • +
  • -

#4 eZACKe  Icon User is offline

  • Garbage Collector

Reputation: 120
  • View blog
  • Posts: 1,278
  • Joined: 01-June 09

Re: Nim Game Java

Posted 19 June 2010 - 03:46 PM

No problem! If you have any questions about what I did feel free to ask.
Was This Post Helpful? 1
  • +
  • -

#5 deja  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 19-June 10

Re: Nim Game Java

Posted 19 June 2010 - 04:39 PM

I know this isn't right, but what do I put in to replace _board[0]

I'm wanting to take the value of each pile / 2 to make sure you can't take more than half the pile.

//Only allow user to take half the pile.
          while ( stones > _board[0]/ 2 )
            {
               //Display error message, and ask user to re enter number.
               System.out.print("Invalid number, You can't take more than half the pile");
               stones = input.nextInt();
            }

Was This Post Helpful? 0
  • +
  • -

#6 eZACKe  Icon User is offline

  • Garbage Collector

Reputation: 120
  • View blog
  • Posts: 1,278
  • Joined: 01-June 09

Re: Nim Game Java

Posted 19 June 2010 - 05:05 PM

Well you're thinking about it right, but it seems you're missing some points.

Let's walk through what we want to do here (full code at bottom):

First we want to know what half of the pile we're trying to take stones from is, you're basically correct in your thinking (in NimClass):
_board[pile - 1] /2



But alas, if we only have 1 left we don't want this to be the case, we can implement that like this:
  if (_board[pile - 1] /2  >= stones || _board[pile-1] == 1)
        {
          _board[pile - 1] -= stones;
          return true;
        }



Okay, now the part that is a little more complicated is telling the player that he needs to choose again. I do this by uses a "boolean flag". You'll see how this works in my code example.

At the top of NimGame we'll want this global variable:
public static boolean flag = true;



Now we change the flag to false if the user entered too large of a number:
else
        {
          System.out.println("Invalid number of stones");
          NimGame.flag = false;
          return false;
        }



Then back in NimGame we just modify what you've already done:

 //Determine what player is entering the values.
            if (player == 1 && flag == true)
            {
                player = 2;
            }
            else if(player == 1 && flag == false)
            {
            	player = 1;
            	flag = true;//set the flag back to true
            }
            else if(player == 2 && flag == true)
            {
                player = 1;
            }
            else
            {
            	player = 2;
            	flag = true;
            }
            





So when we put it all together we get this:

NimGame:
import java.util.Scanner;

public class NimGame
{
	public static int player = 1;//THIS IS A FIX
	public static boolean flag = true;

	
    public static void main(String[] args)
    {

        //Declare variables
        //TOOK player AWAY HERE AND MADE IT GLOBAL STATIC
        int pile = 0;//which pile to pick from
        int stones = 0;//how many stones to pick
        int counter = 0;//if the game is over or not -> 0 not over
        int move;

        //Scanner 
        Scanner input = new Scanner(System.in);

        NimClass myAssistant = new NimClass();
        myAssistant.displayBoard();//board gets set up

        //Begin loop
        while(counter == 0)
        {
        //Choose pile you want to remove stones from.
        System.out.print("Player " + player + " Please enter the pile you wish" +
                         " to remove from. (1, 2, 3 or 4)\n");
        pile = input.nextInt();//get a pile number
      
        //Enter # of stones you want to remove.
        System.out.print("Player " + player + " Please enter the amount of" +
                          " stones you wish to remove\n");
        stones = input.nextInt();
        
        
        myAssistant.playerMove(pile, stones);
        

        
        

            //Determine what player is entering the values.
            if (player == 1 && flag == true)
            {
                player = 2;
            }
            else if(player == 1 && flag == false)
            {
            	player = 1;
            	flag = true;//set the flag back to true
            }
            else if(player == 2 && flag == true)
            {
                player = 1;
            }
            else
            {
            	player = 2;
            	flag = true;
            }
            

             //Display board / determine the winner of the game.
             myAssistant.displayBoard();
             myAssistant.determineWinner();


            if (myAssistant.determineWinner() != -1)
                counter = 1;

        }
        
       
       
        }
    
   
    


    }



NimClass:
public class NimClass
{
    //Declare varaiables
    private int [] _board;//the board for the game -> just an array

    
    public NimClass()
    {
    	
    	
        //Determing # of stones in each pile at the beginning.
        _board = new int [4];
        _board[0] = 3;//pile 1 - 3 stones
        _board[1] = 5;//pile 2 - 5 stones
        _board[2] = 7;//pile 3 - 7 stones
        _board[3] = 9;//pile 4 - 9 stones

        System.out.println("Welcome to the Game of Nim\n" +
                           "You'll need to first pick a pile\n" +
                           "Then select how many stones you wish to remove\n");
    }


   //Display the game board
    public void displayBoard()//just setting up the board with default values
    {
        for(int row = 0; row < 4; row++)
        {
            if(_board[row] == 0)
                System.out.print("    0    ");
            else
                System.out.print("     " + _board[row] + "   ");
        }
            //Print out the piles
            System.out.println("\n  Pile 1   Pile 2   Pile 3   Pile 4\n");

    }

    //Determine the player's moves
    public boolean playerMove (int pile, int stones)
    {
      if ((pile < 1) || (pile > _board.length))
      {
          return false;//user specified wrong pile
      }

        if (_board[pile - 1] /2  >= stones || _board[pile-1] == 1)
        {
          _board[pile - 1] -= stones;
          return true;
        }
     else
        {
          System.out.println("Invalid number of stones");
          NimGame.flag = false;
          return false;
        }
    }


    //Determine the winner of the game
    public int determineWinner()
    {
        boolean complete = true;
        int winner = -1;

        //Checking the piles to see if they're empty.
        if((_board[0] == 0) && ( _board[1]== 0) && ( _board[2]==0) && ( _board[3]==0))
        {
        	winner = NimGame.player;//FIXED THIS HERE
        	complete = false;//MADE CHANGE HERE!
        }

        if(complete == false && winner == 1)
        {
            //Display the results of player 1 winning.
            System.out.println("Player 1 Wins!");
            winner = 0;
        }

        if(complete == false && winner == 2)
        {
            //Display the results of player 2 winning.
            System.out.println("Player 2 Wins!");
            winner = 0;
        }
        return winner;

    }
}





This seems to work on my computer how it's suppose to.

Hope it helps!


If it's confusing at all let me know and I'll explain in more detail.

This post has been edited by eZACKe: 19 June 2010 - 05:24 PM

Was This Post Helpful? 0
  • +
  • -

#7 m-e-g-a-z  Icon User is offline

  • Winning
  • member icon


Reputation: 497
  • View blog
  • Posts: 1,453
  • Joined: 19-October 09

Re: Nim Game Java

Posted 19 June 2010 - 05:29 PM

winner = NimGame.player;//FIXED THIS HERE


Wouldn't it be easier to pass player within the methods constructor and make it take an int in its params since you are invoking the determineWinner(); method on the NimClass object in the main().
Was This Post Helpful? 0
  • +
  • -

#8 eZACKe  Icon User is offline

  • Garbage Collector

Reputation: 120
  • View blog
  • Posts: 1,278
  • Joined: 01-June 09

Re: Nim Game Java

Posted 19 June 2010 - 05:31 PM

Sure, you could also do it that way. Just wasn't the way I thought of it.
Was This Post Helpful? 0
  • +
  • -

#9 deja  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 19-June 10

Re: Nim Game Java

Posted 19 June 2010 - 05:50 PM

I'm not familiar with the "flag" concept, after working out a few bugs that I made on my end it's working now! I'll have to look it over a few times to soak it all in.

Thank you so much for your help, you have explained everything really well. I appreciate it a lot!

not sure what you're talking about megaz but some of this stuff is in over my head, and it's given me a headache.. I'll have to look more into it later
Was This Post Helpful? 0
  • +
  • -

#10 eZACKe  Icon User is offline

  • Garbage Collector

Reputation: 120
  • View blog
  • Posts: 1,278
  • Joined: 01-June 09

Re: Nim Game Java

Posted 19 June 2010 - 05:52 PM

A flag just lets me easily check if a condition has been met.

Like in this example whenever the player enters a number that is too high I set the flag.

It allows me to easily check conditions between classes.

Note: there's other ways that are probably better to do things like this, but for the small code like this I find this strategy acceptable.


You're welcome! Glad I could help.

This post has been edited by eZACKe: 19 June 2010 - 05:54 PM

Was This Post Helpful? 0
  • +
  • -

#11 deja  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 19-June 10

Re: Nim Game Java

Posted 19 June 2010 - 06:09 PM

that makes sense, thanks again!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1