C # WinForms: ожидание нажатия кнопки внутри бесконечного цикла - PullRequest
0 голосов
/ 17 июня 2009

Я делаю простую игру "Угадай число" с графическим интерфейсом. Мне нужно подождать в цикле, ожидая, пока пользователь введет число в текстовое поле и нажмет «ОК». Как мне ждать события внутри цикла?

Примечание: я не хочу сообщений. Это делается в главном окне, поэтому необходимо дождаться ввода.

РЕДАКТИРОВАТЬ: Я должен был объяснить себя лучше. Я знаю, что внутри GUI есть петля. Я хочу еще один цикл внутри метода. Может быть, есть лучший способ сделать это. Я мог бы написать код в обработчике событий кнопки, теперь, когда я об этом думаю. Хотя мне нужны глобальные переменные. Как бы то ни было, я подумаю об этом, но надеюсь, теперь мой вопрос прояснится.

РЕДАКТИРОВАТЬ 2: Извините, что мой вопрос не был ясным, и редактирование не сильно помогло. Во-первых, код слишком велик для размещения здесь. Вероятно, мне придется опубликовать снимок экрана с графическим интерфейсом, так что он будет бесполезен. По сути, у меня есть два поля: «Максимальное количество» и «Количество разрешенных предположений». Пользователь вводит эти два и нажимает кнопку «Играть». Становится доступной новая панель с текстовым полем и кнопкой «Угадай». Пользователь вводит предположение, и программа проверяет, правильно ли оно.

Цель второго бесконечного цикла - избежать глобальных переменных. Смотрите, каждый раз, когда пользователь нажимает кнопку «Играть», игра должна генерировать новое случайное число в качестве правильного предположения. Если все сделано внутри метода, нет проблем. Но если обработчик события кнопки «Угадай» вызывается несколько раз, число должно быть сохранено как переменная экземпляра формы. Конечно, это не имеет большого значения, но я думаю, что число должно быть свойством метода, направляющего текущую игру, а не формы.

Мне бы также пришлось отслеживать оставшееся количество догадок вне метода. Опять же, это не страшно. Я просто хочу избегать глобалов, если смогу.

Опять же, мне жаль, что мой вопрос не был слишком ясным. Я немного устал, и мне не хотелось писать слишком много. Если это все еще не ясно, не беспокойтесь. Я подумаю о чем-то.

Ответы [ 5 ]

5 голосов
/ 17 июня 2009

C # автоматически зацикливается, ожидая событий, пока ваша форма не будет закрыта. Вам просто нужно ответить на событие нажатия кнопки.

3 голосов
/ 17 июня 2009

Предложение Джейсона Дауна мудро, создайте новый класс GuessingGame и добавьте его в свой проект. Я знаю, что вы беспокоитесь о «глобальных переменных» (которые все учат в школе никогда использовать, если в этом нет особой необходимости), но задумайтесь над вашими проектными характеристиками на минуту.

Но если обработчик события кнопки «Угадай» вызывается несколько раз, номер должен быть сохранен как переменная экземпляра формы. Конечно, это не имеет большого значения, но я думаю, что число должно быть свойством метода, направляющего текущую игру, а не формы.

В качестве альтернативы, сохраните экземпляр вашего класса GuessingGame в форме. Это не глобальная переменная! Вы сами так сказали, смысл игры в том, чтобы отслеживать догадки и генерировать новые цифры, чтобы угадывать каждый раз, когда нажимается «Играть». Если вы сохраните экземпляр игры в форме, а затем откроете другую форму (например, окно «Справка» или «О программе»), экземпляр игры будет недоступен (то есть не является глобальным).

Объект GuessingGame будет выглядеть примерно так:

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.");
        }
    }
}

Таким образом, все данные, относящиеся к игре, инкапсулированы в классе. Подключить события легко в коде за формой:

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
    }
}
1 голос
/ 23 ноября 2009

Да, и что, если я жду событий Речи, это может произойти в любое время, когда функция работает, мне нужно обработать это без рекурсивного вызова функции

1 голос
/ 17 июня 2009

вы, скорее всего, делаете это неправильно, как уже было указано, но вы можете использовать это

Application.DoEvents ();

для обработки событий, когда вы находитесь в реальном цикле

чтобы сделать это правильно - не используйте петлю - используйте поле ввода для ввода, затем кнопку - реализовать кнопку onclick event

1 голос
/ 17 июня 2009

Возможно, вам стоит поискать книгу, чтобы научиться программировать на Windows.

Самые основы:

1) В коде Windows где-то уже есть бесконечный цикл. Любая программа Windows постоянно зацикливается и сканирует для ввода.

2) Как только вход найден, этот цикл запускает событие.

3) Ваша миссия, если вы решите ее принять, - написать обработчики событий для обработки этих событий.

...