Справочник Жаркова по проектированию и программированию искусственного интеллекта. Том 8: Программирование на Visual C# искусственного интеллекта. Издание 2. Продолжение 1
Шрифт:
Игра в очко может иметь одно из следующих состояний в течение всей игры:
игрок выдаёт карты себе или Компьютеру (the player is making his or her moves);
игрок перебрал карты (the player busted);
игрок выиграл (the player has won);
банкомёт (dealer) осуществляет набор карт (the dealer is making his or her moves.);
банкомёт перебрал карты (the dealer busted);
банкомёт выиграл (the dealer has won);
счёт равный (the score is tied, known as a push).
В каждом из этих состояний рисунок экрана будет различным, как ответ
public enum GameMode
{
LoadingDisplay,
PlacingBets,
PlayerActive,
PlayerWon,
PlayerBust,
PocketJack,
DealerActive,
DealerWon,
DealerBust,
Push
}
Переменная типа GameMode сохраняет состояние игры. Эта переменная управляет перерисовкой экрана. Когда состояние игры изменяется, должен произойти ряд действий. Лучший способ получить это поведение состоит в том, чтобы осуществить управление посредством свойства следующим образом:
GameMode modeValue;
GameMode mode
{
get
{
return modeValue;
}
set
{
switch (value)
{
case GameMode.LoadingDisplay:
BetMinusToolStripMenuItem1.Enabled = false;
BetPlusToolStripMenuItem.Enabled = false;
HitMeToolStripMenuItem.Enabled = false;
StayToolStripMenuItem.Text = "Point";
StayToolStripMenuItem.Enabled = false;
MenuToolStripMenuItem.Text = "21";
MenuToolStripMenuItem.Enabled = false;
break;
…
modeValue = value;
this.Invalidate;
}
}
Когда свойству задано значение value, выполняется часть набора свойства после ключевого слова set. Когда код набора set выполнен, переключатель switch устанавливает приложение нужным способом. Например, когда состояние свойства изменено в состояние PlayerActive, активизированы команды меню Hit и Stay. Везде, где происходит изменение состояния в основном приложении, пользовательский интерфейс находится всегда в нужном состоянии. Это также означает, что мы должны изменить конфигурацию игры только в одном месте кода. Отметим, что, когда состояние игры изменено, вызывается метод Invalidate для обновления экрана.
Состояние игры (game state) также управляет рисованием, когда вызывается событие Paint, как показано в следующем коде:
void paintForm(Graphics g)
{
switch (mode)
{
…
case GameMode.PlayerActive:
dealerHand.DrawHand(g, 10, 30, 80, 25);
playerHand.DrawHand(g, 10, 135, 20, 25);
Utilities.BigText(playerHand.BlackJackScoreHand.
ToString, 140, 150, Color.Black,
Color.Yellow, messageFont, g);
break;
…
Этот код с методом Paint показывает, как приложение управляет выводом сообщений и карт. Очки банкомёта не появляются, когда игрок набирает карты.
1.11. Набор карт банкомётом
Банкомёт (dealer)
// clear the hands
playerHand.Clear;
dealerHand.Clear;
// deal the face down hole card
dealerHoleCard = shoe.DealCard;
dealerHoleCard.FaceUp = false;
dealerHand.Add(dealerHoleCard);
// deal the first player card
playerHand.Add(shoe.DealCard);
// deal the second dealer card (face up)
dealerHand.Add(shoe.DealCard);
// deal the second player card
playerHand.Add(shoe.DealCard);
…
mode = GameMode.PlayerActive;
Приложение сохраняет ссылку на "тайную – hole" карту банкомёта, которая инициализируется лицевой стороной вниз, когда начинается набор карт. Это достигается заданием свойству FaceUp (Лицевая сторона вверх) значения, равное False. Когда экран будет перерисовываться, будет нарисована также и обратная сторона "тайной – hole" карты банкомёта. Когда банкомёт начинает набор карт, свойству FaceUp (Лицевая сторона вверх) задаётся значение True, и изображение на лицевой стороне карты становится видимым. Отметим, что изменение режима (mode) внизу приведённого кода переводит игру в активное состояние, когда игрок готов принять участие в игре.
Приложение сдаёт карты в том же самом порядке, как в реальной игре с банкомётом и игроком, по очереди берущими карты. Нет никакой программируемой причины для замены между банкомётом и игроком, но в реальной игре проще "расположить в стеке" колоду, если сдача карт не чередуется.
1.12. Набор карт игроком
Приложение содержит метод, который вызывается, когда игрок хочет набрать себе карты. Он получает дополнительную карту, только если счёт – меньше 21, как показано в следующем коде:
void playerHits
{
if (playerHand.BlackJackScoreHand < 21)
{
playerHand.Add(shoe.DealCard);
if (playerHand.BlackJackScoreHand > 21)
{
//We write in the original:
pot.DoPlaceBet;
pot.HouseWins;
showPot;
mode = GameMode.PlayerBust;
}
this.Invalidate;
}
}
Если счёт игрока превышает 21, игрок совершил перебор карт (the player busts), и состояние игры изменяется, чтобы отобразить это. Иначе, экран обновляется, что вызывает перерисовку и добавление на экран новой карты.
Когда игрок достиг счёта, которым он доволен, игрок может приостановить (stay) набор новой карты, как показано в следующем коде:
void playerStays
{
dealerHoleCard.FaceUp = true;
mode = GameMode.DealerActive;
this.Refresh;
System.Threading.Thread.Sleep(750);
while (dealerHand.BlackJackScoreHand < 17)
{
dealerHand.Add(shoe.DealCard);
this.Refresh;
System.Threading.Thread.Sleep(750);
}
if (dealerHand.BlackJackScoreHand > 21)