Россия и Беларусь начали и продолжают войну против народа Украины!

Урок №7: Добавление уровней сложности в игре «SameGame» на C++/MFC

  Дмитрий Бушуев  | 

  |

  Обновл. 20 Июл 2021  | 

 10293

 ǀ   4 

На этом уроке мы добавим к нашей игре уровни сложности, а также настроим необходимые обработчики событий.

Уровни сложности

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

При нажатии на пункт меню программа инициирует событие, указывающее на то, какой пункт меню был выбран.

Нам же просто нужно поймать это событие с помощью обработчика. Для этого в окне "Представление классов" выберите CSameGameView, а затем нажмите на кнопку "События" (иконка молнии). После чего вы должны увидеть следующую картину:

Обратите внимание на часть "Команды меню". Нажмите на + напротив ID_LEVEL_3COLORS (он соответствует пункту меню "Сложность" > "3 Цвета"). Параметр COMMAND — это обработчик события для выбора пункта меню. Параметр UPDATE_COMMAND_UI — это обработчик события, который позволяет изменить состояние опции меню. Под состоянием подразумевается активно/неактивно или установить/снять флаг выбора пункта меню. В нашем случае мы собираемся поставить галочку напротив выбранного уровня сложности.

Нажмите на стрелочку, которая раскрывает список, соответствующий пункту COMMAND и выберите Add. Повторите то же самое и для UPDATE_COMMAND_UI. Проделайте эти действия для всех ID_LEVEL_3COLORS, ID_LEVEL_4COLORS и вплоть до ID_LEVEL_7COLORS. После того, как вы с этим закончите, мы будем добавлять код.

Начнем с редактирования игровой доски, затем перейдем к Document и закончим на View. В заголовочном файле SameGameBoard.h после m_nRemaining создайте новую переменную-член для хранения количества цветов:

Также нам потребуется добавить в public-раздел 2 функции. С помощью первой функции мы сможем устанавливать значение количества цветов, а с помощью второй — сможем это значение считывать.

Файл SameGameBoard.h:

Функция SetNumColors() ограничивает набор значений числом от 3 до 7 в соответствии с параметрами нашего меню. Так как мы добавляем дополнительные цвета, то нам нужно увеличить массив m_arrColors.

Файл SameGameBoard.h:

Теперь в исходном файле для игрового поля нам нужно обновить несколько дополнительных функций и массив цветов. Конечно, нам также нужно не забыть обновить конструктор.

Файл SameGameBoard.cpp:

Теперь рассмотрим функцию SetupBoard(). В предыдущие разы мы зафиксировали количество цветов числом 3. Теперь же нам нужно изменить это значение с 3 на m_nColors, чтобы потом, при помощи функции rand(), получать случайное количество цветов для каждой отдельной партии в игре.

Файл SameGameBoard.cpp:

Теперь перейдем к Document. Нам нужно добавить функции, чтобы View мог изменить количество цветов. Функцию GetNumColors() следует поместить в public-раздел Document заголовочного файла SameGameDoc.h. Также нам необходимо добавить реализацию функции SetNumColors().

Файл SameGameDoc.cpp:

На данный момент, это все изменения, которые нам потребовалось внести в Document. Вы наверняка уже заметили, что мы не внесли соответствующие правки во View и поэтому пока не можем пользоваться данными функциями. Последний шаг — это отредактировать View. При добавлении обработчиков событий в заголовочный файл SameGameView.h, автоматически должны были прописаться следующие прототипы функций.

Файл SameGameView.h:

При этом вы могли заметить пару вещей в новых прототипах, которые в коде раньше не встречались. Обозначение afx_msg указывает на то, что функция является обработчиком событий. Функции, начинающиеся с OnUpdateLevel…(), используют указатель на объект CCmdUI. Мы поговорим об этом чуть позже, но это именно тот способ, с помощью которого мы будем воздействовать на меню, изменяя его состояние на активное/неактивное и устанавливая метку выбрано/не выбрано для подпунктов меню. В исходный файл SameGameView.cpp нужно добавить некоторое количество дополнительного кода:

Карта сообщений (MESSAGE_MAP) — это список макросов в языке C++, которые связывают событие с соответствующим обработчиком. Данный список генерируется автоматически, вам не нужно будет его редактировать. Функции OnLevel*colors() (вместо * пишется номер от 3 до 7) практически одинаковые и имеют следующий вид.

Файл SameGameView.cpp:

Во всех функциях представления View нам нужно сначала получить указатель на Document. Затем мы устанавливаем количество используемых цветов, которое указано в имени соответствующей функции, т.е. OnLevel3colors() вызывает SetNumColors(3) и так далее. В конце мы перерисовываем View. Эти действия необходимо повторить для всех обработчиков событий пунктов меню. После того, как все эти шаги будут выполнены, можно скомпилировать и запустить наш проект. Вы увидите, что количество цветов изменяется от 3 до 4 и так далее. Как вариант, можно попробовать рассмотреть возможность создания вспомогательной функции, которая выполнит за вас всю эту работу, принимая количество цветов в качестве аргумента. Например, в заголовочном файле SameGameView.h добавляем следующий прототип функции:

А в SameGameView.cpp добавим следующий код:

Теперь вернемся к последней группе обработчиков. Обработчики событий ON_UPDATE_COMMAND_UI вызываются при раскрытии списка меню по команде пользователя (по одной функции для каждого пункта меню). Затем используется функция SetCheck() объекта CCmdUI для установки/снятия флажка выбора уровня сложности. Как всегда, начинаем с получения указателя на Document, а затем проверяем количество выставленных на доске цветов.

Файл SameGameView.cpp:

И снова вы можете заметить, что все функции OnUpdateLevel*colors() практически идентичны друг другу, за исключением числа, с которым мы сравниваем GetNumColors(). Все эти пять функций вызываются при отображении меню уровня сложности для установки или снятия флажка выбора пользователя. Теперь ваша игра должна выглядеть примерно следующим образом:

Заключение


На этом уроке мы сделали нашу игру интереснее, добавив 4 новых уровня сложности. Мы также узнали о редакторе меню и о том, как это меню настроить. Научились устанавливать обработчики событий меню для типов событий ON_COMMAND и ON_COMMAND_UPDATE_UI. На следующем уроке мы добавим новые опции, позволяющие задать количество и размер блоков на игровом поле.

  GitHub / Исходный код — Урок №7: Добавление уровней сложности в игре «SameGame» на C++/MFC

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (20 оценок, среднее: 5,00 из 5)
Загрузка...

Комментариев: 4

  1. Валерий:

    В файле SameGameBoard.cpp в функции:

    Вызов SetupBoard(); не нужен, так как он уже есть в CSameGameDoc.cpp:

    1. Avatar photo Дмитрий Бушуев:

      Добрый день.
      Посмотрел я плотнее код игры и не нашел какого-то сакрального смысла в вызове SetupBoard() в конструкторе. Автор оригинала, на основе которого был выполнен перевод, далее в своих статьях мельком упоминает такую фразу "мы исходим из предположения, что у нас всегда есть указатель на доску"… Метод SetupBoard(), если доски нет, создаёт её и определяет соответствующий указатель. А самый ранний момент, когда можно создать указатель на доску, чтобы он "всегда был", это непосредственно в конструкторе объекта доски. Видимо поэтому он и запихнул в него лишний вызов SetupBoard(). Как-то так… 🙂

  2. Raimok:

    В последней (на момент написания комментария) версии VS столкнулся с тем, что вместо понятных буквенных литералов новым кнопкам присваиваются безымянные цифровые ID (ID_32772 и так далее в моем случае). Подозреваю, что это нормальная ситуация в таком случае. Решением проблемы является переход в режим редактирования меню из прошлого урока, затем щелчок ПКМ на любом пункте меню, проставить галочку на "Изменить идентификаторы", затем, при двойном нажатии на любой пункт меню вылезет менюшка свойств этого меню (у меня справа), где, в поле ИД можно выбрать из уже имеющихся или прописать свой пользовательский. После этого отображение в свойствах SameGameView будет идентичным.

    1. Alexandr:

      Спасибо!

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *