保龄球计分系统C语言优秀课程设计.docx
保龄球计分系统C语言优秀课程设计目 录 1 需求分析 . 1 1.1 1.2 1.3 1.4 1.5 问题描述 . 1 输入数据要求 . 1 输出数据要求 . 2 开发环境和工具 . 2 成员分工 . 2 2总体设计 . 3 2.1总体设计思路 . 3 2.2模块结构图 . 3 2.3模块说明 . 4 3详细设计 . 6 3.1数据类型定义 . 6 3.2SCAN模块实现 . 6 3.3SAVE以及READ模块实现 . 8 3.4COUNT模块实现 . 9 4 测试结果与分析 . 11 4.1.输入数据计算结果 . 11 4.2数据的文件保存 . 12 4.3从文件读入数据并计算结果 . 12 5个人总结 . 14 6 附 录 . 15 6.1源代码. 15 1 需求分析 1.1 问题描述 从键盘读入比赛数据;从文件读入比赛数据;将从键盘输入的比赛数据存入文件。将比赛数据显示在屏幕上计算比赛结果及统计数据,并显示在屏幕上。 一局(GAME)保龄球分为10格,每格里有两次投球机会,如在第一次投球时全中,就不需要投第二球。每一格可能出现三种情况: 1.失球(MISS) 无论何种情况,在一格的两次投球时,未能击倒10个瓶,此格的分数为击倒的瓶数,未击中用一个(-)符号表示。 2.补中(SPARE) 当第二次投球击倒该格第一球余下的全部瓶子,称为补中,用一个(/)符号表示。补中的记分是10分加上下一次投球击倒的瓶数。 3.全中(STRIKE) 当每一格的第一次投球击倒全部竖立的十个瓶时,称为全中,用一个(×)符号表示。全中的记分是10分(击倒的瓶)加该球员下两次投球击倒的瓶数。 但在第十格中情况比较特殊: (1)如第二次投球未补中,则第十格得分为第九格得分加上第十格所击倒瓶数。 (2)如第二次投球补中,则追加一次投球机会,第十格得分为第九格得他加上10加上追加一次投球击倒瓶数。 (3)如第一球为全中,则追上加二次投球机会,第十格得分为第九格得分加上10加追加二次投球击倒的瓶数。因此从第一格到第十格的两次追加投球,都为全中,则为12个全中,得分为满分300分。 1.2 输入数据要求 第一格第一次击倒瓶数: 第一格第二次击倒瓶数: 第二格第一次击倒瓶数: 第二格第二次击倒瓶数: - 1 - 1.3 输出数据要求 输入数据显示格式: 序号 1 9|1 2 6|3 2 6|3 25 3 8|2 3 8|/ 42 4 5 6 7 8 4|5 8 4|5 133 9 10 7|2 10|0 10|0 10|0 4 7|2 51 5 6 7 8|2 10|7|3 9 8|/ 153 10 × | 7 | / 积分输出数据显示格式: 序号 1 9|/ ×| ×| ×| 81 105 124 得16 分 173 1.4 开发环境和工具 开发环境:Windows 7 开发工具:Visual C+ 6.0 1.5 成员分工 - 2 - 2总体设计 2.1总体设计思路 1. 设计思路 因为这是一个计分系统,所以在主函数中采用switch结构来达到输入数字来进行选项操作。然后通过定义大量的函数,然后在swtich中来一个个调用函数,来进行运算和处理。 由于要使得系统能一次输入多局比赛并保存,读写文件时,先把每局数据存入一个最多能存10局比赛数据的结构体中,然后将整个结构体存入文件,读取文件时,可以自由选择载入保存比赛数据的文件,并自行选择需要显示和计算的比赛局数,然后进行显示,读写文件一律采用二进制方式读写。 输入比赛数据以及输出比赛数据时,利用循环语句依次输出;对于保龄球第十格击球的特殊性,再加入if语句判断,然后根据不同情况进行输入或者计算。 显示部分先定义count函数用来在得到比赛数据后进行计算积分,然后一种显示是输入数据后直接计算显示;还有一种是读取文件中比赛数据,然后再进行积分运算,再显示结果。 在现实中,充分运用清屏函数,使程序显得直观简洁。 2. 数据存储 在不退出程序的时候,如不进行将比赛数据存入文件的选项,每局比赛都存在个最多包含10局比赛数据的结构体中,然后可以选择是否把整个结构体读入文件并存储以便下次直接读取并计算显示。 2.2模块结构图 根据需求将系统划分为两个个功能模块,函数之间的调用关系如图1.1所示。- 3 - Main(switch) Scan Read Changeout Print Save Count Changein Print Count 图1.1 保龄球计分系统模块结构图 1)Scan:初始化比赛,输入比赛数据。 2)Save: 将比赛数据读入文件。 3)Count:通过计算得到比赛积分。 4)Print: 调用Count计算后得到比赛积分结果并输出。 5)Read: 读取存储了比赛数据的文件。 6) Changein: 将比赛数据由数组存入结构体,便于读入文件。 7) Changeout: 将结构体中数据赋值给数组,方便读取文件得到数据后的计算、处理。 2.3模块说明 1. Scan模块 函数原型:void scan; 功 能:提示输入局数以及每格击倒球数,即输入比赛数据。 输入参数:a114,二维数组,存放比赛数据。 输出参数:a114,已经赋值了的二维数组,存有一局比赛数据。 2. Save模块 函数原型:void save; 功 能:将小于等于十局数量的比赛数据存入自己命名的文件。 输入参数:char ch,infile15,字符串数组,输入文件名字。 输出参数:char ch,infile15,字符串数组,已经输入的文件名字。 3. Count模块 函数原型:void count(int p 4,int n); - 4 - 功 能:按保龄球比赛规则计算比赛积分。 输入参数:int p4,已经赋值了二维数组,包含比赛数据。 输出参数:int p4,已经赋值了二维数组,包含比赛数据以及每格所得分数。 4. Print模块 函数原型:void print; 功 能:按格式输出比赛数据并加和总分并按格式显示积分结果; 输入参数:int a114,已经赋值了二维数组,包含比赛数据以及每格所得分数。 输出参数:int a114,已经赋值了二维数组,包含比赛数据以及每格所得分数以及总分。 5. Read模块 函数原型:void read; 功 能:读取存在文件中的比赛数据; 输入参数:outfile,字符串,需要读取的文件名; t,整形变量,需要读取的比赛的局数。 输出参数:gamet,结构体,包含所需比赛的数据。 6. Changein模块 函数原型:void changein; 功 能:将二维数组转化为结构体; 输入参数:int a114,已经赋值了二维数组,包含比赛数据以及每格所得分数。 输出参数:game10.turn112,结构体,包含比赛数据以及每格所得分数。 7. Changeout模块 函数原型:void changeout; 功 能:将结构体转化为二维数组; 输入参数:game10.turn112,结构体,包含比赛数据以及每格所得分数。 输出参数:int a114,已经赋值了二维数组,包含比赛数据以及每格所得分数。 - 5 - 3详细设计 3.1数据类型定义 1. 数据类型定义 char ch,infile15,outfile15; /*定义两个字符数组,用来输入存储以及读取的文件名*/ struct game_number int turn112; game10; /*定义结构体,最多包含10局比赛数据*/ int a114; int t; /*定义两个全局变量,分别用于进行数据输入以及计算和输入选择比赛局数*/ 3.2Scan模块实现 1. 算法思想 用for循环来给数组赋值;用if 以及 do while语句同进行,来进行输入判断,避免输入错误;在第十格用if语句判断接下来的击球情况。 2. 具体实现 for(i=0;i<=8;i+) /* 用for循环来给数组赋值 */ printf("请输入第%d格第一次击倒瓶数:",i+1); scanf("%d",&ai0); do if( ai0>10 | ai0<0 ) m=0; printf("错误,请再次输入:"); scanf("%d",&ai0); else m=1; while(m=0); /*用if、do-while来避免输入错误*/ printf("请输入第十格第一次击倒瓶数:"); scanf("%d",&a90); - 6 - do if( a90>10 | a90<0 ) m=0; printf("错误,请再次输入:"); scanf("%d",&a90); else m=1; while(m=0); if(a90=10) printf("请输入追加第一次击倒瓶数:"); scanf("%d",&a100); do if( a100>10 | a100<0 ) m=0; printf("错误,请再次输入:"); scanf("%d",&a100); else m=1; while(m=0); printf("请输入追加第二次击倒瓶数:"); scanf("%d",&a101); do if( a101>10 | a101<0 ) m=0; printf("错误,请再次输入:"); scanf("%d",&a101); else m=1; while(m=0); else printf("请输入第十格第二次击倒瓶数:"); scanf("%d",&a91); do if( a91>10 | a91<0 | a90+a91>10 | a90+a91<0 ) - 7 - m=0; printf("错误,请再次输入:"); scanf("%d",&a91); else m=1; while(m=0); if(a90+a91=10) printf("请输入追加一次击倒瓶数:"); scanf("%d",&a100); do if( a100>10 | a100<0 ) m=0; printf("错误,请再次输入:"); scanf("%d",&a100); else m=1; while(m=0); /*用if和do-while语句按照比赛规则判断第十格第一次击球后所有输入情况*/ 3.3Save以及Read模块实现 1算法思想 定义两个字符串组以及一个包含10个二维数组的结构体,前者用来输入文件名,后者用来包含10局以内数量的比赛数据,然后通过二进制读写方式,将整个结构体存储进自己命名的文件中;读取文件时也采用二进制将整个结构体读取。 读入、读取文件时采用for循环方式全部读入、读写。 注意:Save模块保存的只是比赛数据,即几局比赛每局每格击倒的瓶数;并不是直接保存比赛积分结果;所以Read模块读取后,还要再将数据进行计算然后得出积分结果。 2.具体实现 struct game_number int turn112; game10; char ch,infile15,outfile15; void save - 8 - FILE *fp1; int i; printf("请输入保存比赛数据的文件名:"); /*自己命名保存数据的文件名*/ scanf("%s",infile); if(fp1=fopen(infile,"wb+")=NULL) printf("cannot open filen"); return; for(i=0;i<=9;i+) fwrite(&gamei,sizeof(struct game_number),1,fp1); fclose(fp1); void read FILE *fp2; int i; printf("请输入读取比赛数据的文件名:"); /*输入比赛数据所在文件命以读取数据*/ scanf("%s",outfile);printf("n"); printf("请输入要查询的比赛局数:"); scanf("%d",&t); if(fp2=fopen(outfile,"rb+")=NULL) printf("cannot open filen"); for(i=0;i<=9;i+) fread(&gamei,sizeof(struct game_number),1,fp2); /*用for循环读取整个结构体的数据*/ 3.4Count模块实现 1.算法思想 根据题目要求的积分格式,在Count模块中,我只算出每轮所得分数,然后供Print模块调用,Print模块再用for循环即可加和求总积分,所以Count模块中我只利用if else语句判断击球情况来根据规则积分。 2.具体实现 void count(int p 4,int n) /*定义形式参数,方便已经赋值的二维数组进行计算*/ if(n=9) /*由于比赛规则特殊性,所以从第9格后的积分算法要专门判断计算*/ pn2=pn0+pn1+pn+10+pn+11; /*将每轮分数赋值到p2中去*/ else - 9 - if(pn0=10) if(pn+10!=10) pn2=10+pn+10+pn+11; else pn2=10+pn+10+pn+20; else if(pn0+pn1=10) pn2=10+pn+10; else if(pn0+pn1<10) pn2=pn0+pn1; - 10 - 4 测试结果与分析 4.1.输入数据计算结果 主页面,按照提示,测试输入数据计算结果这一项。 看到如果输入有误会立即提示并重新输入 - 11 - 这次输入数据后计算出的结果,并且按照要求格式输出; 4.2数据的文件保存 接下来测试能否保存文件。 再继续又输入一局比赛数据后,将两句的比赛数据一起保存进了名为“2game”的文件中: 4.3从文件读入数据并计算结果 现在继续测试是否能选择读取文件数据,然后同样计算得积分。 - 12 - 选择载入2game.dat这个文件,要查询的是第二局比赛的数据:可以看到得到的是之前输入的第二局比赛的数据,然后系统再次运算得出了相同的积分结果。 - 13 - 5个人总结 1、 虽然能在输入数据时报错,但是由于定义的输入数据为int型,所以如果输入字母等其他的话,就会有错误,所以还要继续改进。 2、 定义太多全局变量,而且定义结构体有些多余,完全可以通过定义三维数组达到。 3、 有些界面不能直接返回主界面,所以还需在一些数据输入的界面上加上这一选项。 - 14 - 6 附 录 6.1源代码 #include<stdio.h> #include<stdlib.h> struct game_number int turn112; game10; int a114; int t; char ch,infile15,outfile15; void scan int i,m; printf("请输入比赛局数:"); scanf("%d",&t); for(i=0;i<=8;i+) printf("请输入第%d格第一次击倒瓶数:",i+1); scanf("%d",&ai0); do if( ai0>10 | ai0<0 ) m=0; printf("错误,请再次输入:"); scanf("%d",&ai0); else m=1; while(m=0); printf("请输入第%d格第二次击倒瓶数:",i+1); scanf("%d",&ai1); do if( ai1>10 | ai1<0 | ai0+ai1>10 | ai0+ai1<0 ) m=0; printf("错误,请再次输入:"); scanf("%d",&ai1); else m=1; - 15 - while(m=0); printf("请输入第十格第一次击倒瓶数:"); scanf("%d",&a90); do if( a90>10 | a90<0 ) m=0; printf("错误,请再次输入:"); scanf("%d",&a90); else m=1; while(m=0); if(a90=10) printf("请输入追加第一次击倒瓶数:"); scanf("%d",&a100); do if( a100>10 | a100<0 ) m=0; printf("错误,请再次输入:"); scanf("%d",&a100); else m=1; while(m=0); printf("请输入追加第二次击倒瓶数:"); scanf("%d",&a101); do if( a101>10 | a101<0 ) m=0; printf("错误,请再次输入:"); scanf("%d",&a101); else m=1; while(m=0); else printf("请输入第十格第二次击倒瓶数:"); scanf("%d",&a91); - 16 - do if( a91>10 | a91<0 | a90+a91>10 | a90+a91<0 ) m=0; printf("错误,请再次输入:"); scanf("%d",&a91); else m=1; while(m=0); if(a90+a91=10) printf("请输入追加一次击倒瓶数:"); scanf("%d",&a100); do if( a100>10 | a100<0 ) m=0; printf("错误,请再次输入:"); scanf("%d",&a100); else m=1; while(m=0); void changein int h; for(h=0;h<=10;h+) gamet.turnh0=ah0; gamet.turnh1=ah1; void changeout int h; for(h=0;h<=10;h+) ah0=gamet.turnh0; ah1=gamet.turnh1; void save - 17 - FILE *fp1; int i; printf("请输入保存比赛数据的文件名:"); scanf("%s",infile); if(fp1=fopen(infile,"wb+")=NULL) printf("cannot open filen"); return; for(i=0;i<=9;i+) fwrite(&gamei,sizeof(struct game_number),1,fp1); fclose(fp1); void read FILE *fp2; int i; printf("请输入读取比赛数据的文件名:"); scanf("%s",outfile);printf("n"); printf("请输入要查询的比赛局数:"); scanf("%d",&t); if(fp2=fopen(outfile,"rb+")=NULL) printf("cannot open filen"); for(i=0;i<=9;i+) fread(&gamei,sizeof(struct game_number),1,fp2); void count(int p 4,int n) if(n=9) pn2=pn0+pn1+pn+10+pn+11; else if(pn0=10) if(pn+10!=10) pn2=10+pn+10+pn+11; else pn2=10+pn+10+pn+20; else if(pn0+pn1=10) pn2=10+pn+10; else if(pn0+pn1<10) pn2=pn0+pn1; - 18 - void print int i,k; printf("第%d局比赛数据及结果:n",t);printf("n");printf("n");printf("n"); printf("轮 数: "); for(i=0;i<10;i+) printf("%6d",(i+1); printf("n"); printf("击倒瓶数: "); for(k=0;k<=10;k+) if(k<=9) printf("%4d|%d",ak0,ak1); else if(a90=10) printf("|%d|%dn",ak0,ak1); else if(a90+a91=10) printf("|%d n",ak0); else printf("n"); printf("nnn"); for(i=9;i>=0;i-) count(a,i); for(i=0;i<10;i+) if(i=0) ai3=ai2; else ai3=ai-13+ai2; printf("轮 数: "); for(i=0;i<10;i+) printf("%6d",(i+1); printf("n"); printf(" "); for(k=0;k<=10;k+) if(k<=9) if(ak0=10) if(k=9)printf(" ×"); else printf(" ×| ");