Создание игры «Пятнашки» на C++/SFML

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

  |

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

 24371

 ǀ   4 

Игра «Пятнашки» — это механическая игра-головоломка, которая была изобретена в 1878 году почтмейстером из Канастоты (деревня в штате Нью-Йорк, США) Ноем Чепмэном. И хотя официальной датой создания игры значится именно 1878 год, первый вариант своей головоломки Ной продемонстрировал в кругу друзей еще за 4 года до этого.

Уже в 1880 году игра приобрела колоссальную популярность, а спустя всего лишь несколько месяцев в нее уже вовсю играли жители таких стран, как: Эстония, Норвегия, Швеция, Австрия, Латвия, Германия, Англия, Австралия, Дания, Мексика, Италия, Нидерланды и Новая Зеландия.

Игру «Пятнашки» раскупали миллионными партиями, часто люди забывали про еду и сон. Из-за этого на некоторых предприятиях был введен запрет на «Пятнашки». Впоследствии у этого явления даже появилось название «Пятнашечное» сумасшествие.

Стоит отметить, что на данный момент головоломка «Пятнашки» занимает третье место в мире по популярности после Пазлов и кубика Рубика.

Описание игры и её правила

В классическом варианте исполнения игра «Пятнашки» представляет собой квадратное поле размером 4×4 клетки с 15-ю квадратными подвижными элементами, на которые нанесены числа от 1 до 15, и одной свободной ячейкой. Цель игры состоит в том, чтобы, перемещая элементы в горизонтальном или вертикальном направлениях, выстроить числа в правильной последовательности (1, 2, 3, 4 и т.д.).


Приступаем к разработке


Я уже неоднократно об этом говорил (а повторение, как известно, — мать учения), что практически любое SFML-приложение можно начать с нижеследующего минимального каркаса:

Далее нам нужно создать переменную текстуры и загрузить для нее .png-файл изображения, которое содержит графическое представление элементов игры (квадраты с нанесенными на них числами от 1 до 15):

Примечание: .png-файл с изображением для текстуры вы можете найти в конце статьи в исходниках на GitHub (папка images).

Как уже отмечалось выше, «Пятнашки» состоят из 15 подвижных элементов с числами (далее — «блоки») и 1 пустой ячейки, расположенных в 4 строках и 4 столбцах игрового поля. В нашем случае размер одного такого блока будет соответствовать квадрату 64×64 пикселя.

Так как всего будет 16 блоков, то для их графического представления нам потребуется массив из 17 спрайтов. Как вы знаете, в языке С++ нумерация элементов массива начинается с 0, но, т.к. числа на наших блоках начинаются с 1, для простоты мы будем использовать массив не из 16 спрайтов, а из 17. Отсчет первого элемента при этом будем начинать с индекса 1, а не с индекса 0.

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

Это приведет к усложнению нашей программы, ухудшит её читабельность и повысит риск сделать ошибку в коде. Выходом из данной ситуации является добавление с каждого края к нашему массиву (ниже на рисунке он обозначен оранжевым цветом) по одному дополнительному нулевому столбцу/строке (на рисунке они выделены голубым цветом). Отсчет первого элемента данного двумерного массива так же будем начинать с индекса 1, а не с индекса 0 (на рисунке индексы выделены зеленым цветом). Таким образом, модель игрового поля принимает следующий вид:

В коде:

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

Осталось установить наши спрайты на позиции соответствующих блоков игрового поля и произвести их отрисовку:

Теперь можно попробовать запустить программу. В результате у нас должна получиться следующая статичная заготовка:

Примечание: Если у вас ничего не отображается, то попробуйте прописать полный путь к файлу текстуры. Например, вместо:

укажите:

При этом у вас на компьютере должна быть папка C:\images, в которой должен находиться файл 15.png.

Обработка нажатия кнопки мыши

Когда пользователь нажимает левой кнопкой мыши (сокр. «ЛКМ») на каком-либо блоке игрового поля с целью переставить его на пустое место, то мы должны отловить данное событие, а затем проверить, находится ли рядом с этим блоком пустая клетка и если действительно такая клетка присутствует, то нужно задать направление перестановки (через переменные dx и dy).

Ниже представлен код обработчика события щелчка ЛКМ и проверки на присутствие рядом пустой клетки:

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

Снова компилируем, запускаем нашу программу и видим уже следующее:


Добавляем анимацию перемещения


Остался последний штрих — сделать более плавной перестановку выбранного блока на пустое место. Для этого добавим дополнительный цикл for, в котором мы будем двигать выбранный блок с помощью функции sprite[temp.].move(speed*dx, speed*dy);.

На каждой итерации цикла блок будет перемещаться на speed*dx пикселей по горизонтали и на speed*dy пикселей по вертикали:

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

Скомпилировав и запустив нашу программу, мы уже сможем наблюдать финальный результат наших трудов:

  GitHub / Создание игры «Пятнашки» на C++/SFML — Исходный код

Заключение

Вот мы и подошли к концу еще одного урока по C++/SFML. На мой взгляд, он является одним из самых простых примеров быстрого создания относительно несложного игрового приложения. Надеюсь, что каждый, кто дочитал эту статью до конца, сможет найти в ней что-то новое и интересное для себя. Ну а я, как всегда, говорю Вам: «До встречи на следующем уроке!» 🙂

Примечание: Статья написана по мотивам одноименного видеоролика за авторством FamTrinli.


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

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

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

  1. Finchi:

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

  2. Никита:

    Добрый вечер) Поставил себе задачу придумать возможность отменить последний ход. Никак не могу додуматься. Может вы подскажете ? Буду невероятно благодарен)

  3. Erplate:

    Здравствуйте, а как самому создать спрайт? Так и не понял, хоть и посмотрел соответствующий урок у Вас

    1. Иван:

      Разве для спрайта не достаточно просто нарисовать любую картинку и использовать её как текстуры?

Добавить комментарий для Finchi Отменить ответ

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