Суть игры проста. Раздаются две карты, и игрок пытается угадать: окажется ли числовое значение третьей в промежутке значений этих двух. Затем вскрывается третья карта. Масть не важна; важны достоинства карт и их комбинации. То есть если выпали шестерка червей и девятка треф, а третья выпавшая карта — шестерка бубен, комбинация проигрышная. Четверка пик тоже даст проигрышную комбинацию, а семерка треф — выигрышную.
Итак, перед нами стоит две задачи: сымитировать полную колоду карт и логику самой игры, включая предложение пользователю ввести свою догадку. Ах да, еще одно правило: если первые две карты имеют одинаковое достоинство, нет никакого смысла угадывать, потому что в этом случае нельзя победить.
Сценарий обещает быть интересным. Готовы? Тогда переходите к листингу 12.14.
Код
Листинг 12.14. Игровой сценарий aceydeucey
··#!/bin/bash
··# aceyduecey: Дилер выкладывает две карты, и вы должны угадать, попадает ли
··#·· числовое значение следующей карты в колоде между значениями этих двух
··#·· карт. Например, выпали 6 и 8, если следующая карта окажется 7, вы выиграли
··#·· если 9 — проиграли.
··function initializeDeck
··{
····# Создать колоду карт.
····card=1
····while [$card −le 52] # 52 карты в колоде. Вы это знаете, правда?
····do
······deck[$card]=$card
······card=$(($card + 1))
····done
··}
··function shuffleDeck
··{
····# Это не настоящее перемешивание. Это случайное извлечение значений карт
····#·· из массива 'deck' и создание массива newdeck[], представляющего
····#·· "перемешанную" колоду.
····count=1
····while [$count!= 53]
····do
······pickCard
······newdeck[$count]=$picked
······count=$(($count + 1))
····done
··}
··function pickCard
··{
····# Это самая интересная функция: выбор случайной карты из колоды.
····#·· Поиск карты осуществляется в массиве deck[].
····local errcount randomcard
····threshold=10 # Максимальное число попыток, прежде чем признать неудачу
····errcount=0
····# Выбирает из колоды случайную карту, которая еще не была выбрана,
····#·· выполняя не более $threshold попыток. В случае неудачи (чтобы
····#·· избежать зацикливания, когда раз за разом выполняется попытка
····#·· извлечь уже извлеченную карту) выполняется переход к запасному
····#·· варианту.
····while [$errcount −lt $threshold]
····do
······randomcard=$((($RANDOM % 52) + 1))
······errcount=$(($errcount + 1))
······if [${deck[$randomcard]} −ne 0]; then
········picked=${deck[$randomcard]}
········deck[$picked]=0 # Выбрали — удалить ее.
········return $picked
······fi
····done
····# Если сценарий оказался здесь, значит, он не смог выбрать случайную карту,
····#·· поэтому дальше просто продолжается последовательный обход массива
····#·· до обнаружения первой доступной карты.
····randomcard=1
····while [${newdeck[$randomcard]} −eq 0]
····do
······randomcard=$(($randomcard + 1))
····done
····picked=$randomcard
····deck[$picked]=0 # Выбрали — удалить ее.
····return $picked
··}
··function showCard
··{
····# Функция использует операции деления и взятия остатка для определения
····#·· масти и достоинства, хотя в этой игре значение имеет только достоинство.
····#·· Однако для представления важно иметь полную информацию.
····card=$1
····if [$card −lt 1 −o $card −gt 52]; then
······echo "Bad card value: $card"
······exit 1
····fi
····# деление и взятие остатка — школьные годы не были потрачены впустую!
····suit="$(((($card — 1) / 13) + 1))"
····rank="$(($card % 13))"
····case $suit in
······1) suit="Hearts"··;;
······2) suit="Clubs"····;;