views:

2234

answers:

5

I'm making a simple Guess-The-Number game with a GUI. I need to wait on a loop waiting for the user to input a number in a text box and press "OK". How do I wait for an event inside a loop?

Note: I don't want message boxes. This is done in the main window, hence the need to wait for input.

EDIT: I should have explained myself better. I know that there's a loop inside the GUI. What I want is another loop inside a method. Maybe there's a better way to do this. I could code stuff inside the button's event handler, now that I think about it. Although I'd need global variables. Whataver, I'll think about it, but I hope my question is clearer now.

EDIT 2: Sorry that my question wasn't clear and the edit didn't do much help. First of all, the code is too big to be posted here. I'd probably have to post a screenshot of the GUI, so it wouldn't be of much use. Basically, I have two fields, "Max number" and "Number of allowed guesses". The user enters these two and clicks "Play". A new panel becomes available, with a text box and a "Guess" button. The user enters a guess, and the program checks to see if it's correct.

The purpose of the second infinite loop is to avoid global variables. See, each time the user clicks "Play", the game has to generate a new random number as the correct guess. If everything is done inside a method, no problem. But if the "Guess" button's event handler is called multiple times, the number has to be stored as an instance variable of the Form. Sure, it's not big deal, but I think the number should be a property of the method directing the current game, not of the Form.

I'd also have to keep track of the remaining number of guesses outside of the method. Again, it's no big deal. I just want to avoid globals if I can.

Again, I'm sorry that my question wasn't too clear. I'm kind of tired, and I didn't feel like writing too much. If this still isn't clear, then don't bother. I'll think of something.

+5  A: 

C# automatically loops infinitely waiting for events until your form is closed. You just need to respond to the button click event.

Daniel Straight
A: 

You should probably look for a book to actually learn windows programming.

The very basics:

1) There is already an infinite loop deep down in the windows code somewhere. Any windows program is constantly looping and scanning for input.

2) Once input is found, this loop fires off an Event.

3) Your mission, should you choose to accept it, is to write event handlers to handle those events.

Telos
+1  A: 

you are most likely doing it wrong as it has already been pointed out, but you can use this

Application.DoEvents();

to process events when you are on an actual loop

to do it the right way - don't use a loop - use an edit box for the input, then a button - implement the button onclick event

BlackTigerX
+3  A: 

Jason Down's suggestion is wise, create a new GuessingGame class and add it to your project. I know you're worried about "global variables" (which everyone is taught in school never to use unless you absolutely have to), but think about your design specifications for a minute.

But if the "Guess" button's event handler is called multiple times, the number has to be stored as an instance variable of the Form. Sure, it's not big deal, but I think the number should be a property of the method directing the current game, not of the Form.

As an alternative, store an instance of your GuessingGame class in the form. This is not a global variable! You said so yourself, the point of the game is keep track of the guesses and generate new numbers to guess every time "Play" is clicked. If you store an instance of the game in the form then open another form (e.g. a Help or About box), then the game's instance would not be available (thus, not global).

The GuessingGame object is going to look something like:

public class GuessingGame
{
    private static Random _RNG = new Random();
    private bool _GameRunning;
    private bool _GameWon;
    private int _Number;
    private int _GuessesRemaining;

    public int GuessesRemaining
    {
     get { return _GuessesRemaining; }
    }

    public bool GameEnded
    {
     get { return !_GameRunning; }
    }

    public bool GameWon
    {
     get { return _GameWon; }
    }

    public GuessingGame()
    {
     _GameRunning = false;
     _GameWon = false;
    }

    public void StartNewGame(int numberOfGuesses, int max)
    {
     if (max <= 0)
      throw new ArgumentOutOfRangeException("max", "Must be > 0");

     if (max == int.MaxValue)
      _Number = _RNG.Next();
     else
      _Number = _RNG.Next(0, max + 1);

     _GuessesRemaining = numberOfGuesses;
     _GameRunning = true;
    }

    public bool MakeGuess(int guess)
    {
     if (_GameRunning)
     {
      _GuessesRemaining--;
      if (_GuessesRemaining <= 0)
      {
       _GameRunning = false;
       _GameWon = false;
       return false;
      }

      if (guess == _Number)
      {
       _GameWon = true;
       return true;
      }
      else
      {
       return false;
      }
     }
     else
     {
      throw new Exception("The game is not running. Call StartNewGame() before making a guess.");
     }
    }
}

This way, all the data related to the game is encapsulated within the class. Hooking up the events is easy in the codebehind of the form:

GuessingGame game = new GuessingGame();

private void btnPlay_Click(object sender, EventArgs e)
{
    int numberOfGuesses = Convert.ToInt32(txtNumberOfGuesses.Text);
    int max = Convert.ToInt32(txtMax.Text);
    game.StartNewGame(numberOfGuesses, max);
}

private void btnGuess_Click(object sender, EventArgs e)
{
    int guess = Convert.ToInt32(txtGuess.Text);
    bool correct = game.MakeGuess(guess);

    if (correct) 
        lblWin.Visible = true;

    if (game.GameEnded)
    {
        // disable guess button, show loss label
    }
}
John Rasch
+1  A: 

Yes, and What if I am waiting for Speech events, it could happen anytime event when a function is running, I need to handle that without recursively call a function

Patrick