Каждый может написать игру сокобан на языке C

задняя часть GitHub игра C++

Язык C, как первый язык программирования большинства людей, его важность очевидна.В это время сформировались многие привычки программирования и логические методы. Это игра сокобан, которую я написал после изучения языка C на первом курсе. Мои логические способности улучшились. Здесь я делюсь с вами этим проектом игры сокобан.

Адрес репозитория GitHub:GitHub.com/Sozhiwen/C…

Давайте посмотрим на эффект финального запуска.

最终的效果图

Это небольшая игра на интерфейсе Windows Dos.В интерфейсе есть карта Сокобана.Использовать#представлять границы карты,PЧтобы представить маленького человека Сокобана,Xпредставлять коробку,Oчтобы представить целевую позицию, в которую будет перемещен ящик.

W(w), S(s), A(a), D(d)Двигайтесь вверх, вниз, влево и вправо соответственно злодею.

Чтобы написать эту небольшую игру, мы столкнулись со следующими проблемами.

  • 1. Как сохранить игровую карту?

  • 2. Как работает игра?

  • 3. Как меняется игровая карта, пока локация фиксирована?

  • 4. Как прописать логику движения злодея?

  • 5. Чем заканчивается игра?

1. Как сохранить игровую карту?

В языке C есть только базовые типы данных.Карта игры представляет собой двухмерную плоскую структуру.Легко представить себе использование двумерного массива для сохранения карты игры.Подробнее о коде см. в репозитории GitHub.уровень.чдокумент.

游戏地图

2. Как работает игра?

Поскольку игра Sokoban должна непрерывно принимать вводимые пользователем данные до тех пор, пока игра не закончится, мы можем установить флаг, чтобы определить, окончена ли игра, и установить этот флаг как условие цикла while. В каждом цикле должен быть получен ввод пользователя, и следующая операция будет выполняться в соответствии со значением, введенным пользователем.В игре это направление движения злодея, вверх и вниз, влево и вправо, здесь мы можем использовать оператор switch для суждения. Каждый цикл соответствует пользовательскому вводу.

3. Как меняется игровая карта, пока локация фиксирована?

В каждом цикле текущая карта должна отображаться первой, чтобы облегчить пользователю следующий мобильный ввод. Задаем игровую карту как глобальную переменную, чтобы после перемещения злодея изменения персонажей на карте были постоянными, а затем печатаем новую карту с локальными изменениями. Таким образом, программа непрерывно зацикливается и печатает карту снова и снова.Персонажи на игровой карте могут непрерывно меняться, но положение карты не может быть зафиксировано. Если мы сможем обновить значение в интерфейсе, мы сможем продолжать изменять его, пока положение фиксировано. Суть освежения состоит в том, чтобы удалить старое и приветствовать новое, то есть удалить старое и приветствовать новое. В программе мы можем очистить исходный интерфейс, а затем отобразить новый интерфейс в исходном положении. Доступно на языке Csystem("cls")функция для очистки содержимого консоли, а затем мы отображаем новое содержимое карты.

Логика движения злодея относится к конкретной программной реализации, о ней поговорим ниже, сначала поговорим о том, чем программа заканчивается.

4. Чем заканчивается игра?

Ранее мы говорили, что установка флага определяет, окончена ли игра, но когда игра заканчивается? Цель игры Sokoban — переместить каждую коробку в заданное положение. Это игра окончена. Поскольку каждый цикл необходимо оценивать, его можно записать в виде функции. Кроме того, если пользователь не хочет играть и хочет выйти, это тоже ситуация, когда игра окончена.Здесь я рассматриваю только эти две ситуации.Что касается других ситуаций, читатели могут рассмотреть сами.

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

程序大致框架

5. Как прописать логику движения злодея?

На приведенном выше снимке экрана программы вы можете видеть, что я записал движения злодея вверх, вниз, влево и вправо в четыре функции, а именно MoveToUp(), MoveToDown(), MoveToLeft() и MoveToRight(). На примере функции MoveToUp() разберем логику движения злодея.

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

不能向上移动

В следующей ситуации злодей может двигаться вверх, потому что на вершину злодея нет ограничений.

可以向上移动

