您的位置:首页 > 其它

如何设计21点游戏

2014-05-25 10:13 218 查看
21点游戏的设计能够充分体现C语言结构化程序设计的思想,如果你是C语言的初学者,本文对你一定有帮助.

21点游戏的规则如下:扑克牌A、2、3、4、、、、、、10、J、Q、K、大小鬼分别代表数字1、2、3、4、、、、、、10、11、12、13、21;人和电脑轮流坐庄,庄家先发牌。胜利条件:将所取牌点数相加凑成 "和"是21,谁先凑成21就胜出,如果没有人凑到"和"是21,就定"和"最接近21且小于21就胜出。每人至多可取5张扑克牌。要注意"和"超过21者谁先爆掉也就是输了,如果都爆了,点数小的胜;当点数相同时,庄家胜。

首先,理清游戏的运行思路是非常关键的。面对众多杂乱的规则,可以先去除无关紧要的细节,这样细节与游戏总体的思路没有关系,只是影响某些过程的处理细节.比如: 每人至多可取5张扑克牌,注意"和"超过21者谁先爆掉也就是输了,如果都爆了,点数小的胜;当点数相同时,庄家胜。可以概括为”取牌规则和判定规则”,这样整个游戏其实就变成了轮流取牌并计分的过程.只是一次取牌结束后可以自行退出,只是不能取5次以上,然后最终用特定的规则来判定胜负.这样理解的游戏的整体思路后,即使加入再多的细节也能轻松应对.

程序编码的第一步是什么?是先声明变量?写主函数?我个人喜欢的是先完成子函数模块的设计.把子模块完成之后,更高级的模块就变得容易了.就像盖楼房一样,先堆砌基础的模块总让我很放心,而一开始就从上层开始让我有一种悬于空中的感觉。我认为对于小型程序来说,自下而上的设计方式是高效的.

分析的时候从分析主体开始,没想到设计的时候从细节开始,但是,我小手一抖,就写出了几个子模块:

//根据牌点获取其数值

intvalue(int i)

{

if(i <= 52)

return i / 4 + 1; //花牌

return MAXNUM; //鬼牌

}

//电脑取牌

introbot_fetch()

{

if(robot_value >= AVG_POINT) //如果取得平均点,不再取牌

return AVG_POINT;

int id;

do{

id = rand() % SUM + 1; //随机选牌

}while(map[id]);

map[id] = 1; //标记为选择状态

return robot_value + value(id);

}

//玩家取牌

intplayer_fetch()

{

int id;

do{

id = rand() % SUM + 1; //随机选牌

}while(map[id]);

map[id] = 1; //标记为选择状态

int temp = value(id);

printf("\t\t你获得了%d 点, 现在您有 %d 点了\n", temp, player_value + temp);

return player_value + temp;

}

//判断胜负

voidjudge_win(int flag)

{

int winer;

if(robot_value > MAXNUM &&player_value > MAXNUM)

{

//同时大于21,少者取胜

if(flag == 1) //玩家是庄家

winer = (robot_value >=player_value);

else

winer = (robot_value >player_value);

}

else if(robot_value> MAXNUM)

winer = 1; //玩家赢了

else if(player_value> MAXNUM)

winer = 0; //电脑赢了

else

{

//同时小于21,多着取胜

if(flag == 1) //玩家是庄家

winer = (robot_value <=player_value);

else

winer = (robot_value <player_value);

}

printf("\n\t\t%s\n", winer ?"玩家赢了" : "电脑赢了");

}

在设计这些子模块的同时便决定了一些细节:

1. 用随机数模拟取牌过程

2. 用map数组记录牌的选中状态防止重选.

3. 扑克牌是按数字顺序排序的.

也在设计的过程中发现并使用了必要的变量和常量:

1. 玩家和电脑对于的点数

2. 对中间点数,总点数进行宏定义,增强程序通用性.

做出这些决定是非常自然了,你可以做出个性的不同的决定,比如用数组记录每张牌的点数,用局部变量的参数传递代替全局变量的使用等等.

子模块的设计是非常简单了,即使一个C语言的新手对这个游戏束手无策,仍然可以编出上面的程序,因为在设计的过程中不需要考虑其他的任何细节,只要在乎眼前的问题而已。这和面向对象的封装思想一样,C++的封装更优秀无非就是把子函数整理归类了.

最后就是用已有的模块搭建函数主题了,也同样可以轻松写出来:

int main()

{

srand((unsigned)time(NULL)); //随机种子

int flag = FLAG; //庄家标志

do

{

memset(map, 0,sizeof(map)); //初始所有的扑克牌没有被选中

player_value = robot_value= 0;

printf("\n\t\t游戏开始\n");

int count = 1;

do{

player_value =player_fetch(); //玩家取牌

robot_value =robot_fetch(); //电脑取牌

if(count >MAXFETVH || player_value > MAXNUM)

break;

count++;

printf("您要继续取牌吗?(Y / N)\n");

}while(tolower(get_sign())!= 'n');

printf("\n\t游戏结束, 您获得了 %d 点, 电脑获得了 %d 点\n",player_value, robot_value);

judge_win(flag);

flag = !flag; //交换庄家

printf("您要继续游戏吗?(Y / N)\n");

}while(tolower(get_sign()) != 'n');

return 0;

}

上面也有很大默认的规则,不过我想读者应该能够看出来,我就不多解释了.

程序仅用了150行,实现了基本的21点游戏功能,再此基础上继续增加新的功能非常简单.

如果电脑更加智能,可以根据对方的牌数和自己的点数来决定是否继续选牌,只要改变robot_fetch()函数的一部分就可以了.如果玩家是在赌博,加入金币制,只要再声明一个变量记录金币的流失与获得就可以了.就算从控制台界面转入windows窗体界面,也许全部的代码都要改动,但是流程和思路是不变的,只要懂得控件的使用就可以.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: