c随机发牌课程设计报告.docx
《c随机发牌课程设计报告.docx》由会员分享,可在线阅读,更多相关《c随机发牌课程设计报告.docx(24页珍藏版)》请在冰豆网上搜索。
c随机发牌课程设计报告
学号
2016-2017学年第2学期
1608220203
《高级语言程序设计》
课程设计报告
题目:
随机发牌
专业:
网络工程
班级:
16(3)
姓名:
代应豪
指导教师:
代美丽
成绩:
一、设计内容及要求
1.进一步掌握和利用C语言进行程设计的能力;
2、 进一步理解和运用结构化程设计的思想和方法;
3、 初步掌握开发一个小型实用系统的基本方法;
4、 学会调试一个较长程序的基本方法;
5、 学会利用流程图或N-S图表示算法;
6、 掌握书写程设计开发文档的能力(书写课程设计报告);
二、概要设计
(1).系统功能与分析(填写你所设计的菜单及流程图)
◆系统功能综述
本文本编辑器通过菜单的选择可以实现对扑克牌的构建、洗牌和发牌的功能,并可将最初始的扑克牌的花色与面值显示出来以及发牌后的花色与面值显示出来
◆设计的主菜单
程序初始化主窗口
选择执行的
操作
◆N-S流程图
main()主函数
定义显示菜单的函数
定义构建扑克牌的函数
定义低效洗牌的函数
定义低效发牌的函数
定义高效洗牌、发牌的函数
定义扑克牌花色的函数
定义扑克牌面值的函数
初始化二维数组deck为0
初始化一维数组huase
初始化一维数组dianshu
调用菜单函数
当为真时
调用构建扑克牌函数
输入用户所需要的选择
根据用户的选择进行功能
根据根据
voidsuit(structpukepk[52])
voidface(structpukepk[52])
判断列数,打印正确的面值
◆分析与设计说明
每个函数的基本功能及函数的重要变量的意义:
voidmenu()/*打印主菜单栏*/
voidmake(structpukepk[52])/*构建一副扑克并打印起初的扑克顺序*/
voidordinary_shuffle(structpukepk[52])/*进行低效洗牌*/
voidordinary_deal(structpukepk[52])/*进行低效发牌*/
voideffective(intdeck[][13],charhuase[],chardianshu[])/*进行高效洗牌、发牌*/
voidsuit(structpukepk[52])/*打印扑克的花色*/
voidface(structpukepk[52])/*打印扑克的面值*/
各函数中的重要变量的意义详见下面源程序段的解释说明部分
各函数的之间的相互关系:
(2).数据结构(程序中所使用的变量、数组、结构体)
变量
e使用户选择所需要操作的功能的按键
i定义为1-52张牌,在1-4内的随机变量
t定义为随机变量进行运算后所赋的值
tds某张牌的面值在实现洗牌功能时暂时存放的变量地址
ths某张牌的花色在实现洗牌功能时暂时存放的变量地址
temp扑克牌在实现高效洗牌、发牌时,某张牌暂时存放的变量地址
row表示行数
column表示列数
card代表52张扑克牌
jishu表示在实现高效洗牌、发牌时,发牌的牌数
数组
deck[4][13]定义为一个4x13的二维数组deck表示一副牌。
行与花色对应:
第0行代表红心、第l行代表方块、第2行代表草花、第3行代表黑心。
列代表牌的面值:
第0列到第9列对应于“A”到9,第10列到第12列对应于“J”、“Q’’和“K”。
字符串数组suit代表四种花色,字符串数组face代表13张牌的面值。
huase[4]定义扑克牌的花色:
第0行代表红心、第l行代表方块、第2行代表草花、第3
行代表黑心
dianshu[13]定义扑克牌的面值:
第0到13列分别用‘A’,’2’,’3’,’4’,’5’,’6’,’7’,’8’,'9','10','J','Q'’K'
结构体
structpuke用来定义扑克牌的花色与面值,使得扑克牌被打印时能够显示出每张牌的特征
(3).模块设计
根据功能需要:
在运行程序时调用了这几个头文件
源文件
函数名
功能
fapai---xipai.c
voidmain()
主函数
voidmenu()
打印主菜单栏
voidmake(structpukepk[52])
构建一副扑克并打印起初的扑克顺序
voidordinary_shuffle(structpukepk[52])
进行洗牌
voidordinary_deal(structpukepk[52])
进行发牌
voideffective(intdeck[][13],charhuase[],chardianshu[])
进行高效的洗牌、发牌
voidsuit(structpukepk[52])
打印扑克的花色
voidface(structpukepk[52])
打印扑克的面值
(3)总体设计思想:
◆先定义一个扑克牌的结构体变量,成员列表中包含扑克牌的花色与面值
◆创建主菜单栏,表明此程序的主要用途及相关操作步骤
◆如果要进行此游戏则进行构建一副扑克牌并将其牌最初始的52张牌的花色与面值显示出来以达到游戏的公正性
◆1.询问是否进行洗牌操作,若选择“1”则调用voidordinary_shuffle(structpukepk[52])函数进行洗牌。
此函数是循环有限次,在每次循环时都让系统随机取一个数除52取余得变量t即范围为1-13(也就是在A-K这13个数中任取一数),并同时将52张牌的首个面值与花色付给变量tds与ths,然后利用上面的变量t在这52张牌中随机取值,将其花色与面值从第1张牌开始进行随机地替换,这样就达到了低效洗牌的功效了;
2.然后继续询问要执行哪个操作。
3.若选择“2”则调用voidordinary_deal(structpukepk[52])函数进行发牌。
进行52次循环,调用suit(pk)函数(利用switch语句显示每张牌的花色:
第1行代表红心、第2行代表方块、第3行代表草花、第4行代表黑心)与face(pk)函数(利用switch语句显示每张牌的面值:
第0列到第9列对应于“A”到9,第10列到第12列对应于“J”、“Q’’和“K”)。
这样就可以把52张牌的花色与面值显示出来,从而也就完成了发牌的功能。
的每一张牌呢?
因为数组suit已经预载人了四种花色,所以通过打印字符串suit[row]来获得花色。
同样,打印字符串face[column]可获得牌的面值。
4.接着继续询问要进行哪个操作,若选择“4”,则调用voideffective(intdeck[][13],charhuase[],chardianshu[])函数进行高效的洗牌、发牌操作。
首先,把数组deck清为0;然后,随机地从0~3中选择一行(row),从0~12中选择一列(column)。
把数1插入到数组元素deck[row][column]中并作标记card=1,之后的每一个循环就依次累加。
表示这张牌将是从洗好的牌中发出的第一张牌。
继续这个过程,把数2、3、…、52随机地插入到数组deck中表示从洗好的牌中发出的第2、第3、…、第52张牌。
若card已经标记到13,则需换行。
在把发牌序号插入到数组deck中的过程中,一张牌被选择两次是可能的,即选中它时,deck[row][column]可能会重复。
遇到此情况,系统就会把它忽略不做任何处理,跳出本循环,继续反复地随机选择其它的row和column,直到发现没有被选中过的牌为止。
这样牌的序号1到52最终会分给数组deck中的52张牌。
这时,这副牌就算完全洗好了。
用这种方法系统调用的函数就只有一个,而且使用嵌套的for循环使系统运行得更有效率。
5.如此循环地询问操作,直至用户输入“3”退出此程序。
(4)调试过程:
测试数据及结果,出现了哪些问题,如何修改的
调试过程:
◆在发牌的过程中,第一张牌缺少花色
原因:
对变量局部i进行重复定义,导致变量i值在第二次调用时出错
修改:
将局部变量i定义成全局变量
◆在使用recycle函数递归调用时,并没有多次循环,只执行一次就结束了
原因:
在此程序中,recycle函数的递归调用并没有限制条件,它会无终止地进行,导致内存空间不足,甚至死机
修改:
将recycle函数改成while函数进行多次循环
◆在执行完发牌之后,进行循环,可是第二次循环却未执行洗牌之后的工作,而进行在此循环
原因:
scanf与getch()函数在输入上有所区别。
利用getch()函数输入一个字符之后,必须再按回车键,而所按的回车键会被内存记录,使得“\n”成为变量e的一个值,从而导致多输入了一次shufflethedeck(1/0)?
:
语句。
若使用scanf函数则不会出现此问题,虽然也要再输入回车键,但并不会将“\n”赋值给e变量
修改:
将输入Y/N形式修改为1/0,并将e=getch();修改为scanf(“%d”,&e);
◆在使用voideffective(intdeck[][13],charhuase[],chardianshu[])进行高效洗牌、发牌操作时,发出的牌显示得很凌乱,没有规律性的分布
原因:
高效发牌时,并不是每张牌都会打印出来,因此会显得凌乱,没有规律
修改:
增加初始化了的变量jishu,在打印完扑克牌之后,判断是否已经达到发过13张牌,若已发过13张牌,则换行
三、设计结果与分析
初始化界面
输入“1”进行低效洗牌后,会继续询问用户作何操作
然后继续输入“2”后就会显示低效洗牌后的结果,并继续询问用户作何操作
然后继续输入“4”进行高效洗、发牌显示其结果,并继续询问用户作何操作
然后继续输入“3”后,就会推出DOS界面,结束此程序
(5)程序有待改进的地方及本次实习的收获和建议
待改进:
◆本程序是将扑克牌的正面(即牌面的花色与面值都显示出来),而实际生活中洗牌与发牌的过程都是背面朝上,并不能知道其牌值。
因此洗牌、发牌过程中的正反面问题有待改进
◆本程序是用文本编辑器win-tc写的,发牌效果不是特别好,需将牌的展示生动化写成图形界面效果更佳
◆本程序还有一些小小的细节问题,仍有待改进
收获:
由于这是第一次自己写这么大型的程序(相对以往写的程序而言),一开始琢磨了很久也琢磨不出什么,通过一番努力。
终于写出了一些程序段,然而在写程序的过程中出现了很多错误,碰了不少钉子,但通过他人的指导、帮助与自己不断修改与改进让我对C语言的知识有了更进一步的改进,学会了如何从一个题目入手进行有效的算法分析,写出合理的数据结构,并使程序运行得更加有效率。
同时也发现了自己的不足:
对C语言的掌握还不是特别好,特别是到了指针那部分之后就基本上没有什么概念了。
建议:
C语言课程的内容较多,运用起来时常会出错,有时甚至怎么找也找也找不出来,老师能多在下面转转,观察观察学生的实践情况以及设计进度,适时提出合理的建议或意见供同学们参考。
自己也要多看看书,把C语言掌握透彻;多上机实践,从问题中不断地提高编程能力
四、程序代码
voidmenu()
{printf("****************************************************\n");
printf("*ThisisAutomaticDealingCardprogram!
*\n");
printf("*Inonegame52cardsaredividedinto4grounds.*\n");
printf("****************************************************\n");
printf("ordinary(1:
shuffle2:
deal3:
exit)\n");
printf("effetive(4:
shuffleanddeal)\n\n");
}
该程序段的功能是打印初始时的主菜单,显示其主要功能
voidmake(structpukepk[52])
{printf("Theoriginalpuke:
\n");
for(i=0;i<52;i++)
{
intt=i%13+1;
pk[i].dianshu=t;
}
for(i=0;i<52;i++)
{
intt=i/13+1;
pk[i].huase=t;
}
for(i=0;i<52;i++)
ordinary_deal(pk);
}
该程序段是构建一副扑克牌,让扑克牌有规律地排在一块并显示,以达到游戏的公证性
voidordinary_shuffle(structpukepk[52])
{
for(i=0;i<52;i++)
{intt;
inttds=0,ths=0;
t=rand()%52;/*取随机数*/
tds=pk[i].dianshu;/*进行牌与牌之间的随机替换*/
ths=pk[i].huase;
pk[i].dianshu=pk[t].dianshu;
pk[i].huase=pk[t].huase;
pk[t].dianshu=tds;
pk[t].huase=ths;
}
}
该程序段是通过取随机变量进行52张牌的之间的随机替换以达到洗牌的功能
voidordinary_deal(structpukepk[52])
{
for(i=0;i<52;i++)
{
suit(pk);/*打印扑克的花色*/
face(pk);/*打印扑克的面值*/
}
}
voidsuit(structpukepk[52])
{
switch(pk[i].huase)
{
case1:
printf("%c",3);break;
case2:
printf("%c",4);break;
case3:
printf("%c",5);break;
case4:
printf("%c",6);break;
}
}
voidface(structpukepk[52])
{
switch(pk[i].dianshu)
{
case1:
printf("%s","A");break;
case2:
printf("%s","2");break;
case3:
printf("%s","3");break;
case4:
printf("%s","4");break;
case5:
printf("%s","5");break;
case6:
printf("%s","6");break;
case7:
printf("%s","7");break;
case8:
printf("%s","8");break;
case9:
printf("%s","9");break;
case10:
printf("%s","10");break;
case11:
printf("%s","J");break;
case12:
printf("%s","Q");break;
case13:
printf("%s","k");break;
}
printf("");
if((i+1)%13==0)printf("\n");
}
该程序段是进行发牌功能,调用suit(pk)函数打印洗完牌后的花色,调用face(pk)函数打印洗完牌后的面值
voideffective(intdeck[][13],charhuase[],chardianshu[])
{
inti,j;
inttemp;
introw;/*行*/
intcolumn;/*列*/
intcard;/*计数器*/
intjishu=0;
for(card=1;card<=52;card++)/*循环52张牌*/
{row=rand()%4;
column=rand()%13;
deck[row][column]=card;/*将牌放在选择的位置中*/
for(row=0;row<=3;row++)/*循环deck中的每一行*/
{
for(column=0;column<=12;column++)/*循环deck中的每一列*/
{i=rand()%4;
j=rand()%13;
temp=deck[i][j];
deck[i][j]=deck[row][column];
deck[row][column]=temp;
if(deck[row][column]==card)/*如果当前位置有牌,则打印*/
{
++jishu;
printf("%c%-3c",huase[row],dianshu[column]);
if(jishu%13==0)printf("\n");/*打印13张牌后换行*/
}
}
}
}
}/*结束effective函数*/
该程序段是用随机数洗牌,用嵌套式的for循环进行发牌
附录:
完整、可运行代码及注释
#include
#include
#include
#include
structpuke/*创建扑克的花色与面值的结构共同体*/
{
inthuase;
intdianshu;
};
voidmain()
{voidmenu();
voidmake(structpukepk[52]);
voidordinary_shuffle(structpukepk[52]);
voidordinary_deal(structpukepk[52]);
voideffective(intdeck[][13],charhuase[],chardianshu[]);
voidsuit(structpukepk[52]);
voidface(structpukepk[52]);
chare;
structpukepk[52];
intdeck[4][13]={0};/*初始化数组deck*/
charhuase[4]={3,4,5,6};/*初始化数组face*/
chardianshu[13]={'A','2','3','4','5','6','7','8','9','10','J','Q','K'};
menu();/*打印主菜单栏*/
make(pk);/*构建一副扑克牌并打印起初的扑克顺序*/
while
(1)
{
printf("\npleaseenteryourchoice:
");
scanf("%d",&e);/*选择所要操作的功能*/
switch(e)
{case1:
ordinary_shuffle(pk);break;/*普通方法洗牌*/
case2:
ordinary_deal(pk);break;/*普通方法发牌*/
case3:
exit(0);break;/*退出程序*/
case4:
effective(deck,huase,dianshu);break;/*高效洗牌、发牌*/
default:
printf("Error!
\n");break;
}
}
getch();
}
voidmenu()
{printf("****************************************************\n");
printf("*ThisisAutomaticDealingCardprogram!
*\n");
printf("*Inonegame52cardsaredividedinto4grounds.*\n");
printf("****************************************************\n");
printf("ordinary(1:
shuffle2:
deal3:
exit)\n");
printf("effetive(4:
shuffleanddeal)\n\n");
}
inti;
voidmake(structpukepk[52])
{printf("Theoriginalpuke:
\n");
for(i=0;i<52;i++)
{
intt=i%13+1;
pk[i].dianshu=t;
}
for(i=0;i<52;i++)
{
intt=i/13+1;
pk[i].huase=t;
}
for(i=0;i<52;i++)
ordinary_deal(pk);
}
voidordinary_shuffle(structpukepk[52])
{
for(i=0;i<52;i++)
{intt;
inttds=0,ths=0;
t=rand()%52;/*取随机数*/
tds=pk[i].dianshu;/*进行牌与牌之间的随机替换*/
ths=pk[i].huase;
pk[i].dianshu=pk[t].dianshu;
pk[i].huase=pk[t].huase;
pk[t].dianshu=tds;
pk[t].huase=ths;
}
}
voidordinary_deal(structpukepk[52])
{
for(i=0;i<52;i++)
{
suit(pk);/*打印扑克的花色*/
face(pk);/*打印扑克的面值*/
}
}
voideffective(intdeck[][13],charhuase[],chardianshu[])
{
inti,j;
inttemp;
introw;/*行*/
intcolumn;/*列*/
intcard;/*计数器*/
intjishu=0;
for(card=1;card<=52;card++)/*循环52张牌*/
{row=rand()%4;
column=rand()%13;
deck[row][column]=card;/*将牌放在选择的位置中*/
for(row=0;row<=3;row++)/*循环deck中的每一行*/
{
for(column=0;column<=12;column++)/*循环deck中的每一列*/
{i=r