**大学数据结构课程设计报告题目:纸牌游戏院(系):计算机工程学院学生姓名:班级:学号:起迄日期:2011.6.21---2011.7.1指导教师:2010—2011年度第2学期一、需求分析1.问题描述:随机产生52个数按照某一规则计算正面牌数。编号为1-52张牌,正面向上,从第2张开始,以2为基数,是2的倍数的牌翻一次,直到最后一张牌;然后,从第3张开始,以3为基数,是3的倍数的牌翻一次,直到最后一张牌;然后…从第4张开始,以4为基数,是4的倍数的牌翻一次,直到最后一张牌;...再依次5的倍数的牌翻一次,6的,7的直到以52为基数的翻过,输出:这时正面向上的牌有哪些。2.基本功能:选择纸牌是顺序排序还是随机排序随机,1为随机排序,其他数字为顺序排序,输入一个数使程序运行,随机产生52张纸牌,运行之后输出正面向上的牌。之后输入1重新运行,输入其他数字回车停止3.输入输出:1)输入一个数字选择是使用顺序放牌还是随机放牌,1为随机放牌,其他数字为顺序放牌,输入一个正整数种子值,程序运行,输出52张纸牌的排列顺序,列出纸牌序列,输出正面向上的牌,进入选择语句,是否再玩一局,输入1,程序从新运行,输入其他,程序运行结束。二、概要设计1.设计思路:当每个号码每次遇到是某个数的倍数的时候,都会相应的翻一次牌,这样,每张牌翻得次数就个不一样,可能很多次,也可能只有一两次,结果就只是要输出在经过各个不同次数的反派后,正面向上的牌都有哪几个。例如24,第一次他是2的倍数时要从背面翻到背面,当进行到3时,又要从背面返回来。如果他在多次翻拍后,正面还向上了,那么他就是要输出的结果之一。//操作函数voidoperate(void){rcardrc;inti,j;rc=Random();//获得纸牌不同排序方式//翻面游戏for(j=2;j=NUM;j++)//j为基数,也是开始翻面的位置{for(i=j;i=NUM;i++)//i为纸牌位置{if(rc.c[i-1].info%j==0)rc.c[i-1].state=rc.c[i-1].state?0:1;}}2.基本算法:算法的主要流程为:选择所需纸牌是随机还是顺序—>建立代表52张牌的链表—>链表可以选择顺序链表和随机链表->输出这52张牌—>调用翻牌算法按照规则进行翻牌->输出翻牌算法之后的结果->选择是否从新开始。3.数据结构设计:实体:card[]其中的特征为intinfo,intpostion,intstate实体:rcard[]它中的元素就是card[],包涵card[]中的特征。函数名返回值类型Main()voidSelect()voidoperate2voidoperate2()voidrandom()rcardshunxu()rcardh_bian()voidl_bian()voidinformation()viod4.数据结构设计:定义程序中用到的抽象数据类型;抽象数据类型线性表的定义如下:ADTcard{数据对象:D={ai|ai∈c[NUM],i=1,2,3……,n,n≥0}数据关系:R1={ai-1,ai|ai-1,ai∈D,i=1,2,3,……,n}ADTrcard{数据对象:D={ai|ai∈rc,i=1,2,3……,n,n≥0}数据关系:R1={ai-1,ai|ai-1,ai∈D,i=1,2,3,……,n}基本操作:h_bian(void)操作结果:构成输出纸牌的两边纵向边框。l_bian(void)操作结果:构成输出纸牌的横向边框。voidinformation(intinfo)初始条件:info已存在。操作结果:输出构成所选定纸牌的编号。z_picture(intinfo)操作结果:输出所选定纸牌Random()初始条件:线性表num已存在。操作结果:形成随机链表序列。shunxu()初始条件:线性表num已存在。操作结果:形成顺序链表序列。voidoperate1(void)初始条件:随机数列存在。操作结果:输出正面向上的纸牌。voidoperate2(void)初始条件:顺序数列存在。操作结果:输出正面向上的纸牌。select(void)操作结果:判断调用两个操作函数中的一个。5.软件结构设计:1.按需求分析中的功能进行模块划分:1)定义两个实数体。2)构造输出纸牌的外观和信息。3)形成顺序或随机数列4)对选择数据进行操作5)选择操作函数6)主函数6.函数原型:定义两个实体struct{}:card[]rcard[]图形输出函数:z_picture()调用函数l_bian()、h_bian()和information()选择函数:select()操作函数:operate1()调用函数random()Operate2()调用函数shunxu()排序函数:random()Shunxu()三、详细设计1.详细算法模块1.//定义两个实体,其中card为52张纸牌,rcard为被选中操作的纸牌struct{intinfo;//纸牌编号intpostion;//纸牌位置,从1开始计intstate;//纸牌状态,1表示纸牌正面向上,0表示纸牌背面向上}card;#defineNUM52//定义常量,方便调试和验证。typedefstruct{cardc[NUM];}rcard;2.构造纸牌输出界面,形成输出的纸牌形。//纸牌横向边框voidh_bian(void){inti;printf(\n\t);for(i=0;i10;i++)printf(*);}//纸牌列向边框voidl_bian(void){inti,j;for(i=0;i2;i++){printf(\n\t);printf(*);for(j=0;j8;j++)printf();printf(*);}}3.输出正面向上的纸牌信息。//纸牌序号信息voidinformation(intinfo){printf(\n\t);if(info10)printf(*%d*,info);elseprintf(*%d*,info);}//纸牌正面voidz_picture(intinfo){h_bian();l_bian();information(info);l_bian();h_bian();printf(\n\n);}4.被调用函数,分别由operate1和operate2调用其中random形成52张随机数列,shunxu形成52张顺序序列。//获得纸牌不同排序方式rcardRandom(){rcardrc;intcont[NUM];//将需要的数存放到数组中,然后通过调换数组中数的位置,达到随机排列目的。unsignedintseed;//申明初始化器的种子,注意是usignedint型的intindex,i,t;//初始化纸牌状态for(i=0;iNUM;i++)rc.c[i].state=1;//对数组进行初始化for(i=0;iNUM;i++)cont[i]=i+1;//提供随机种子printf(请输入一个正整数种子值:\n);scanf(%u,&seed);srand(seed);//生成随机序列for(i=0;iNUM-1;i++)//交换NUM-1次{index=(rand()%(NUM-i-1))+i+1;//产生从i+1到NUM-1的一个随机数//交换t=cont[i];cont[i]=cont[index];cont[index]=t;}printf(纸牌编号按顺序排列为:\n);for(i=0;iNUM;i++){rc.c[i].info=cont[i];//纸牌编号rc.c[i].postion=i+1;//对应纸牌位置printf(%d,rc.c[i].info);}returnrc;}5.对选定操作对象进行操作,即进行选择和翻面。//操作函数voidoperate1(void)/////////////////////////////////////////////////////////////////操作函数1,实现随机序列翻牌操作{rcardrc;inti,j;rc=Random();//获得纸牌不同排序方式//翻面游戏for(j=2;j=NUM;j++)//j为基数,也是开始翻面的位置{for(i=j;i=NUM;i++)//i为纸牌位置{if(rc.c[i-1].info%j==0)rc.c[i-1].state=rc.c[i-1].state?0:1;}}//打印,用纸牌图形打印。printf(\n正面向上的牌有:);for(i=0;iNUM;i++){if(rc.c[i].state)z_picture(rc.c[i].info);}printf(\n);}voidoperate2(void)/////////////////////////////////////////////////////////////////操作函数2,实现顺序序列翻牌操作{rcardrc;inti,j;rc=shunxu();//获得纸牌不同排序方式//翻面游戏for(j=2;j=NUM;j++)//j为基数,也是开始翻面的位置{for(i=j;i=NUM;i++)//i为纸牌位置{if(rc.c[i-1].info%j==0)rc.c[i-1].state=rc.c[i-1].state?0:1;}}//打印,用纸牌图形打印。printf(\n正面向上的牌有:);for(i=0;iNUM;i++){if(rc.c[i].state)z_picture(rc.c[i].info);}printf(\n);}6.选择函数,用于程序运行结束后选择是否再来一局或者结束游戏。//选择设计voidselect(void){charc;while(1){system(cls);//清屏chara;printf(请输入要选择的初始放牌序列输入1为随机,其他为顺序\n);scanf(%c,&a);if(a=='1')operate1();//判断输入elseoperate2();fflush(stdin);printf(再玩一局?按1继续,按其他键退出!\n请输入选择:);c=getchar();fflush(stdin);switch(c){case'1':select();default:exit(0);}}}7.主函数//定义主函数intmain(intargc,char*argv[]){select();system(color3e);return0;}2.实现主函数的流程图。.NN设一个一维数组card[52],并将所有变量赋初值为1,表示直拍正面向上2=>jj<=52j=>ii<=52j++开始YNY4.函数之间的调用关系图i%j=0翻牌,如果card[i-1]为0,则变为1;如果为1,则变为0i++输出card[]数组中正面向上的序号结束四、调试分析1.这题的时间复杂度是O(52)。按照操作指示,可以选择顺序放牌很随机放牌,选择后运行程序即可输出相应放牌顺序下的正面向上的牌。2.虽然本次程序的题目难度与其他问题想必不是很高,但是仍有很多问题我们是很容易忽视的,其一:在理解题目要求时,应注意翻拍次数可能很多次;其二:for循环的嵌套使用在书写是很容易漏掉大括号。3.在程序调试期间根据提示还是很容易找出问题,但是自己编写时就不会发现,应注意培养自己的严谨认真,Main()operate1Operate2select()system(color3e)l_bian()z_picture()shunxu()random()a=1l_bian()结束information(intinfo)4.编写完程序之后,发现程序要求很简单,但是我应该编写更多的玩法,由于刚接触MFC感觉是个很好的工程,以后有机会可以利用MFC自己开发一个真正可以玩起来的纸牌游戏。五、测试结果1.其输入要选择的初始放排序列1为随机,其他为顺序。输入:1其输入一个正整数种子值。输