桥牌游戏和牌面展示
玩随机抽四人桥牌游戏
要玩上述游戏,请下载 BridgeCardGameV3.zip。
引言
我相信学习数学或编程的人迟早都会研究纸牌游戏。过去我曾多次涉及这个主题,无论是学习面向对象编程还是概率统计。最近,我阅读了 Gary Stafford 的 C# 纸牌战争游戏模拟,我非常喜欢它,因为它与其他的纸牌程序不同,并且具有一些独特的特点,而且他的代码在整个过程中都有很好的文档记录,易于理解。
最大的优点是它的简单性,并且不需要链接到任何 DLL,例如 Cards.dll。
通常,链接到正确的 DLL 并找到和下载 DLL 并不是一件简单的事情。花时间下载和链接,却发现是 DLL 的错误版本。有了 Gary 的代码,你可以立即启动并运行,专注于研究纸牌游戏算法,而不是处理编程接口问题。
为了练习编程,我采用了他的代码和其他我在 Google 上找到的示例纸牌类,并将其制作成一个桥牌游戏演示。如果你在机场感到无聊,可以随机显示桥牌的四手牌进行查看。这篇文章也可以作为未来扩展的基础。
本文将演示以下内容
- 基于现有的 CodeProject 文章进行变体
- 面向对象编程的应用
- 使用 XML 和 XML 样式表制作漂亮的演示文稿
- 讨论未来的编程想法
Using the Code
我从 introcs.cs.princeton.edu 的 Deck 类代码(Java) 找到一个非常基本的 Deck
类。令我惊讶的是,Java 和 C# 非常相似。这个类非常短,就是一个包含 52 张随机洗牌的牌堆。我添加了一个模块,两个 dictionary
对象,以及一个漂亮的套装,显示字符集。该项目是在 Microsoft Visual C# 2010 Express 下编译的。
static string[] suit = { "♦", "♣", "♥", "♠" };
static string[] rank = { "2", "3", "4", "5", "6",
"7", "8", "9", "10", "J", "Q", "K", "A" };
// Dictionary contains the index value to card suit and rank
// for example, A♠ = 52, 2♦ = 0
// so it can display nicely as player groups his cards on hand
Dictionary<string, int> cardOrder = new Dictionary<string, int>();
Dictionary<int, string> orderedDeck = new Dictionary<int, string>();
/// <summary>
/// format drawing cards to xml tagged string for nice display
/// refer to t.xml and t.css
/// </summary>
//
public string drawCardXml(int numCard, int sideIdx)
{
string handxml = "";
orderedDeck.Clear();
if (CardIndex + numCard <= N) //enough cards left to draw
{
for (int i = CardIndex; i < CardIndex + numCard; i++)
{
Console.Out.WriteLine(deck[i]);
orderedDeck.Add(cardOrder[deck[i]], deck[i]);
}
CardIndex += numCard;
// order cards on hand by suit
var sortedDict = (from entry in orderedDeck orderby entry.Key descending
select entry).ToDictionary(pair => pair.Key, pair => pair.Value);
string[] suitOnHand = { "", "", "", "" };
char[] suitchar = { '♦', '♣', '♥', '♠' };
char[] side = { 'N', 'E', 'W', 'S' };
string[] suitName = { "DIAMONDS-", "CLUBS-", "HEARTS-", "SPADES-" };
foreach (KeyValuePair<int, string> pair in sortedDict)
{
int idx = pair.Key / RANKS;
// extract only the value of the card
suitOnHand[idx] += pair.Value.TrimEnd(suitchar[idx]) + ", ";
}
for (int i = SUITS-1; i >= 0; i--) // reverse order, spade on top
{
handxml += "<" + suitName[i] + side[sideIdx] + ">" + suit[i] + ": "
+ suitOnHand[i].TrimEnd(new Char[] { ' ', ',' })
+ @"</" + suitName[i] + side[sideIdx] + ">";
}
}
return handxml;
}
drawCardXml
返回一个 string
,它将被保存到 t.xml 中进行显示;t.xml 显示如下
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="t.css"?>
<GAME><BRIDGE>
<SPADES-N>♠: 5</SPADES-N>
<HEARTS-N>♥: Q , 9 , 8 , 2</HEARTS-N>
<CLUBS-N>♣: 10 , 5</CLUBS-N>
<DIAMONDS-N>♦: 10 , 9 , 7 , 6 , 5 , 4</DIAMONDS-N>
<SPADES-E>♠: 9 , 4 , 2</SPADES-E>
<HEARTS-E>♥: K , 7 , 4</HEARTS-E>
<CLUBS-E>♣: K , Q , 7 , 3</CLUBS-E>
<DIAMONDS-E>♦: K , 8 , 2</DIAMONDS-E>
<SPADES-W>♠: A , Q , J , 10 , 3</SPADES-W>
<HEARTS-W>♥: J , 10 , 6</HEARTS-W>
<CLUBS-W>♣: 9 , 8 , 6 , 4</CLUBS-W>
<DIAMONDS-W>♦: J</DIAMONDS-W>
<SPADES-S>♠: K , 8 , 7 , 6</SPADES-S>
<HEARTS-S>♥: A , 5 , 3</HEARTS-S>
<CLUBS-S>♣: A , J , 2</CLUBS-S>
<DIAMONDS-S>♦: A , Q , 3</DIAMONDS-S>
</BRIDGE></GAME>
最后,我们需要一个样式表 t.css 来在屏幕上用不同的颜色排列四手桥牌。
GAME
{
background-color: #ffffff;
width: 100%;
}
BRIDGE
{
display: block;
margin-bottom: 30pt;
margin-left: 0;
}
SPADES-N
{
display: block;
color: #000000;
font-size: 20pt;
margin-left: 200pt;
}
CLUBS-N
{
display: block;
color: #000000;
font-size: 20pt;
margin-left: 200pt;
}
HEARTS-N
{
display: block;
color: #FF0000;
font-size: 20pt;
margin-left: 200pt;
}
DIAMONDS-N
{
display: block;
color: #FF0000;
font-size: 20pt;
margin-left: 200pt;
}
未来项目构想
一个数据库包含几份报纸上发表的桥牌游戏,包含叫牌合同和游戏步骤,缓慢显示纸牌游戏的过程。
参考文献
历史
- 2012 年 2 月 11 日 - 第一个版本(显示牌)
- 2012 年 2 月 17 日 - V3(玩牌);修复了错误并添加了 AI 来生成默认合同