下面是我在一个大学bbs上看到的一个小问题,问题不难,可还是有许多要注意的地方,数据抽象这一块,函数抽象这一块,还是要多考虑一下,不然,写出的程序会相当冗杂繁琐,相当不优美。
问题陈述:
游戏公司老板准备开发一个人机交互的打牌游戏,项目组里每个人都分配了不同的工作。你现在负责的模块就是为计算机设计一个分牌程序,帮助计算机像人一样可以把分到的牌进行分类。
众所周知,一副扑克牌有四种花色(即方块、梅花、红桃和黑桃)和14个分值级别(即二、三、四、五、六、七、八、九、十、J、Q、K和A)。这里假设A是分值最高级别的。
程序每次读取一手五张牌,然后根据下列类别把手中的牌分类(列出的顺序依次是从最好类别到最坏类别):
Straight flush: 同花顺的牌(即顺序相连又都是同花色)
Four-of-a-kind: 四张相同的牌(四张牌级别相同)
Full house: 三张花色相同和两张花色相同的牌(三张牌是同样的花色,而另外两张牌是同样的花色)
Flush: 同花色的牌(五张牌是同花色的)
Straight: 同顺序的牌(五张牌的级别顺序相连)
Three-of-a-kind: 三张相同的牌(三张牌级别相同)
Two pairs: 两对子
Pair: 一对(两张牌级别相同)
High card: 其它牌(任何其它情况的牌)
如果一手牌有两种或多种类别,程序将选择最好的一种。
为了输入方面,这里把牌的级别和花色简化(字母不区分大小写):
级别:2 3 4 5 6 7 8 9 t j q k a 花色:c d h s 输入
每组要求输入五张牌的内容,每张牌一行(格式参见上述类型英文名)。每次可以运行多组测试,如果输入为0而不是牌,则程序终止。如果用户输入非法牌或者输入同张牌两次,程序将把此牌忽略掉,产生报错信息(Duplicate card; ignored.或者Bad card; ignored.),然后要求输入另外一张牌。
2s↵
5S↵
4s↵
3S↵
2s↵
6S↵
8c↵
As↵
8C↵
7C↵
aD↵
3h↵
6s↵
D2↵
2D↵
9c↵
4h↵
tS↵
0↵
以文本方式显示 Duplicate card; ignored.↵
Straight flush↵
Duplicate card; ignored.↵
Pair↵
Bad card; ignored.↵
High card↵
数据抽象上有一些改动,级别使用2 3 4 5 6 7 8 9 a b c d e,主要是别于后面的规则判断,颜色未改动,因为影响不大。上述数据都是用数组表示。如果想要方便用户输入,可以写个中间函数进行字符转换。
首先,我先谢了一个分派cards的函数,card的表示也采用数组结构,颜色和级别相连,构成一连串字符串,可后来发现,这样构造数据在使用上还是不很方便。(n是牌数,select函数则是随机选择正确的颜色和级别)
void Dispatch(char *card,int n)
{
//dispatch n cards to the machine
int i,j;
for (i = 0;i < n;++ i)
{
//random select the card color and number
Select(&card[i*2],&card[i*2+1]);
while (true)
{
for (j = 0;j < i;++ j)
{
//check each card for if it is already existing
if (card[i*2]==card[j*2] && card[i*2+1]==card[j*2+1]) break;
}
//not existing card
if (i == j) break;
//already exist and check for another card
Select(&card[i*2],&card[i*2+1]);
}
}
}
之后,排序这些cards,是按级别排列,主要是因为上述9种levels 几乎都基于级别。(下列红色那条除外)
Straight flush: 同花顺的牌(即顺序相连又都是同花色)
Four-of-a-kind: 四张相同的牌(四张牌级别相同)
Full house: 三张花色相同和两张花色相同的牌(三张牌是同样的花色,而另外两张牌是同样的花色)
Flush: 同花色的牌(五张牌是同花色的)
Straight: 同顺序的牌(五张牌的级别顺序相连)
Three-of-a-kind: 三张相同的牌(三张牌级别相同)
Two pairs: 两对子
Pair: 一对(两张牌级别相同)
High card: 其它牌(任何其它情况的牌)
排序采用了一个插入排序,然后判断上述level;
int ClassifyTheCards(char *card,int n)
{
//classify the n cards with the rules
//level one:Straight flush
int i,num;
for (i = 1;i < n;++ i)
{
//different color or not connected
if ((card[2*i-2] != card[2*i]) || !Linked(card[i*2-1],card[i*2+1]))
break;
}
if (i == n) return 1;
//level two:Four-of-a-kind
num = 0;
for (i = 1;i < n;)
{
if (num == 3) return 2;
if (card[i*2-1] == card[2*i+1])
{
++ num;
++ i;
}
else
{
num = 0;
i += 2;
}
}
//level three:Full house
if (FullHouse(card,n)) return 3;
//level four:Flush
for (i = 1;i < n;++ i)
{
if (card[i*2-2] != card[i*2]) break;
}
if (i == n) return 4;
//level five:Straight
for (i = 1;i < n;++ i)
{
if (!Linked(card[i*2-1],card[i*2+1])) break;
}
if (i == n) return 5;
//level six:Three-of-a-kind
num = 0;
for (i = 1;i < n;)
{
if (num == 2) return 6;
if (card[i*2-1] == card[i*2+1])
{
++ num;
++ i;
}
else
{
num = 0;
i += 2;
}
}
//level seven:Two pairs
num = 0;
for (i = 1;i < n;)
{
if (num == 2) return 7;
if (card[i*2-1] == card[i*2+1])
{
++ num;
i += 2;
}
else ++ i;
}
//level eight:Pair
for (i = 1;i < n;++ i)
{
if (card[i*2-1] == card[i*2+1]) return 8;
}
//level nine:High card
return 0;
}
上述特例是level 3,是基于颜色的判断,刚开始的时候,因为懒得再写其它函数重新排序,就硬着头皮使用if语句一个个判断,结果写的我晕头转向,最终放弃了。于是还是写了个按颜色排序的函数,并判断是否满足level 3,结果,程序很简单,行数也减少不少。
测试了一下,100次dispatch中,最高级别达到2,level5也有一些,其他的是pair较多,当然最多的还是High card。
为了更好的验证活方便用户输入,于是写了一INPUT函数,希望能有一些异常处理的作用,提供一个较好的输入方式。毕竟内部处理的数据和现实用户接触到的数据是有一些的出入的。
分享到:
相关推荐
1. **洗牌** (`random` 函数): 用于随机化扑克牌顺序。 2. **发牌** (`fapai` 函数): 将洗好的牌分发给四个玩家。 3. **整理牌** (`zhengli` 函数): 对每个玩家手中的牌进行排序。 4. **显示牌** (`pri_all`, `...
在本项目中,"扑克牌源代码"是一个基于Windows窗体程序实现的程序,主要功能是进行扑克牌的发牌和排序。这个程序对于学习面向对象编程、算法设计以及图形用户界面(GUI)的开发非常有帮助。接下来,我们将详细讨论...
总的来说,“C语言扑克牌问题”是一个综合性的编程练习,它锻炼了C语言基本功的同时,也促进了对数据结构、算法和程序设计的理解。通过解决此类问题,开发者能够提升编程技能,为更复杂的项目打下坚实基础。
"java扑克牌课程设计" Java语言是当今流行的网络编程语言,它具有面向对象、跨平台、分布应用等特点。面向对象的开发方法是当今世界最流行的开发方法,它不仅具有更贴近自然的语义,而且有利于软件的维护和继承。 ...
在本Java发牌游戏中,我们需要实现一个扑克牌的分配机制,根据给定的玩家数量将一副扑克牌平均或不平均地分发给每个玩家,并按照特定的顺序输出每个人手中的牌。以下是实现这个游戏的关键知识点: 1. **扑克牌的...
"牌堆"类则管理纸牌的存储和分发。类是创建对象的蓝图,而对象是类的实例,具有特定的属性值。 2. 封装:封装是OOP的重要特性,它将数据和操作这些数据的方法捆绑在一起。在纸牌游戏中,我们不会直接访问纸牌的内部...
1. 牌组构建:程序首先需要创建一个完整的52张牌的牌组,然后按照规则进行洗牌和分发到不同的牌堆。 2. 游戏状态:Solitaire游戏有多种可能的状态,如牌的移动、翻转、重新排列等。这些状态可以通过游戏循环和条件...
该程序的主要目标是创建一个能够将一副扑克牌洗匀并分发给四个人的程序,同时按照桥牌规则进行排序和展示。 首先,设计中定义了一个名为`CARD`的结构体,包含两个成员变量:`flag`和`value`。`flag`用于存储牌的...
1. **类和对象**:首先,我们需要定义一个名为`Card`的类来表示扑克牌。这个类应该包含牌的值(如2, 3, ..., A, K, Q, J)和花色(如红桃、黑桃、梅花、方块)。每个`Card`实例代表一张牌。 2. **数据结构**:为了...
首先,我们要明白斗地主是一款流行的扑克牌游戏,需要三名玩家进行,总共使用一副54张牌,包括大王和小王两张特殊牌。在游戏开始时,每名玩家会获得17张牌,留底3张作为地主的特权。发牌过程的公平性和随机性是游戏...
这个列表仅包含一个文件,即"蜘蛛牌.e",这可能是游戏的主程序文件或者是包含了游戏数据和资源的文件。解压RAR文件后,用户通常需要运行这个文件来启动游戏。如果"蜘蛛牌.e"是一个可执行文件(.exe),那么双击即可...
Deck-Shuffler-C 是一个用 C 语言编写的简单纸牌游戏程序,它允许用户根据自己的需求定制游戏规则,如设置纸牌数量和玩家人数。下面我们将深入探讨这个程序的核心知识点,帮助你理解并可能创建类似的游戏。 1. **C ...
首先,课前教师给每个小组分发扑克牌,要求学生将手中的牌按大小顺序排列,这样就将抽象的算法转化为具体的实践活动。这种方法不仅激发了学生的学习兴趣,也降低了理解难度,使学生能更好地掌握排序的过程。 接着,...
最后,压缩包中的"license.txt"文件通常包含软件的许可协议,对于开源项目,这可能是MIT、GPL等许可证,规定了软件的使用、修改和分发规则。而"Texas HoldEm Simulator"则是我们的主程序文件,包含了所有上述功能的...
斗地主是一种流行的扑克牌游戏,通常由三位玩家进行,需要用到一副完整的54张扑克牌(包括大小王)。游戏开始前,首先要进行发牌,发牌过程决定了每位玩家手中的牌面,对游戏的策略和结果有着直接影响。在编程实现...