资源描述
21点 高质量C语言程序
精品资料
设计题目: 21点游戏
二十一点游戏是一款操作简单,老少皆宜,并且带有很强娱乐性的游戏。二十一点游戏也是我们学习C语言过程中用来锻炼我们编程能力的一种简单有效的方式。编写二十一点游戏的目的就是在编写过程中学习和掌握各种编程的能力,二十一点游戏中有我们经常接触到的一些头文件,和小的函数体,以及一些相关知识,能让我们在实践中得到锻炼。
一、 设计目的与要求
1、程序设计的源程序功能如下:
(1)将所有的函数与相应的数据封装到类中,并改写主程序,使程序简化。
(2)程序中一共有13张扑克牌可以随机抽取,大于10的点数为10,现要求大于10的点数全部为半点。
(3)要求庄家永远不会暴庄,即庄家可以查看下一张牌,若大于21点,则拒绝,当然,在游戏规则上不能泄露这点秘密。
(4)高级玩家可以查看下一张牌,即按h键,然后按要求输入密码,密码正确可以看牌,并决定是否要牌。
(5)每次要牌后可以设定赔率,即如果开始下的是10元钱的注,如果牌好,你可以要求再下注,当然不能超过你所有的总钱数。
(6)将界面的提示说明改成中文界面,界面的解释详细友好,可以吸引更多的玩家。
二、 课程设计
(1)题目要求把源程序封装在类中,需要编写一个类来封装所有相关函数和变量,同时对main主函数进行改写,以完成题目的要求。
(2)题目要求把抽到的大于10点的牌的点数设为半点,只需要设计随机取下一张牌的成员函数时用if语句判定牌的点数是否大于10,大于10的牌对其重新赋值为0.5即可。
(3)题目要求超级玩家在输入密码后可以查看下一张牌,只需设计一成员函数,判定玩家是否继续要牌之前加入对玩家是否输入h键的判定,如果有输入,则调用为处理玩家输入密码而单独编写的成员函数,在该函数中,首先判定玩家的密码输入是否正确,不正确则返回0,正确则返回1。
(4)题目要求玩家可以根据手上的牌决定是否下注,只需设计一成员函数,检查玩家的赌注累计不超过他所拥有的总资本。
三、 设计描述
1、为满足上述第一条要求,在程序中增加了一个类play,封装到类中的函数有:
void replay(); //检测是否重玩
void hitplayer(); //玩家要牌
void hitcpu();//电脑要牌
void deal(); //开始发牌
void BET(); //加注
void print(); //打印最终结果
void rules(); //显示规则
void results();//判断获胜方
int getmoney();//读取钱数至主程序
void shuruans();//输入判断用字符(如Y,S等)
void firstbet();//首次下注;
void writer(void) ; //写入文本文件
void load(void); //读取文本文件
源程序已有的函数中,void replay(),void rules(), void results(), void print()已经较为完善,仅需将其英文界面部分改为中文即可,而其他函数则应按要求改写。
2、为满足上述第二条要求,按一般玩法>=10的数本应该都按10来算,而这里这些书全都算作0.5,所以
if(card>=10)card=0.5;
即可。
3、第三条要求较为困难,将原程序中的一个void hit(int &total)函数改编为void hitplayer()与void hitcpu()两个函数,分别用来运行玩家及庄家的要牌过程。
要求庄家永远不会暴庄,即是要让庄家可以看牌并判断要牌后点数是否超过21点。因此函数改写为:
void play::hitcpu(void){
float total;
for(;(cpu<16)&&(cputurns<6);cputurns++)
{
cout<<endl;
card=random(13,1);
if(card>=10)card=0.5;
total=cpu+card;
if(total<=21)
{
cpu=total;
cout<<"\t\t\t庄家拿牌"<<endl;
cout<<"\t\t\t这张牌是 :"<<card<<endl;
cout<<"\t\t\t总共 :"<<cpu<<endl;
wait(1350);
}
}
}
使用一个中间变量total即可判断且不影响庄家的实际总点数。
设置超级玩家即是设计一成员函数,判断是否输入正确密码。由于要求要牌也是输入H,因此只需要将函数语句一并编入void hitplayer()中,函数如下:
void play::hitplayer(void){
char str[20];
char c;
nocheats=0;
cout<<"请输入密码"<<endl;
cin>>str;
card=random(13,1);
if(card>10) {card=0.5;}
if(strcmp(str,Password)==0)
{
cout<<"下张牌是"<<card<<endl;
cout<<"输入y要牌,其他键不要"<<endl;
cin>>c;
if(c=='y'||c=='Y')
{
player=player+card;
cout<<"\t\t\t牌面是:"<<card<<endl;
}
else
{
nocheats=1;
}
cout<<"\t\t\t总的牌面是:"<<player<<endl;
}
else
{
player=player+card;
cout<<"\t\t\t牌面是:"<<card<<endl;
cout<<"\t\t\t总的牌面是:"<<player<<endl;
}
}
由strcmp()语句判断输入密码的正确性,若正确则可看牌并决定是否要牌,若不正确则由于已选择要牌(已输入了要牌指令“H”)则拿牌并计入总点数中。加入参数nocheats是由于判断是否要牌的语句在主函数中,不加入参数则可能出现玩家不要牌后仍可再次拿牌(正确结果应是结束玩家拿牌,改由庄家拿牌)。
4、第四条要求中的总下注数不超过总资产数。因此需设计函数使每次要牌后能输入加注数并加入总下注数中。使用void BET()完成加注设定,函数如下:
void play::BET(){
int a=0;
do
{
cout<<"\t\t\t你拥有"<<money<<"元"<<endl;
cout<<"\t\t\t请继续下注";
cin>>a;
if(a<0)
{
a=a*-1;
}
if(a>money)
{
cout<<"你没有足够的钱!"<<endl;
}
}while(a>money);
bet=bet+a;
money=money-a;
}
也是使用中间变量a,目的在于判断总下注数不超过总资产数,若超出则将警告并要求重新输入,且不会误计入总下注数中。又由于每局后下注金额应清零,且加注提示应与下注提示不同,故增设函数如下:
void play::firstbet(void){
cout<<"\t\t\t你拥有"<<money<<"元"<<endl;
cout<<"\t\t\t请下注";
cin>>bet;
if(bet<0)
{
bet=bet*-1;
}
money=money-bet;
}
即是为防止上一局的干扰。
此外,还需将游戏的数据存入文件中,方便下次使用,因此加入了函数void writer(void)和 void load(void),分别用来将游戏的主要数据写入磁盘文件中,可以起到存盘与读盘的效果。
此外,函数int getmoney()用来读取类中的参数money,由于此参数为私有的,且又需在主函数中使用,故设置此函数。但使用次数并不多是一个缺憾。
同时,函数void shuruans()用于在函数外输入参数ans(char ans; //判断用字符型)变量进行判断。由于ans封装在类中,设置这个函数目的即在于此。
此程序运作方式如下:
void play::shuruans(void){
cin>>ans;
}
这样在类体外就可以通过void shuruans()对ans进行赋值.
四、 调试分析
1、 游戏开始
2、 游戏过程
3、 游戏结果
五、 总结
主函数的设计显得有些繁冗杂乱,有很多的程序段有简化的空间。但由于能力有限,不能给出更好的设计方案。以至于函数中出现很多而且肢体庞大的条件、循环语句,程序的可读性也不强。对简化函数体的设计要求没有达到。
密码设计段的知识运用有问题,因为对设计原理不太明白,只是按照题给提示编写该部分程序,或许存在设计上的错误。
两三个星期的调试程序,让我感受到C的魅力,也让我知道只有不断努力的尝试,最终都会成功。
六、 答辩记录
七、 教师意见
参考文献:
【1】C程序设计(第四版) 谭浩强 清华大学出版社
【2】Visual C++.NET完全手册 Chris H.Pappas, William H.Murray 电子工业出版社
仅供学习与交流,如有侵权请联系网站删除 谢谢9
展开阅读全文