Привет. Продолжаем тему написания простых и увлекательных программ с использованием ПТК «Квинт 7» Российская разработка.
В предыдущих постах мы показали как можно просто и быстро написать игрушку типа змеи или сапер .
Но несмотря на то, что это две совершенно разные игрушки, с точки зрения программирования на CFC (в результате спора с одним другом мы пришли к выводу, что этот язык все же ближе к CFC, чем к FBD) по сути это была та же программа с небольшими косметическими изменениями.
В этой статье мы рассмотрим новый пример программирования, написав простую игрушку БлэкДжек с нуля.
Если вам интересна эта тема, добро пожаловать под кат.
Постановка задачи
Задача довольно простая – написать игру в Блэкджек с помощью программного обеспечения Quint 7. Но в процессе изучения правил игры выяснилось, что разновидностей блэкджека существует огромное количество.Начиная от того, сколько колод используется в игре и заканчивая всевозможными опциями типа «страховка от проигрыша», «разделение карт», «удвоение ставки» и т.д. и т.п.
Остановимся на самом простом варианте:
- одна колода
- без возможности удвоения, страховки, дробления и т.д.
- один игрок играет против казино (в нашем случае против ПТК)
Надо сказать, что остальные варианты можно реализовать крайне просто в течение пяти минут, добавив в исходную программу несколько дополнительных проверок.
Задача поставлена, теперь можно приступить к реализации.
И здесь, в отличие от предыдущих примеров, мы начнем с графической части.
Делаем графический интерфейс
Первым делом ищем в интернете картинку для фона.
Например это: Изображение на заднем плане
Это фоновое изображение нам идеально подходит, потому что.
На нем уже есть фишки с номиналами для ставок и кнопка раздачи.
Дальше нам нужны карточки.
Вот здесь и возникла самая большая проблема, потому что… Чертежей колоды карт, подходящей по размеру и стилю, я сразу не нашел.
В результате мне пришлось вооружиться красками и нарисовать все карты самому.
Останется только вставить несколько полей с цифрами, кнопки начала и завершения игры, кнопки «взять другую карту» и «стоп», а также несколько всплывающих картинок с указанием результата игры.
Размещаем все это на нашем фоне и получаем следующую картину: Полный рисунок
Это похоже на путаницу, где элементы накладываются друг на друга и ничего не понятно.
Но мы еще не сделали анимацию.
Когда программа будет готова, большинство элементов будут невидимы и появятся только при заданном условии.
Кроме того, внимательный читатель может заметить очевидную ошибку, которая примерно в 0,00001% случаев приведет к неправильному распределению.
Но ради этого примера я решил оставить всё как есть.
Написание программы
Итак, наша графика уже готова и пришло время ее оживить.Начнем с понимания того, что должно происходить в нашей программе.
1. Нам нужен генератор случайных карт. Здесь воспользуемся старым проверенным методом:
Есть два быстро меняющихся числа, которые становятся «случайными» в тот момент, когда игрок нажимает кнопку.
Делим их друг на друга, отбрасываем целую часть и первые 4 знака после запятой, а весь оставшийся хвост переносим в шкалу 1-52. Далее настраиваем проверку, указывающую, для какого игрока была сгенерирована данная карта.
Таким образом, используя несколько простых алгоритмических блоков, мы за пару минут получили хороший генератор случайных чисел.
2. Теперь сделаем макрос для вытягивания карт игроками.
Здесь задача несколько сложнее.
И как я показал в предыдущих постах, самый простой способ решить эту проблему — выяснить, чего мы действительно хотим от этого макроса.
Входы: — Во-первых, нам нужна команда для добавления карты в набор.
Итак, назовем это: «Добавить карту».
— Дальше нам нужна сама карта, которую мы добавим.
Давайте создадим соответствующий вход и назовем его «карта».
— Кроме того, если мы посмотрим на макрос генерации случайных чисел, то увидим, что он просто выдает случайное целое число в диапазоне от 1 до 52. Однако мы договорились делать одноколодный блэкджек, и поэтому карты не должны повторяться.
.
Таким образом, для анализа нам необходимо добавить два входа: «Открытые карты игрока» и «Открытые карты дилера», чтобы мы могли «видеть», какие карты уже вышли из колоды, и при появлении уже открытой карты генерировать случайную номер еще раз.
И так до тех пор, пока не выпадет одна из ранее невытянутых карт. — Перед каждой новой раздачей нужно брать у игроков все карты и складывать их в колоду.
Поэтому необходим вход «Сброс», который обнулит все карты игрока и дилера.
— Последний ввод «Скрыть карту».
Как уже говорилось выше, правил игры в Блэкджек существует великое множество.
При первичной раздаче дилер может взять себе только одну карту, показав ее игроку, а может и сразу две, одна из которых открыта, а вторая скрыта и дилер раскрывает ее только тогда, когда очередь переходит к нему.
.
С точки зрения вероятности для игрока эти два варианта абсолютно одинаковы.
Но для того, чтобы все было совсем «честно», здесь используется второй вариант (дилер сразу забирает себе две карты), а для этого нам нужна функция, позволяющая скрыть вторую карту дилера в начале раздачи.
рука.
Выходы: — «Карты».
Этот вывод показывает карты игрока и дилера.
- «Еще одна попытка».
Если генератор случайных чисел выбрасывает уже открытую карту, то генерируется эта функция, позволяющая сгенерировать случайное число еще раз.
— «Обработка карт».
Как уже говорилось выше, дилер сразу забирает две карты, одну из которых прячет (в нашем случае код 54).
Однако на самом деле карта уже взята из колоды и игрок не может взять себе такую же карту.
Поэтому для отображения в графическом интерфейсе мы будем использовать первый вывод «Карты», где вторая карта дилера заменяется кодом 54. А вывод «Обработка карт» предназначен для анализа уже выпавших карт и подсчета очков.
В результате получается такой макрос:
Содержание макроса и описание его работы
Макрос предельно простой.
Берем вход «Карта» и сравниваем его со всеми картами, которые уже есть у игроков на руках.
Если он новый ( <> проверка производится по всем сравнениям), затем по блоку алгоритма «24. Комплекс1», добавьте его порядковый номер и запишите его в соответствующую ячейку памяти.
Если проверка на уникальность не прошла, то взводим триггер «21.RS1» и снова начинаем генерировать карты до завершения проверки.
Командой «reset» мы сбрасываем все ячейки памяти и серийный номер раздаваемой карты.
С помощью команды «Скрыть карту» заменяем вторую карту дилера на код 54 (отображается в графическом интерфейсе как рубашка карты).
3. Теперь, когда карты разданы, пришло время подсчитать очки.
Для этого мы создадим макрос «Оценка» со следующими входными и выходными данными.
Входы: — «Карты».
Собственно сам набор карточек, на основании которых мы должны посчитать количество очков.
- «Скрыть карту».
Карманная карта дилера заменяется на ноль очков.
Выходы: - "Очки".
Количество очков, набранных игроком и дилером.
Отображается в графическом интерфейсе.
— «Обработка точек».
Количество набранных очков вместе со скрытой картой дилера.
- "Слишком.
" Логичный признак того, что игрок набрал более 21 очка.
Результатом является этот макрос:
Содержание макроса и описание его работы
Ничего сложного нет. При входе выдается карта.
Далее вложенный макрос преобразует карту в баллы.
Баллы суммируются и проверяются, не превышают ли они порог в 21. Если есть превышение, то с задержкой в 50 мс выводится знак «перебора».
При этом по признаку «Скрыть карту» вторая карта дилера, которая закрыта, равна нулю очков.
Единственный вопрос - задержка в 50 мс.
Для прояснения ситуации рассмотрим вложенный макрос «Обработка карты», который выдает количество очков, соответствующее карте.
и более подробная информация:
У нас есть 52 карты от двойки до туза четырех разных мастей.
Кодируются они следующим образом: 1 – бубновая двойка, 2 – бубновая тройка, … 13 – бубновый туз, 14 – пиковая двойка и т. д. Отсюда и принцип подсчета очков.
Код карты делим с остатком на 13. Частное будет равно масти, а остаток будет равен карте.
При этом нетрудно заметить, что ace-код всегда будет иметь нулевой остаток.
Теперь конвертируем карту в очки.
Если остаток от деления лежит в диапазоне от 1 до 9, то баллы, которые дает карта, соответствуют остатку плюс один, что реализуется с помощью блока алгоритма «7. Сложный1».
Карты Валет, Дама и Король приносят 10 очков.
А вот с тузом все сложнее.
По правилам игры туз может дать либо 11 очков, либо одно очко, если 11 очков приведут к перебору.
взглянув на блоки алгоритма 3-5 и 9-12, можно увидеть, что изначально туз (частное деления кода карты не равно нулю, а остаток равен нулю) равен 11 очкам, но если «перебор» поступает сигнал, затем срабатывает триггер «10.RS1» и туз уже равен 1 очку.
Поскольку сигнал о переборе приходит по обратной связи с задержкой в 10 мс, то для предотвращения преждевременного поражения игрока (а вдруг перебор случился как раз из-за 11 очков туза) мы установили задержку 50 мс, чтобы успеть пересчитать баллы.
Итоговая программа
Основа нашей программы (рассмотренные выше макросы) готова.Остаётся только разместить их на поле и сделать жгут для контроля и отображения результатов.
Итоговая программа.
Хабрастораж.
Рисунок очень большой.
Итоговая программа.
Радикальный.
Рисунок очень большой.
Краткое объяснение итоговой программы.
В качестве основного элемента управления используется блок алгоритма «1.Ruchselector1».
По команде с операторской станции формирует единицу на соответствующем выходе в течение 10 мс.
В комментариях указано, какой бит что означает. — Для запуска игры первый селектор на первом выходе выставляется на единицу.
Эта команда запускает триггер «3.RS8», который содержит признак того, что игра продолжается.
— Единица на втором выходе селектора сбрасывает все триггеры, обнуляет все счетчики и сохраненные состояния и возвращает программу в исходное состояние.
— Единица на третьем выходе селектора запускает раунд. При этом триггер «14.RS5» взводится только в том случае, если взведен триггер «Идет игра» и одновременно сделана ставка.
После взведения этого триггера запускается формирование 4 импульсов, по которым игроку и дилеру сдаются по две карты.
— Единица на четвёртом выходе формирует импульс, по которому игроку выдаётся очередная карта.
— Блок на пятом выходе взводит триггер «31.RS10» и блокирует игроку вытягивание карт. В это же время начинается раздача карт дилеру.
Здесь внесена одна поправка.
По правилам казино, дилер должен остановиться, как только наберет 17 и более очков, независимо от того, сколько очков у игрока (кстати, это даже написано на фоновой картинке).
Но если игра идет 1 на 1, то это правило не имеет смысла.
Поэтому реализован алгоритм, согласно которому дилер забирает карты до тех пор, пока его очки меньше, чем у игрока.
Разумеется, если у игрока перебор, то дилер вообще не берет карты, т.к.
на этом раунд заканчивается.
— Блок на шестом выходе сбрасывает триггер раунда и сохраненные карты.
Таким образом, программа готова к новому дистрибутиву.
Далее проверяются условия окончания раунда и в случае победы игрока ему присуждается количество фишек, равное ставке, и соответственно такое же количество фишек забирается у дилера.
Если игрок проигрывает, его ставка переходит дилеру.
При равенстве каждый остаётся при своём.
Накопленное количество фишек (а изначально у игрока и дилера по 1000 фишек) сравнивается с нулем (алгоблоки «98.Сравнить8» и «99.Сравнить9») и взводится соответствующий триггер победы или поражения в игре.
Вот и все.
Программа готова.
Компилируем и загружаем все это в контроллер.
Статистика программы
Привязываем нарисованный в самом начале графический интерфейс к сигналам в программе и можно играть.
Исходное состояние
Начало игры
Отдавать
Потеря руки
И мы побеждаем!
Совмещайте с работой :)
Краткие выводы
В отличие от предыдущих примеров, когда задача содержала несколько тысяч блоков алгоритма, в этот раз потребовалось всего 600 штук.Причём, как видите, большая часть блоков алгоритма находится внутри макросов.
Для реализации этой задачи не потребовалось долгое и утомительное изучение справочников или поиск ответов на вопросы в Интернете.
Все написано с использованием простых алгоритмов типа «и», «или», «сложение», «деление», «триггер» и т. д., принцип действия которых понятен даже школьнику.
Причем задача была выполнена менее чем за сутки (весь проект занял 3 дня.
Не полный, конечно.
Около 2-3 часов в день в общей сложности.
Причем первые два дня я рисовал карты в пейнте, делал надписи и другие картинки) получились не громоздкими и при желании их можно легко модифицировать.
Вначале я писал, что блэкджек будет одноколодным.
Итак, за пять минут вы сможете переделать программу под любое количество колод. Достаточно установить в макросе счетчик совпадений при проверке карты на уникальность.
Если колод 3, то одна и та же карта может появиться три раза и поэтому знак «еще одна попытка» должен быть взведен при появлении карты в четвертый раз.
Другие изменения сделать так же легко.
Закончим статью фразой о том, как «на CFC писать программы весело и легко».
Спасибо всем, кто дочитал до конца.
Надеюсь, это было интересно.
ПС.
Ответ на вопрос об ошибке.
В самом начале я написал об ошибке (которую намеренно оставил), приводящей к некорректной раздаче.
Итак, ошибка в том, что слотов для карточек всего восемь.
Теоретически игрок может дополнительно получить 4 двойки, 4 тройки и туз.
В результате даже с восемью картами вам не удастся набрать больше 21 очка.
А т.к.
если слотов для карт не осталось, игроку придется нажать на кнопку «Достаточно» и передать ход дилеру.
Однако вероятность такого распределения очень и очень мала, поэтому эту ошибку было решено оставить на самый внимательный вопрос.
УПД.
Только заметил, что на хабрастораже большое изображение сжато и посмотреть его в нормальном разрешении по предоставленной ссылке (по крайней мере у меня) не представляется возможным.
Перезалил картинку на радикал.
Теги: #ПТК #Квинт 7 #игра своими руками #игра своими руками #Необычное программирование #программирование
-
Паренаго Павел Петрович
19 Oct, 24