Привет, Пикабу! В прошлых постах 1, 2 я рассказывал об играх.
В этом посте хочу рассказать об игре, которую я хотел написать 7 лет назад, но забросил, потому что не придумал как реализовать пару моментов, а потом мне не хватало времени и стало не до написания игр.
Цели игры: на поле 5x5 собрать руку из 5 карт, в которой будет наилучшая покерная комбинация.
Как видим, цель игра достаточно проста с точки зрения геймплея, но оказалась не так проста с точки зрения разработки, по крайней мере, на тот момент.
Как получилось в итоге можно увидеть на этом видео:
А дальше перейдем к разработке
Разработка
С чего начать разработку карточной игры? С игральных карт.
Для того, чтобы карты можно было различать нам понадобится два свойства:
Создадим скрипт Card, который будет содержать эту информацию. Для удобства заполнения, масть сделаем через перечисления enum
Повторить еще 51 раз и колода карт готова. Теперь можно приступать к реализации геймплея. Как и говорил, нам нужно поле 5х5, заполненное случайными, неповторяющимися картами. Для перемешивания колоды(List<GameObject>) воспользуемся методом ShuffleDeck()
Затем при заполнении будем удалять из колоды карту, которую инициализировали на столе.
Подсчет комбинаций
Когда я писал эту игру, то задача поиска комбинаций показалась мне самой интересной, поэтому её я решал с удовольствием. Будем искать комбинации для техасского холдема.
При поиске нам понадобится свойства карт, которые мы добавили в самом начале и немного математики. Будем держать в уме, что некоторые комбинации в покере перекрывают друг друга, например, каждый флеш-рояль - это стрит флеш, но не каждый стрит-флеш - флеш-рояль
Поэтому искать комбинации будем сверху вниз(от самой сильной к слабой) и если нашлась комбинация, то завершаем дальнейший поиск и выходим из метода.
Не буду перечислять поиск всех комбинаций, напишу несколько примеров.
Как определить, что перед нами флеш-рояль?
Для этого заведем булеву переменную isSameSuit, которая примет значение true, если в нашей руке из 5 карт все будут одной масти. Затем подсчитаем сумму руки, она должна равняться 60 в моей реализации(туз имеет вес -14, а десятка - 10). Если оба этих условия выполняются, то мы нашли его - флеш-рояль! В холдеме вероятность собрать его примерно0.000154%, в моей игре чуточку побольше )
Найдем стрит. Для поиска стрита отсортируем руку в порядке возрастания, затем пробежимся по ней и подсчитаем разность достоинств между следующей и предыдущей - она должна равняться - 1, если же нет, то стрита тут нет. В этом моменте у меня закрался баг, связанный с особенностями стрита, который я заметил только выпустив игру, но уже исправил.
Его суть под спойлером, на тот случай, если кто-нибудь захочет сам предположить, в чем его суть.
Т.к. туз может быть и вначале стрита A, 2, 3, 4, 5 и в его завершении 10, J, Q, K, A, а у нас для туза прописано только высшее достоинство - 14, то комбинация A, 2, 3, 4, 5 не засчитывалась как стрит
Решил я эту коллизию "грязным трюком", если высчитывая разницу я получал ответ отличный от 1, то я проверял, не стоит ли на последнем месте туз, а на предпоследним пятерка. Если это были они, то значит перед нами стрит.
Примерно так был реализован поиск всех комбинаций.
Дальше наступил момент, на котором я застопорился много лет назад: смещение карт и генерация новых. Похожую механику мы можем увидеть у игр 3 в ряд, но как её реализовать у себя тогда я не понимал. В этот раз, подумав несколько дней я формализовал задачу и понял, что вообще требуется.
Если представить, что наше поле - это массив чисел 5х5, а уничтоженные карты это нули, то наша задача - сместить все нули "наверх", а затем на их место сгенерировать новые значения(карты). Тут примеров кода не будет; такое стыдно и нельзя показывать людям : )
На этом закончились самые сложные момент написания. Для поддержания интереса я решил добавить ачивки
и возможность покупать улучшения за монеты, которые можно получить заполнив шкалу комбинаций.
Шкала заполняется за серию безошибочных комбинаций и после заполнения обнуляется, попутно сгенерировав игровые бонусы(доп. время и доп. очки). Говоря о безошибочности - в игре всего одна комбинация считается ошибочной - старшая карта. За неё можно заработать сброс шкалы, минус 20 очков и 5 секунд времени.
Такой получилась моя очередная игра. Немного сумбурная статья, потому что в момент написания игры многие момент кажутся интересными или полезными, а после вычитывания - эти момент выглядят очевидными и будто про них все уже давно знают.
Если возникли вопросы, то буду рад ответить в комментариях.
А поиграть можно по ссылкам ниже:
Браузерная версия
Версия для android playmarket