一 目的
通过验证谁是最伟大的puzzle,培养学生综合利用C语言进行程序设计的能力,加强函数的运用及学生对计算机软件基础的认识,使学生将所学知识转化为分析和设计简单问题的能力,学会查资料和工具书。
二 需求分析
1.任务
此次程序设计的任务是要求学生将所学的C语言知识运用到具体的课程设计里面,而这次需要解决的问题就是谁是最伟大puzzle这个问题,此次程序要求学生利用数据结构,文件,C语言等研究出在1000次射击里面谁是赢家,并且将每次的结果输出到指定的文件中
2.规定
(1).输入的形式和输入值的范围:输入的数据类型只有整型和字符型,n的值只有输入1或2,程序才会运行得出结果,否则将提示出错。当提示是否尝试另一种游戏方法时,只有输入y,Y或n,N程序才会正常运行,否则将提示出错。
(2)输出形式:当输入的n值为1或2时,将会输出正确的结果,即三个人在一千次游戏当中各自获胜的概率,若用户输入其它数值,将输出一语句提示用户输入错误。在以一种方法进行了游戏之后,将输出提示语句,提示用户是否继续以另一种游戏方法再进行一次游戏,这时若用户输入y或Y,则界面将会提示用户再一次输入n值,若输入n或N,则输出一语句提示游戏结束,若输入其它的字符,则提示输入错误。
(3)程序所能达到的功能:a.模拟一次射击的过程;b.模拟一次整个游戏的循环过程;c.进行一千次游戏,并将每个游戏参与者最后获胜的概率输出;d.能将游戏方法的标志,即n值,以及每次游戏的结果,还有最后每个人获胜的概率,记录入指定的文件当中;e.当输入的数据不符合要求是,程序会输出语句提示用户输入错误;f.当以一种游戏方法进行了游戏时,程序会提示用户是否以另一种游戏方法进行游戏。
(4)初步的测试计划:按如下顺序进行:a.输入n值为1,以测试第一种游戏方法;b.输入y或Y继续进行,接着输入n值为2,以测试第二种游戏方法;c.输入n值为3,以测试当输入的n值不符合要求时程序的反应.
三 概要设计
1.所有数据类型的定义及含义:
shooting:定义为实型,含义是0到1的随机数。Winner:整型,用于标志每次游戏的结果,即获胜者。Player:整型,用于记录人数。Alive,Bob,Charlie:都是整型,且值只有1或0,分别用于标志三个人的死活。a,b,c:整型的指针变量,分别指向Alive,Bob,Charlie,用于赋值给函数shoot的形参,表示被射击的人。n:整型变量,值只能是1或2,用于标志游戏方法。A,B,C:整型变量,分别用于记录三个人在一千次游戏当中获胜的次数。j:整型,用于一千次游戏的计数器。k:字符型变量,用于标志游戏是否继续进行。fp1:指向结构体的指针变量,用于标志指定的文件。Player1,Player2,Player3:实型变量,用于记录每个人获胜的概率。
2.函数的调用关系图:
3.个程序模块的功能:
void shoot ( int *targetAlive, double accuracy ):模拟一次射击过程,电脑产生一个0到1的随机数,若此随机数小于射击者的概率,则被射击者死,反之则活。int startDuel(int n):模拟一次完整的游戏循环过程。main():模拟一千次游戏过程,并对每个人获胜的概率进行记录。
4.各模块之间的层次(调用)关系:
shoot函数是一个的函数。startDuel函数包含了shoot函数,其中若干次调用了shoot函数。main函数又包含了startDuel函数,其间一千次调用了startDuel函数。
2
《数据结构》课程设计
四 详细设计
1.主程序流程图:
主程序开始输入nn为其他数值 n=1或n=2提示输入错误进入for循环调用starDuel函数调用shoot函数得出概率,并把每次结果录入文件是否继续?输入其他字符输入n或N输入y或Y提示出错游戏结束
2.最终源程序:
#include void shoot ( int *targetAlive, double accuracy )/*此函数模拟一次射击过程*/ {float shooting; shooting=random(101)/100.00;/*产生0到1的随机数*/ if(shooting 中南民族大学计算机科学学院 自动化 专业 学号: 姓名 :韦加锴 3 *targetAlive=1;/*随机数大于概率,该人活着*/ } int startDuel(int n)/*此函数模拟一次完整的游戏过程*/ {int winner,player=3; int Alive=1,Bob=1,Charlie=1;/*定义三个整型变量,并赋初值为1,表示每个人初始阶段都是活着*/ int *a,*b,*c; a=&Alive; b=&Bob; c=&Charlie; if(n==1)/*常规的游戏方法,A先打*/ { shoot(c,0.33);/*A先打C*/ if(Charlie==0)/*若C被A打死,则进入A与B互打的循环,直到A与B之间只剩一人*/ {player--; while(player>1) {if(Bob&&Alive) shoot(a,0.5); if(Alive==0) player--; else {if(Bob&&Alive) shoot(b,0.33); if(Bob==0) player--; } } } else/*若C活着,则进行下列过程*/ {shoot(c,0.5);/*B打C*/ if(Charlie)/*若C活着,则进行下列过程*/ { shoot(b,1.0);player--;/*C打B,B肯定死,人数减一*/ shoot(c,0.33);/*轮到A打C*/ if(Charlie==0) player--;/*若C死,人数减一*/ else { shoot(a,1.0);/*若C活着,则C打A,A肯定死,人数减一*/ player--; } 4 《数据结构》课程设计 } else/*若C被B打死,则进入A与B互打的循环,直到A与B之间只剩一人*/ {while(player>1) {if(Alive&&Bob) shoot(b,0.33); if(Bob==0) player--; else {if(Alive&&Bob) shoot(a,0.5); if(Alive==0) player--; } } } } if(Alive) winner=1;/*用winner标志游戏的结果*/ if(Bob) winner=2; if(Charlie) winner=3; return winner; } else/*反常规游戏方法,B先打*/ if(n==2) {shoot(c,0.5);/*B打C*/ if(Charlie==0)/*若C死,则进入A与B互打的循环,直到A与B之间只剩一人*/ {while(player>1) {if(Alive&&Bob) shoot(b,0.33); if(Bob==0) player--; else {if(Alive&&Bob) shoot(a,0.5); if(Alive==0) player--; } } } 中南民族大学计算机科学学院 自动化 专业 学号: 姓名 :韦加锴 5 else/*若C活着,则进行下列过程*/ { shoot(b,1.0);player--;/*C打B,B必死,人数减一*/ shoot(c,0.33);/*轮到A打C*/ if(Charlie==0) player--;/*若C死,人数减一*/ else { shoot(a,1.0); player--;/*若C活着,则C打A,A必死,人数减一*/ } } if(Alive) winner=1;/*用winner标志游戏结果*/ if(Bob) winner=2; if(Charlie) winner=3; return winner; } main() { int A=0,B=0,C=0,j,winner; int n; char k; float player1,player2,player3; FILE *fp1;/*定义一个指向文件的FILE型指针*/ printf(\"\\n\"); printf(\"\\-----The Greatest Puzzle,the wonderful game----\\n\"); printf(\"please input n(normal: n=1 ; unnormal: n=2):\");/*提示用户输入n*/ scanf(\"%d\ if(n!=1&&n!=2)/*若输入的n不是1或2,则提示用户输入错误并重新输入*/ printf(\"Your input is error!Please try it again!\"); else { randomize();/*此函数使每次产生的随机数不同*/ if((fp1=fopen(\"d:\\\\outfile.txt\在D盘建立并打开一个只写的字符文件*/ { printf(\"file cannot be open\\n\"); exit(1);/*打开文件不成功则退出*/ } fprintf(fp1,\"The n is:%d\把n的值记录入文件*/ for(j=1;j<=1000;j++)/*一千次调用整个游戏过程的函数*/ { winner=startDuel(n); if(winner==1) A++;/*用A,B,C分别记录三个人赢的次数*/ if(winner==2) B++; if(winner==3) C++; fprintf(fp1,\" \"); 6 《数据结构》课程设计 fprintf(fp1,\"\\nDi %d ci winner is :%d\ \把每次的游戏结果记录入fp1指定的文件当中*/ fprintf(fp1,\"\\n\"); } player1=(float)A/1000; player2=(float)B/1000; player3=(float)C/1000; printf(\"player1 is %f, player2 is %f, player3 is %f\\n\打印每个人赢的概率*/ fprintf(fp1,\" \"); fprintf(fp1,\"\\nplayer1 is: %f, player2 is:%f, player3 is:%f\\把每个人赢 的概率记录入指定的文件当中*/ fprintf(fp1,\"\\n\"); A=0, B=0,C=0,j=1;/*进入另一游戏方法,对计数器重新赋初值*/ printf(\"Do you want to play the other one(Y or N):\");/*提示用户尝试另一种游戏方法*/ k=getche(); if(k=='y'||k=='Y')/*若用户输入y,则进入另一种游戏方法*/ { printf(\"\\n\"); printf(\"please input n(normal: n=1 ; unnormal: n=2):\"); scanf(\"%d\ if(n!=1&&n!=2) printf(\"Your input is error!Please try it again!\"); else { randomize(); if((fp1=fopen(\"d:\\\\outfile.txt\ { printf(\"file cannot be open\\n\"); exit(1); } fprintf(fp1,\"The n is:%d\ for(j=1;j<=1000;j++) { winner=startDuel(n); if(winner==1) A++; if(winner==2) B++; if(winner==3) C++; fprintf(fp1,\" \"); fprintf(fp1,\"\\nDi %d ci winner is :%d\ \ fprintf(fp1,\"\\n\"); 中南民族大学计算机科学学院 自动化 专业 学号: 姓名 :韦加锴 7 } player1=(float)A/1000; player2=(float)B/1000; player3=(float)C/1000; printf(\"player1 is %f, player2 is %f, player3 is %f\\n\ fprintf(fp1,\" \"); fprintf(fp1,\"\\nplayer1 is: %f, player2 is:%f, player3 is:%f\\ fprintf(fp1,\"\\n\"); } } else/*若用户输入n,则游戏结束*/ if(k=='n'||k=='N') { printf(\"\\n\"); printf(\"The game is over ,thank you for playing!\"); } else/*若用户输入其他字符,则提示用户输入错误*/ {printf(\"\\n\"); printf(\"your input is error!\"); } fclose(fp1);/*关闭文件*/ return 1;/*返回一个值*/ } } 五 调试分析 1.测试数据与输出结果: (1)当输入n值为1时,得到三者获胜的概率分别为0.,0.,0..(2)接着输入y继续,然后输入n值为2,得到概率分别为0.,0.,0..(3)以上是正确的输入形式,接着以错误的形式输入数据,再次运行,输入n值为3,则会输出“Your input is error!Please try it again!”提示输入错误。(4)再次运行,输入n值为2,又得出一组概率,接着界面会输出“Do you want to play the other game(Y or N):”,若输入除y和n外的其它字符,如6,则界面会输出“Your input is error!”,提示用户输入错误。 2.对存在问题的思考: (1)shoot函数:该函数的原型是void shoot ( int *targetAlive, double accuracy ),其形参targetAlive是指针型变量,但最初的程序却把一个普通的整型变量赋给该形参,于是错 8 《数据结构》课程设计 误提示总显示变量targetAlive没用上,但后来把同类型的变量赋给该形参,该错误就解决了。还有一个问题就是,用random函数产生随机数时,没用上randomize函数,导致每次产生的随机数都一样,得不出正确的结果,所以应同时用上randomize函数。(2)startDuel函数:问题1:该函数如何才能包含两种游戏方法,让用户运行时能够选择游戏方法?解决办法:利用if---else语句,并用n值标志游戏方法,不同的n值分别对应的游戏方法。问题2:游戏过程分支多,如何避免因重复或遗漏某一情况而产生的逻辑错误?解决办法:先在纸上清晰地列出游戏的每一种情况,哪种情况是并列关系,哪种是包含关系,要做到心中有数,接着用if——else语句把整个过程表达出来。问题3:A与B互打时,到那步结束时不确定的,怎么解决此问题?解决办法:利用while循环语句,循环条件是人数大于1.(3)main函数:问题1:如何一千次调用startDuel函数?解决办法:用for循环语句。问题2:建立一个文件时,最初总是找不到该文件。解决办法:建立文件时,要指明文件的路径方向,在哪个盘,运行程序后打开此盘就能找到该文件。 3.算法的改进思想: 以上源程序的算法,是建立在整个游戏过程的细节上的,每一种情况都要考虑难到,这给编写和调试程序带来不少的麻烦,改进思想是,用一个while循环语句,以人数大于1为循环条件,循环内容是A,B,C三个人轮流打,每次都打当前除了自己,命中率最高的人,并标明射击条件:射击者与被射击者都还活着。这样,就不用考虑游戏过程的每个细节,程序的思想也简单明了,当循环结束时,三个人也就只剩一人了,该人即获胜者。 六 测试结果 1.完备的测试计划:按如下顺序进行: (a.)输入n值为1,以测试第一种游戏方法;(b).输入y或Y继续进行,接着输入n值为2,以测试第二种游戏方法;(c).输入n值为3,以测试当输入的n值不符合要求时程序的反应. (d).输入n值为1,接着输入n或N,以测试不想继续进行第二种游戏方法时程序的反应;(e).输入n值为1,接着输入h,以测试输入错误字符时程序的反应。 中南民族大学计算机科学学院 自动化 专业 学号: 姓名 :韦加锴 9 2.实验结果: 10 《数据结构》课程设计 七 用户使用说明 按如下步骤使用: 1.进入程序运行界面,并按ctrl---F9键运行程序。 2.接着屏幕会打印出提示语,提示输入n值,即选择游戏方法,这时如果想运行A先打的方法,则输入1,若想运行B先打的方法,则输入2,接着按回车键,则得出游戏结果。 中南民族大学计算机科学学院 自动化 专业 学号: 姓名 :韦加锴 11 3.步骤2之后,屏幕会提示输入y或n,以决定是否以另一游戏方法运行程序,若输入y或Y,则继续运行,接着输入n值,再按Alt---F5键查看结果,若输入n或N,则应按Alt---F5键,于是屏幕会显示出游戏已结束的语句。 4.若用户输入的n值为除了1和2之外的其它数值,则程序会提示输入错误,这时应重新运行。若用户输入的字符是除了y,Y和n,N之外的字符,程序也会提示输入错误,这时也应重新运行程序。 12 《数据结构》课程设计 八 课程设计总结 1、在短短的一个学期内,想学好C语言和数据结构是不可能的,就连课本都学不完,就别说课外的知识了,在这次课程设计中就体现出来,编写该程序需要用到文件的知识,但上课老师根本没讲过,所以需要自己去看书,去自学,然后摸索着把刚学到的知识用到程序上。这就体现了自学的重要性。 2. 程序编出来了,并不代表就完事了,调试和修改程序,还需要花更大的精力,这就需要耐心,把每一个模块,每一句语句都仔细地检查,修改,通过很多次检查与修改,程序才有可能运行成功。通过这次课程设计,我懂得了调试程序时耐心的重要性,并提高了自己编写与调试程序的能力。 3. 很多知识与经验,自己是不懂得,这时就要虚心地去请教别人,就像这次课程设计,起初不知道怎么产生0到1的随机数,后来请教了同学,才知道,应该用random和randomize函数。 中南民族大学计算机科学学院 自动化 专业 学号: 姓名 :韦加锴 13 4. 以前,总以为程序编出来并调试过关就万事大吉了,但通过这次课程设计之后,才明白,程序不只是给自己看的,还要供别人参考并使用,所以编的程序,还需要有整齐的格式,清晰的模块,简洁易懂的语言,而且重要语句后面得有简单明了的注释语句,运行程序时能出现良好的提示菜单,这样,别人才能比较容易地参考并使用自己编写的程序。 5. 通过这次课程设计,我学到的东西不少,同时也明白了自己编程的能力还有待提高,所以我将继续努力学习C语言和其它编程语言。 14
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- 99spj.com 版权所有 湘ICP备2022005869号-5
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务