Таким образом, мы должны судить о сетке (следующей позиции), в которую теоретически может переместиться злодей. может двигаться, если есть предел, вещи не могут двигаться. Поэтому нам необходимо записать значение координатной точки.Здесь эталонный объект "следующая позиция" может выбрать текущую позицию злодея.При запуске игры начальная позиция злодея используется как текущая позиция. Когда злодей движется вверх, абсцисса «следующей позиции» равна абсциссе текущей позиции злодея минус единица, а ордината — ординате текущей позиции злодея. Затем мы можем найти конкретное значение символа в соответствии с горизонтальными и вертикальными координатами «следующей позиции». Если он пуст, его можно переместить. Если это целевая позиция перемещаемого ящика, злодей также может переместиться. , «Следующая позиция» — это коробка, нам также нужно учитывать «следующую позицию» коробки, и следующую позицию коробки также легко получить. Поскольку злодей и ящик перемещаются по одной и той же линии, когда злодей движется вверх, абсцисса «следующей позиции» ящика равна абсциссе «следующей позиции» злодея минус единица, а ордината двух одинаковых. Точно так же нам также необходимо оценить значение символа «следующей позиции» поля.Если значение символа представляет собой пробел и позицию, в которую можно переместить поле, его можно переместить. Код для злодея, чтобы двигаться вверх, выглядит следующим образом:

小人向上移动

Код перемещения злодея вниз, влево и вправо тоже похож, это не что иное, как изменение следующей координаты движения злодея и движение вниз, абсцисса "следующей позиции" - это положение злодея по оси абсцисс. Добавьте один, две ординаты одинаковы, см. подробности кода в репозитории GitHub.control.cppдокумент.

Даже если вся программа здесь завершена, вы можете запустить всю программу, и эффект будет следующим: вы можете найти какие-либо ошибки?

有Bug的效果图

Я полагаю, вы внимательно заметили, что когда злодей перемещается в целевую позицию, куда нужно переместить ящик, а затем уходит, эта позиция «исчезает».Почему это происходит? Мы всегда обращаем внимание на «следующую позицию», которую хочет переместить злодей, и «следующую позицию», которую хочет переместить ящик, но мы не обращаем внимания на исходное значение этой позиции (предыдущей позиции) перед ходом , мы можем записать это «Однако есть много проблем, которые нужно учитывать, особенно когда ящик и злодей находятся в целевой позиции, куда нужно переместить ящик, ситуация очень сложная, поэтому есть ли простой метод? На самом деле до сих пор в нашей программе вообще проблем не было, но в целевой позиции перемещаемого ящика будет отображаться «персонаж исчезает». Это всего лишь небольшая ошибка, как это делает Microsoft, которая использует пользователей в качестве тестов? После того, как система выпущена, патчи постоянно выпускаются, и мы также можем сделать «патч» для этой программы, как этот. Положение перемещаемого ящика не меняется. Можем ли мы использовать двумерный массив для хранения этих особых положений? Значения этих специальных позиций тоже специальные, либо целевая позиция, либо ящик, либо злодей, но не пустой символ, поэтому мы можем написать «патч» — функцию для исправления этого бага. Когда злодей движется, добавьте следующую функцию ремонта в конце функции движения в каждом направлении. Здесь оценивается, является ли специальная позиция пустым символом.Если это пустой символ, значение специальной позиции изменяется на значение символа целевой позиции.Вот символ «О», который «фиксирует» глюк программы, и "персонаж пропадает" Проблема так же решена.

修复函数

Я разделил программу на разные файлы, а в репозитории GitHub также есть файл описания каталога программы.При чтении кода читатели заметятexternИспользование ключевого слова, это ключевое слово, чтобы совместно использовать переменную или функцию среди разделенных файлов. Заменив игровую карту в уровне, можно реализовать несколько уровней Сокобана.Если читатели заинтересованы, то могут попытаться улучшить его сами.Эта статья также играет роль в привлечении новых идей.

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

Добро пожаловать в мой публичный аккаунт WeChat: «Programming Mind», на пути программирования мы будем расти вместе, и когда вы ответите на любое ключевое слово, будут сюрпризы!

编程心路