MenuToolStripMenuItem.Enabled = true;
//Discontent of support group with our exceeding of
//cards:
Assembly a4 = Assembly.GetExecutingAssembly();
Stream s4 =
a4.GetManifestResourceStream(
"PocketJack.pj_busted.wav");
SoundPlayer player4 = new SoundPlayer(s4);
player4.Play();
break;
case GameMode.DealerBust:
BetMinusToolStripMenuItem1.Enabled = false;
BetPlusToolStripMenuItem.Enabled = false;
HitMeToolStripMenuItem.Enabled = false;
StayToolStripMenuItem.Text = "Distribution of cards";
StayToolStripMenuItem.Enabled = true;
MenuToolStripMenuItem.Text = "Menu";
MenuToolStripMenuItem.Enabled = true;
//An applause in our address for a prize in cards:
Assembly a5 = Assembly.GetExecutingAssembly();
Stream s5 =
a5.GetManifestResourceStream(
"PocketJack.pj_claps.wav");
SoundPlayer player5 = new SoundPlayer(s5);
player5.Play();
break;
case GameMode.Push:
BetMinusToolStripMenuItem1.Enabled = false;
BetPlusToolStripMenuItem.Enabled = false;
HitMeToolStripMenuItem.Enabled = false;
StayToolStripMenuItem.Text = "Distribution of cards";
StayToolStripMenuItem.Enabled = true;
MenuToolStripMenuItem.Text = "Menu";
MenuToolStripMenuItem.Enabled = true;
break;
}
modeValue = value;
this.Invalidate();
}
}
//We load the game objects:
public void init()
{
System.Reflection.Assembly asm =
System.Reflection.Assembly.GetExecutingAssembly();
loadingImage = new Bitmap(asm.GetManifestResourceStream(
"PocketJack.images.loading.gif"));
bankImage = new Bitmap(asm.GetManifestResourceStream(
"PocketJack.images.bank.jpg"));
mode = GameMode.LoadingDisplay;
this.Visible = true;
this.Refresh();
pot = new Pot();
//We create also initsializuy the help Form2 form:
helpForm = new Form2();
}
void startGame()
{
shoe = new CardShoe();
//We comment in the original,
//since this line – only for testing of a game:
//shoe =
//new CardShoe(new byte[] { 2, 14, 11, 25, 10, 7, 6, 5 });
pot.ResetPot();
mode = GameMode.PlacingBets;
}
void startHand()
{
mode = GameMode.PlacingBets;
}
void showPot()
{
this.Text =
"Bank: " + pot.PotValue.ToString() + " Bet: " +
pot.BetValue.ToString();
}
void startPlay()
{
//We commented out in the original:
//pot.DoPlaceBet();
//We write in the original:
if (mode == GameMode.PlayerBust && mode == GameMode.DealerWon)
pot.DoPlaceBet();
showPot();
// 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());
if ((dealerHand.BlackJackScoreHand() == 21) &&
(playerHand.BlackJackScoreHand() != 21))
{
//We write in the original:
pot.DoPlaceBet();
pot.HouseWins();
showPot();
//Discontent of support group with our exceeding of
//cards:
Assembly a2 = Assembly.GetExecutingAssembly();
Stream s2 =
a2.GetManifestResourceStream("PocketJack.pj_busted.wav");
SoundPlayer player2 = new SoundPlayer(s2);
player2.Play();
dealerHoleCard.FaceUp = true;
mode = GameMode.DealerWon;
return;
}
if ((playerHand.BlackJackScoreHand() == 21) &&
(dealerHand.BlackJackScoreHand() != 21))
{
pot.PlayerWins();
showPot();
dealerHoleCard.FaceUp = true;
mode = GameMode.PocketJack;
return;
}
if ((playerHand.BlackJackScoreHand() == 21) &&
(dealerHand.BlackJackScoreHand() == 21))
{
pot.DoPushBet();
showPot();
dealerHoleCard.FaceUp = true;
mode = GameMode.Push;
return;
}
mode = GameMode.PlayerActive;
}
Font messageFont = new Font(FontFamily.GenericSansSerif, 20,
FontStyle.Regular);
void paintForm(Graphics g)
{
switch (mode)
{
case GameMode.LoadingDisplay:
//We draw all images below the menu:
g.DrawImage(
bankImage, 0, StayToolStripMenuItem.Height);
g.DrawImage(
loadingImage, 0, StayToolStripMenuItem.Height + 60);
break;
case GameMode.PlacingBets:
g.DrawImage(bankImage, 0, StayToolStripMenuItem.Height);
Utilities.BigText("Bank : " + pot.PotValue.ToString(),
10, 40, Color.Black,
Color.Yellow, messageFont, g);
Utilities.BigText("Bet : " +
pot.BetValue.ToString(), 10, 80, Color.Black,
Color.Yellow, messageFont, g);
break;
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;
case GameMode.PlayerWon:
case GameMode.PocketJack:
dealerHand.DrawHand(g, 10, 30, 20, 25);
playerHand.DrawHand(g, 10, 135, 20, 25);
Utilities.BigText(dealerHand.BlackJackScoreHand().
ToString(), 140, 45, Color.Black,
Color.Yellow, messageFont, g);
Utilities.BigText(playerHand.BlackJackScoreHand().
ToString(), 140, 150, Color.Black,
Color.Yellow, messageFont, g);
Utilities.BigText("Вы выиграли!",
20, 80, Color.Black, Color.Yellow, messageFont, g);
break;
case GameMode.PlayerBust:
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);
Utilities.BigText("Вы перебрали.",
20, 80, Color.Black, Color.Red, messageFont, g);
break;
case GameMode.DealerActive:
dealerHand.DrawHand(g, 10, 30, 20, 25);
playerHand.DrawHand(g, 10, 135, 20, 25);
Utilities.BigText(dealerHand.BlackJackScoreHand().
ToString(), 140, 45, Color.Black,
Color.Yellow, messageFont, g);
Utilities.BigText(playerHand.BlackJackScoreHand().
ToString(), 140, 150, Color.Black,
Color.Yellow, messageFont, g);
break;
case GameMode.DealerWon:
dealerHand.DrawHand(g, 10, 30, 20, 25);
playerHand.DrawHand(g, 10, 135, 20, 25);
Utilities.BigText(dealerHand.BlackJackScoreHand().
ToString(), 140, 45, Color.Black,
Color.Yellow, messageFont, g);
Utilities.BigText(playerHand.BlackJackScoreHand().
ToString(), 140, 150, Color.Black,
Color.Yellow, messageFont, g);
Utilities.BigText("Вы потеряли.",
20, 80, Color.Black, Color.Red, messageFont, g);
break;
case GameMode.DealerBust:
dealerHand.DrawHand(g, 10, 30, 20, 25);
playerHand.DrawHand(g, 10, 135, 20, 25);
Utilities.BigText(dealerHand.BlackJackScoreHand().
ToString(), 140, 45, Color.Black,
Color.Yellow, messageFont, g);
Utilities.BigText(playerHand.BlackJackScoreHand().
ToString(), 140, 150, Color.Black,
Color.Yellow, messageFont, g);
Utilities.BigText("Dealer Bust",
20, 80, Color.Black, Color.Yellow, messageFont, g);
break;
case GameMode.Push:
dealerHand.DrawHand(g, 10, 30, 20, 25);
playerHand.DrawHand(g, 10, 135, 20, 25);
Utilities.BigText(dealerHand.BlackJackScoreHand().
ToString(), 140, 45, Color.Black,
Color.Yellow, messageFont, g);
Utilities.BigText(playerHand.BlackJackScoreHand().
ToString(), 140, 150, Color.Black,
Color.Yellow, messageFont, g);
Utilities.BigText("Вы выиграли.",
20, 80, Color.Black, Color.Yellow, messageFont, g);
break;
}
}
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();
}
}
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)
{
mode = GameMode.DealerBust;
pot.PlayerWins();
showPot();
return;
}
if (playerHand.BlackJackScoreHand() >
dealerHand.BlackJackScoreHand())
{
mode = GameMode.PlayerWon;
pot.PlayerWins();
showPot();
return;
}
if (playerHand.BlackJackScoreHand() <
dealerHand.BlackJackScoreHand())
{
mode = GameMode.DealerWon;
//We write in the original:
pot.DoPlaceBet();
pot.HouseWins();
showPot();
return;
}
if (playerHand.BlackJackScoreHand() ==
dealerHand.BlackJackScoreHand())
{
mode = GameMode.Push;
pot.DoPushBet();
showPot();
return;
}
}
void doLeftMenuKey()
{
switch (mode)
{
case GameMode.LoadingDisplay:
break;
case GameMode.PlacingBets:
startPlay();
break;
case GameMode.PlayerActive:
playerStays();
break;
case GameMode.PocketJack:
case GameMode.PlayerWon:
case GameMode.PlayerBust:
case GameMode.DealerActive:
case GameMode.DealerWon:
case GameMode.DealerBust:
case GameMode.Push:
startHand();
break;
}
}
void doEnter()
{
switch (mode)
{
case GameMode.LoadingDisplay:
break;
case GameMode.PlacingBets:
startPlay();
break;
case GameMode.PlayerActive:
playerHits();
break;
case GameMode.PocketJack:
case GameMode.PlayerWon:
case GameMode.PlayerBust:
case GameMode.DealerActive:
case GameMode.DealerWon:
case GameMode.DealerBust:
case GameMode.Push:
startHand();
break;
}
}
void doUp()
{
switch (mode)
{
case GameMode.PlacingBets:
pot.DoIncreaseBet();
showPot();
this.Invalidate();
break;
}
}
void doDown()
{
switch (mode)
{
case GameMode.PlacingBets:
pot.DoDecreaseBet();
showPot();
this.Invalidate();
break;
}
}
void showHelp()
{
helpForm.ShowDialog();
}
В панели Properties (для Form1) на вкладке Events дважды щёлкаем по имени события Load. Появившийся шаблон метода Form1_Load после записи нашего кода принимает следующий вид.
Листинг 1.2. Метод для загрузки файлов объектов.
private void Form1_Load(object sender, EventArgs e)
{
//We load the game objects:
init();
startGame();
}
В панели Properties (для Form1) на вкладке Events дважды щёлкаем по имени события Paint. Появившийся шаблон метода Form1_Paint после записи нашего кода принимает следующий вид. Напомним, что другие варианты вывода изображения, например, на элемент управления PictureBox и после щелчка по какому-либо элементу управления уже приводились ранее.
Листинг 1.3. Метод для рисования изображений.
private void Form1_Paint(object sender, PaintEventArgs e)
{
paintForm(e.Graphics);
}
Для задания режимов и управления игрой воспользуемся каким-либо элементом управления или компонентом. Как и выше, с панели инструментов Toolbox переносим на форму компонент MenuStrip и щёлкаем по нему (ниже формы в режиме проектирования). На форме Form1 появляются окна с надписью Type Here, в которые записываем команды (по второму варианту, можно записывать в панели Properties в свойстве Text): Stay, Menu, Exit, HitMe, BetPlus, BetMinus, Sound, Help, рис. 1.30. Для команды, слева от которой поставлен флажок, в панели Properties для этой команды значение Checked следует задать как True.
Рис. 1.30. Команды элемента управления MenuStrip.
В режиме редактирования дважды щёлкаем по левой команде Stay (для приостановки игры). Появившийся шаблон метода после записи строки принимает следующий вид.
Листинг 1.4. Метод для приостановки игры.
private void StayToolStripMenuItem_Click(object sender, EventArgs e)
{
doLeftMenuKey();
}
Аналогично дважды щёлкаем по команде Exit. Появившийся шаблон метода после записи нашего кода принимает следующий вид.
Листинг 1.5. Метод для окончания игры.
private void ExitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
Аналогично дважды щёлкаем по команде “Hit Me”. Появившийся шаблон метода после записи нашего кода принимает следующий вид.
Листинг 1.6. Метод для выдачи карты игроку.
private void HitMeToolStripMenuItem_Click(object sender, EventArgs e)
{
playerHits();
}
Аналогично дважды щёлкаем по команде “BetPlus”. Появившийся шаблон метода после записи нашего кода принимает следующий вид.
Листинг 1.7. Метод для увеличения Ставки.
private void BetPlusToolStripMenuItem_Click(object sender, EventArgs e)
{
doUp();
}
Аналогично дважды щёлкаем по команде “Ставка -” (Bet -). Появившийся шаблон метода после записи нашего кода принимает следующий вид.
Листинг 1.8. Метод для уменьшения Ставки.
private void BetMinusToolStripMenuItem1_Click(object sender, EventArgs e)
{
doDown();
}
Методика приостановки и возобновления звука при помощи установки и удаления флажка в команде Звук (Sound) была описана выше. В данной игре, звук включён постоянно.
Аналогично дважды щёлкаем по команде Help. Появившийся шаблон метода после записи нашего кода принимает следующий вид.
Листинг 1.9. Метод для вывода справочной формы.
private void HelpToolStripMenuItem_Click(object sender, EventArgs e)
{
showHelp();
}
Теперь программа должна управлять карточной игрой, используя любые клавиши, например, верхнюю (Up) и нижнюю (Down), левую (Left) и правую (Right) клавиши со стрелками, а также клавишу Enter (для начальной сдачи карт игроку и Банкомёту и последующей сдачи по одной карте игроку). В панели Properties (для формы Form1) на вкладке Events дважды щёлкаем по имени события KeyDown. Появившийся шаблон обработки нажатий всех клавиш после записи нашего кода для нажатий только трех клавиш (относящимся к тематике данной главы) принимает следующий вид.
Листинг 1.10. Метод для обработки нажатий клавиш.
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if ((e.KeyCode == System.Windows.Forms.Keys.Up))
{
doUp();
e.Handled = true;
}
if ((e.KeyCode == System.Windows.Forms.Keys.Down))
{
doDown();
e.Handled = true;
}
if ((e.KeyCode == System.Windows.Forms.Keys.Enter))
{
//Набираем себе карты:
doEnter();
}
}
Мы закончили написание программы в главный класс Form1 (для формы Form1 с пользовательским интерфейсом игры). В этом проекте движок игры (Engine Game) находится не в файле Form1.cs (как обычно бывает), а в следующем файле CardEngine.cs.
Теперь в наш проект добавляем новые файлы (для программирования соответствующих игровых действий) по следующей схеме.
В панели Solution Explorer выполняем правый щелчок по имени проекта и в контекстном меню выбираем Add, New Item. В панели Add New Item выделяем шаблон Code File, в окне Name записываем имя нового файла с расширением *.cs и щёлкаем кнопку Add. В проект (и в панель Solution Explorer) добавляется этот файл, открывается пустое окно редактирования кода, в которое записываем следующий код.
Листинг 1.11. Новый файл CardEngine.cs.
using System;
using System.Collections;
using System.Drawing;
namespace PocketJack
{
/// <summary>
/// Provides the behaviours required to manage and draw cards
/// </summary>
public class Card
{
/// <summary>
/// The number of the card, in the range 1 to 52
/// </summary>
public byte CardNo;
/// <summary>
/// Indicates if the card is to be drawn face up.
/// True by default.
/// </summary>
public bool FaceUp = true;
/// <summary>
/// The images of the cards. Stored for all the cards.
/// The image with number 0 is the
/// back pattern of the card
/// </summary>
static private Image[] cardImages = new Bitmap[53];
/// <summary>
/// The attribute to be used when drawing the card
/// to implement transpancy
/// </summary>
static public System.Drawing.Imaging.ImageAttributes
cardAttributes;
/// <summary>
/// Used when loading card images prior to drawing
/// </summary>
static private System.Reflection.Assembly execAssem;
/// <summary>
/// Sets up the color and attribute values.
/// </summary>
static Card()
{
cardAttributes =
new System.Drawing.Imaging.ImageAttributes();
cardAttributes.SetColorKey(Color.Green, Color.Green);
execAssem =
System.Reflection.Assembly.GetExecutingAssembly();
}
/// <summary>
/// Scores for each of the cards in a suit
/// </summary>
static private byte[] scores =
new byte[] { 11, //ace
2,3,4,5,6,7,8,9,10, //spot cards
10,10,10}; //jack, queen, king
/// <summary>
/// Picture information for each card in a suit
/// </summary>
static private bool[] isPicture =
new bool[] { false, //ace
false,false,false,false,false,false,
false,false,false, //spot cards
true,true,true}; //jack, queen, king
/// <summary>
/// Names of the suits, in the order that of the suits
/// in the number sequence
/// </summary>
static private string[] suitNames =
new string[] { "club", "diamond", "heart", "spade" };
/// <summary>
/// Names of individual cards, in the order of the cards
/// in a suit
/// </summary>
static private string[] valueNames =
new string[] {"Ace", "Deuce","Three","Four","Five","Six",
"Seven","Eight","Nine","Ten", "Jack","Queen","King" };
/// <summary>
/// Returns the value in points of a given card,
/// according to BlackJack rules
/// </summary>
public int BlackJackScore
{
get
{
return scores[(CardNo – 1) % 13];
}
}
/// <summary>
/// Returns true if the card is a picture
/// (i.e. jack, queen or king)
/// </summary>
public bool IsPicture
{
get
{
return isPicture[(CardNo – 1) % 13];
}
}
/// <summary>
/// Returns text of the suit of this card
/// </summary>
public string Suit
{
get
{
return suitNames[(CardNo – 1) / 13];
}
}
/// <summary>
/// Returns the text of the value of this card
/// </summary>
public string ValueName
{
get
{
return valueNames[(CardNo – 1) % 13];
}
}
/// <summary>
/// Returns true if this is a red card
/// </summary>
public bool Red
{
get
{
int suit = (CardNo – 1) / 13;
return ((suit == 1) || (suit == 2));
}
}
/// <summary>
/// Returns true if this is a black card
/// </summary>
public bool Black
{
get
{
return !Red;
}
}
/// <summary>
/// Returns an image which can be used to draw this card
/// </summary>
public Image CardImage
{
get
{
int dispNo = CardNo;
if (!FaceUp)
{
dispNo = 0;
}
if (cardImages[dispNo] == null)
{
cardImages[dispNo] = new Bitmap(
execAssem.GetManifestResourceStream(
@"PocketJack.images." + dispNo + @".gif"));
}
return cardImages[dispNo];
}
}
/// <summary>
/// Constructs a card with a partiuclar number
/// </summary>
/// <param name="cardNo">number of the card
/// in the range 1 to 52</param>
/// <param name="faceUp">true if the card
/// is to be drawn face up</param>
public Card(byte cardNo, bool faceUp)
{
CardNo = cardNo;
FaceUp = faceUp;
}
/// <summary>
/// Constructs a face up card with that number
/// </summary>
/// <param name="cardNo"></param>
public Card(byte cardNo)
: this(cardNo, true)
{
}
/// <summary>
/// String description of the card
/// </summary>
/// <returns>the name and suit of the card</returns>
public override string ToString()
{
return ValueName + " of " + Suit;
}
}
/// <summary>
/// Provides a container for a number of cards.
О проекте
О подписке