Labels, Textboxes and Buttons
You will construct a form-based program to play the ancient game of Nim. In the game of Nim, 2 players would remove objects from a pile in alternating moves. The player could remove 1, 2, or 3 objects at a time. The player who is forced to remove the last object from the pile loses the game.
The game that you will implement will have the players remove integer values of 1, 2, or 3 from a total value. Initially when the game is started, the total value will be 21. The player who is forced to remove the last value, making the total 0, loses the game.
Create the form shown below. Initially, the two textboxes for number entry, and the Play button, will be disabled.

When the Start button is pressed, the program will randomly select the player to make the first play. Enable the textbox for the selected player, and the set the focus (for input) to that textbox. The Start button will be disabled until the game is over. The selected player will enter an integer value of 1, 2 or 3. If a non-integer string was entered, or a value outside the range of 1, 2 or 3 was entered, a MessageBox will be used to display an error message. Also, if the value entered by the user exceeds the current total, an error message will be shown using a MessageBox. The value entered by the player will be deducted from the current total value. After each player has entered a value, that player's textbox will be cleared then disabled and the next player's textbox will be enabled and given the focus. After each move, the current total will be checked to determine if it has reached zero. When the current total reaches zero, the player who made the last move loses the game. A label will be used to display who is to make the next play, and the winner of game.


I know the instruction is very long, and i am sorry for that.
My problem in this programming is that i could not switch from player 1 to player 2.
i want to go randomly select either player 1 or 2 after pressing the "Start" Button, i just don't know how put in my code.

So far i have this:
namespace ICA2___Kristian_V
{
  public partial class Form1 : Form
  {
  int i_Play = 0;  //Player 1 or 2
  int m_Total = 21;  //Starting Number of the Game
 
  public Form1()
  {
  InitializeComponent();
  }
  private void Form1_Load(object sender, EventArgs e)
  {
  BTn_Play.Enabled = false;
  TBx_P1.Enabled = false;
  TBx_P2.Enabled = false;
  }
  private void BTn_Start_Click(object sender, EventArgs e)
  {
  BTn_Start.Enabled = false;
  BTn_Play.Enabled = true;
  TBx_P1.Enabled = true;
  TBx_P2.Enabled = true;

 
  }
  private void BTn_Play_Click(object sender, EventArgs e)
  {
  i_Play = int.Parse(TBx_P1.Text);
  m_Total = m_Total - i_Play;

  LBl_CNum.Text = m_Total.ToString();
  
  if ((i_Play < 1) || (i_Play > 3) || (i_Play > m_Total))
  {
  MessageBox.Show("Error: You must play 1, 2, 3 or less than the total.",
  "ICA 2 - Nim", MessageBoxButtons.OK, MessageBoxIcon.Error);
  TBx_P1.Enabled = true;
  TBx_P1.Focus();
  TBx_P2.Enabled = false;
  }
  else
  {
  TBx_P1.Enabled = false;
  TBx_P1.Focus();
  TBx_P2.Enabled = true;
  }
 
  }

  }
}
Attachments ica2-1.jpg 9.32 KB ica2.jpg 33.83 KB

When the user clicks Start, you don't want both player's boxes to be enabled. You only want one player's box to be enabled. In the BTn_Start_Click() method, you need to randomly select Player 1 or Player 2 to start.

You can do this with the Random class:

Random r = new Random();
// r.Next(x) returns a random integer from 0 to x-1
int player = r.Next(2) + 1;
if (player == 1)
{
  TBx_P1.Enabled = false;
}
else if (player == 2)
{
  TBx_P2.Enabled = false;
}

I haven't tested the code, but it should give you an idea of what to do.

One other issue with your code is that you subtract i_Play from m_Total and set the CNum label's text before doing any input checking. You need to do that after your error checking once you know that the given input is valid.

Also, lines 39 - 41 need to be revised. First, you don't need to enable or disable any textboxes if there's an error. You just show an error and then the user needs to put a number in the same box again. If you're going to use the Focus() command, you need to check to see which textbox is current enabled with an if statement and then give the currently enabled textbox the focus.

Edited 5 Years Ago by Mouche: n/a

everything is okey except it can not switch from player 1 to player 2.
i can put numbers in player 2 textbox but totally ignore.

If it's not switching between players when there is acceptable input, then you have an issue with your BTn_Play_Click() function. Please post your latest code.

Use Select() instead of Focus().
Focus() sets the visible cues of focus, it does not change the active control.

In BTn_Play_Click() at line 30 you only get input from TBx_P1.Text.
You need to choose which input box to use.
Testing the TBx_P1.Enabled property should work here.

If you are using random player start (or otherwise) then you could try toggling the current user like this.

TBx_P1.Enabled = !TBx_P1.Enabled; // toggle Enabled for player 1
TBx_P2.Enabled = !TBx_P1.Enabled; // set player 2 to not player 1
if (TBx_P1.Enabled)
    TBx_P1.Select(); // select player 1 if enabled
if (TBx_P2.Enabled)
    TBx_P2.Select(); // select player 2 if enabled

Edited 5 Years Ago by nick.crane: n/a

Everything working except everytime i put > 3 or < 1 is still substracting.

public partial class Form1 : Form
    {
        int i_Play = 0;                             //Player 1 or 2
        int m_Total = 21;                           //Starting Number of the Game

        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            BTn_Play.Enabled = false;
            TBx_P1.Enabled = false;
            TBx_P2.Enabled = false;
            LBl_msg.Text = string.Format("Press start to play");
        }
        private void BTn_Start_Click(object sender, EventArgs e)
        {
            BTn_Start.Enabled = false;
            BTn_Play.Enabled = true;
            TBx_P1.Enabled = !TBx_P1.Enabled;
            TBx_P2.Enabled = !TBx_P1.Enabled;
            if (TBx_P1.Enabled)
            {
                TBx_P1.Select();
                LBl_msg.Text = string.Format("Player number 1 plays.");
            }
            else if (TBx_P2.Enabled)
            {
                TBx_P2.Select();
                LBl_msg.Text = string.Format("Player number 2 plays.");
            }            
        }
        private void BTn_Play_Click(object sender, EventArgs e)
        {
            if (TBx_P1.Enabled)
            {
                try
                {
                    i_Play = int.Parse(TBx_P1.Text);
                    m_Total = m_Total - i_Play;
                    LBl_CNum.Text = m_Total.ToString();
                    if ((i_Play < 1) || (i_Play > 3) || (i_Play > m_Total))
                    {
                        MessageBox.Show("Error: You must play 1, 2, 3 or less than the total.",
                            "ICA 2 - Nim", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        TBx_P1.Enabled = true;
                        TBx_P1.Focus();
                        TBx_P2.Enabled = false;
                    }
                    else
                    {
                        TBx_P1.Enabled = false;
                        TBx_P1.Focus();
                        TBx_P2.Enabled = true;
                    }
                }
                catch (FormatException)
                {
                    MessageBox.Show("Error: An invalid was entered.", "ICA 2 - Nim",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                LBl_msg.Text = string.Format("Player number 2 plays.");
            }
            else if (TBx_P2.Enabled)
            {
                try
                {
                    i_Play = int.Parse(TBx_P2.Text);
                    m_Total = m_Total - i_Play;
                    LBl_CNum.Text = m_Total.ToString();
                    if ((i_Play < 1) || (i_Play > 3) || (i_Play > m_Total))
                    {

                        MessageBox.Show("Error: You must play 1, 2, 3 or less than the total.",
                            "ICA 2 - Nim", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        TBx_P2.Enabled = true;
                        TBx_P2.Focus();
                        TBx_P1.Enabled = false;
                    }
                    else
                    {
                        TBx_P2.Enabled = false;
                        TBx_P2.Focus();
                        TBx_P1.Enabled = true;
                    }
                    
                }
                catch (FormatException)
                {
                    MessageBox.Show("Error: An invalid was entered.", "ICA 2 - Nim",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                LBl_msg.Text = string.Format("Player number 1 plays.");
            }
        }
    }

That's because you subtract the value in line 41 which should be right after line 52. Same holds true for line 70 and 82.

Edited 5 Years Ago by Momerath: n/a

On line 41 and 70, you subtract from m_Total before you have checked the input. If the inpt is wrong, you do not change the focus of the boxes so that the user can put in input again yet you still subtract from m_Total. You should move those lines into the else blocks of the function instead of before the if-else blocks.

Update: Whoops, I had the page up for awhile and didn't refresh to check if someone had posted already.

Edited 5 Years Ago by Mouche: n/a

This article has been dead for over six months. Start a new discussion instead.