课程设计24点游戏.docx
- 文档编号:6241248
- 上传时间:2023-01-04
- 格式:DOCX
- 页数:30
- 大小:336.59KB
课程设计24点游戏.docx
《课程设计24点游戏.docx》由会员分享,可在线阅读,更多相关《课程设计24点游戏.docx(30页珍藏版)》请在冰豆网上搜索。
课程设计24点游戏
目录
1基本功能描述1
3软件设计3
3.1设计步骤3
3.2界面设计4
3.3关键功能的实现5
3.3.1发牌功能的实现5
3.3.2计时功能的实现6
3.3.3计算功能的实现7
3.3.4验算功能的实现8
4结论与心得体会9
5参考文献10
6思考题11
7附录12
7.1调试报告12
7.1.1变量未定义造成错误12
7.1.2关键类未添加12
7.1.3进度条错误13
7.2测试结果14
7.2.1在规定时间内完成点击“验算”按钮操作14
7.2.2在规定时间内未完成点击“验算”按钮操作16
7.3关键源代码17
24点游戏课程设计报告
1基本功能描述
24点游戏是一种使用扑克牌来进行的益智类游戏,游戏内容是:
从一副扑克牌中抽去大小王剩下52张,任意抽取4张牌,把牌面上的数运用加、减、乘、除和括号等进行运算得出24。
每张牌都必须使用一次,但不能重复使用。
在不同版本中,对J、Q、和K的处理有些差异。
一个常见的版本是把J、Q、和K去除,或当成10;还有一个版本是把J表示11,Q表示12,K代表13。
本次课程设计采用将J、Q、K去除,使四张牌在1~10这十张牌中随机取牌。
具体功能如下:
[1]由三个难度级别数,分别为一级、二级和三级。
每次发牌前可进行难度设置,若不设置,系统默认为难度级别数为二级。
难度级别设置完后,点击“发牌”按钮,桌面上显示四张翻开的扑克牌,并且游戏开始计时,进度条开始前进。
[2]在规定的时间内,用户可以在输入算式编辑框中输入想好的算式,并按下“验算”按钮。
如果不输入任何数字和算符,会弹出“表达式有问题!
”,然后再弹出一个对话框,显示“对不起,您的输入不正确!
”;如果输入的数字与给出的不符或者符号不合法,会弹出“对不起,您的输入不正确!
”;如果输入的数字与四张牌相符、字符亦合法但是答案不正确,就会出现“Theresultis:
!
”;如果输入算式经运算后所得答案正确,则会弹出“你做对了!
”。
点击弹出对话框的确定按钮,会出现本轮的用时和分数。
[3]如果在规定的时间内,没有点击验算按钮,则会弹出一个对话框,上面显示“TimeOver!
”。
[4]在结束本轮游戏后,如果用户想继续游戏,点击“重新发牌”按钮即可重新发牌;如果用户想结束游戏,点击“结束”按钮即可结束游戏。
2设计思路
24点游戏的具体流程图如下图1所示,下面对流程图进行详细的说明。
在游戏开始前有难度设置选项,用户可根据自己的实际水平进行设置。
难度级别有三个级别,分别为一级、二级和三级。
三个级别是通过时间来区别的,级别越高,可用时间越少。
三个级别的对应时间分别是100秒、60秒和50秒。
该设置不是必选项。
如果用户不设置,系统默认为难度级别二。
按下“发牌”,游戏开始,通过调用srand()和rand()函数,桌面上会随机显示出4张纸牌,这四张牌从1~10这10张牌中随机调出。
同时,标识耗时时标的进度条开始前进(m_Progress1->SetPos(m_Progress1->GetPos()+1),计时同步开始(SpendTime++)。
由于三个等级设置的时间不一样,进度条在三种情况下的步长也不相同。
游戏设置了时间限制,该设置是通过比较函数m_Progress1->GetPos()的返回值和参数m_Hardlevel的大小。
如果函数的返回值小于参数m_Hardlevel,代表游戏还没结束,用户还有时间进行思考。
否则,本轮游戏结束,在函数OnTimer()的作用下,会弹出对话“TimeOver!
”。
若用户在规定时间内点击了“验算”按钮,系统通过对SubCompute()和TotalCompute()两函数的调用进行相应运算,紧接着系统调用OnYanSuan()函数对编辑框中运算出的结果进行验算,根据验算情况给出相应的结果。
出现的结果有以下四中情况:
(1)如果用户没在输入算式中输入算式,直接按“验算”按钮,会弹出“表达式不能为空白!
”的提示对话框。
(2)如果输入的数字与给出的不符或者符号不合法,会弹出“你的输入不正确!
”的提示对话框。
(3)如果输入的数字与四张牌相符、字符亦合法但是答案不正确,会弹出“Theresultis:
!
”。
(4)如果输入算式经运算后所得答案正确,则会弹出“你做对了!
”在以上任意一种情况下,点击弹出框中的“确定”按钮,系统会自动给出本局的得分和耗时。
游戏的耗时使用SSpendTime.Format("%d",SpendTime)这个函数进行显示,游戏得分是在综合考虑游戏级别、游戏所耗费时间的基础上给出(m_score=100*(m_Hardlevel-SpendTime)/m_Hardlevel)。
于是,本轮游戏结束。
本轮游戏结束后,用户可以选择重新开始,否则,可以点击“结束”按钮退出游戏。
3软件设计
3.1设计步骤
24点游戏的具体设计步骤如下:
[1]创建MFCAppWizard(exe)工程,键入对应的工程名(dinglu),在应用程序类型中选择基本对话框,其余的都采用默认选项,完成对话框的创建。
[2]通过插入-资源-Bitmap加载图片,图片通过拷贝和复制等操作加载完成。
加载完成的图片在对应的工作区可以找到,选中对其名字进行修改。
在对话框中添加4个图像、9个按钮、3个编辑框、1个进度条和3个单选按钮。
然后,根据属性对以上所添加的控件进行属性修改,主要是对其进行重命名。
图像内的属性修改除改名外,还要添加位图。
[3]下一步是对以上控件建立类向导,主要包括AddFunction、AddVariable和EditCode这三项的添加。
[4]在类的原文件中添加实现功能所需要的各种函数,并添加相应的代码,同时在头文件中添加对各种函数及变量的声明。
[5]对完成的程序进行保存,然后开始调试,根据错误进行修改,直至程序不在报错,并且可以实现预计的各种功能。
图224点游戏运行图
3.2界面设计
24点游戏所用控件说明图如下:
表1控件类型、ID及相关说明
对象
ID
Caption或说明
变量名
进程
IDC_PROGRESS1
耗时
m_Progress1
静态文本
IDC_STATIC
静态文字说明
一级单选按钮
IDC_RADIO1
一级
m_Hardleve
二级单选按钮
IDC_RADIO2
二级
三级单选按钮
IDC_RADIO3
三级
位图
IDC_Picture0
位图
位图
IDC_Picture1
位图
位图
IDC_Picture2
位图
位图
IDC_Picture3
位图
编辑框
IDC_EDIT1
输入计算
m_Edit1
编辑框
IDC_STATIC10
时间
SpendTime
编辑框
IDC_STATIC11
得分
m_score
按钮
IDC_Start
开始
按钮
IDC_YanSuan
验算
续表
对象
ID
Caption或说明
变量名
按钮
IDC_OK
退出
按钮
IDC_PARENL_BUTTON
(
按钮
IDC_ADD_BUTTON
+
按钮
IDC_SUB_BUTTON
-
按钮
IDC_MUL_BUTTON
*
按钮
IDC_DEVIDE_BUTTON
/
按钮
IDC_PARENR_BUTTON
)
3.3关键功能的实现
3.3.1发牌功能的实现
首先,通过BOOLCDingluDlg:
:
OnInitDialog()中,根据纸牌对应的ID号加载纸牌,例如:
Bitmap[7].LoadBitmap(IDB_BITMAP7)这条语句加载标有7的纸牌。
利用该函数加载了标号1~10的十张纸牌和两张背景纸牌。
然后运行中的以下一段代码,即可在图像框中得到四张铺开的纸牌。
代码如下:
srand((int)time(0));
for(inti=0;i<4;i++)
Number[i]=rand()%13;//产生一个0—12的随机数
((CStatic*)GetDlgItem(IDC_Picture0))->SetBitmap(HBITMAP(Bitmap[Number[0]]));
((CStatic*)GetDlgItem(IDC_Picture1))->SetBitmap(HBITMAP(Bitmap[Number[1]]));
((CStatic*)GetDlgItem(IDC_Picture2))->SetBitmap(HBITMAP(Bitmap[Number[2]]));
((CStatic*)GetDlgItem(IDC_Picture3))->SetBitmap(HBITMAP(Bitmap[Number[3]]));
srand(seed)用来设置rand()产生随机数时的随机数种子。
参数seed必须是个整数,通常可以利用geypid()或time(0)的返回值来当做seed。
如果每次seed都设相同值,rand()所产生的随机数值每次就会一样。
rand的内部实现是用线性同余法做的,他不是真的随机数,只不过是因为其周期特别长,所以有一定的范围里可看成是随机的,rand()会返回一随机数值,范围在0至RAND_MAX间。
在调用此函数产生随机数前,必须先利用srand()设好随机数种子,如果未设随机数种子,rand()在调用时会自动设随机数种子为1。
rand()产生的是假随机数字,每次执行时是相同的。
若要不同,以不同的值来初始化它.初始化的函数就是srand()。
3.3.2计时功能的实现
首先,在voidCDingluDlg:
:
OnStart()中,通过m_Progress->SetStep
(1)和m_Progress
->SetPos(0)设置进度条的步长为1,进度条的初始位置居左。
然后调用voidCDingluDlg
:
:
OnTimer(UINTnIDEvent)来完成计时功能。
利用函数if(m_Progress1->GetPos()>=
m_Hardlevel)来判断即使结束了没有,如果括号中的条件满足,则计时结束,跳出“TimeOver!
”的提示框。
如果括号中的条件不满足,则执行以下代码:
CProgressCtrl*m_Progress1=(CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);
m_Progress1->SetRange(0,m_Hardlevel);
m_Progress1->SetPos(m_Progress1->GetPos()+1);//进度条前进一步
上述代码表示,如果时间没到,时间每流逝1秒,进度条就前进一步。
当游戏时间即将结束的时候,进度条亦前进到最后一步。
3.3.3计算功能的实现
对于输入结果的验算,主要是通过intLastPos(CStringStr),intFirstPos(CStringStr),charFirstF(CStringStr),intSubCompute(CStringStr),intTotalCompute(CStringStr)等函数来来确定运算式各符号优先级和最终计算出输入算式的结果。
现摘两段代码进行详细说明。
代码1:
intPluPos=Str.Find('+')+1;
intPos=200;
if(PluPos==0)
PluPos=200;
if(Pos>PluPos)
Pos=PluPos;
charResult='-';
inttempPos=SubPos;
if(PluPos { Result='+'; tempPos=PluPos; } returnResult; 代码1的作用是判断最先出现的符号是不是+号。 Pluspos表示+号出现的位置,如果没有+号出现,对pluspos负一个不可能的值;如果+号存在,将pluspos与pos比较大小。 如果pluspos小于pos,将pluspos的值负给pos。 pluspos再与tempos比较,如果在减号之前出现,显示的结果是+号。 代码2: intCDingluDlg: : TotalCompute(CStringStr) { intFirst=Str.ReverseFind('(')+1; while(First) {CStringSubStr=Str.Mid(First,(Str.GetLength()-First)); intLast=SubStr.Find(')')+1; Last+=First CStringLeft=Str.Mid(0,First-1) CStringMiddle=Str.Mid(First,Last-First-1) CStringRight=Str.Mid(Last,Str.GetLength()-Last) intResult=SubCompute(Middle) Middle.Format("%d",Result); Str=Left+Middle+Right; First=Str.ReverseFind('(')+1; } intResult=SubCompute(Str); returnResult; } 代码2的作用是对于编辑框中输入的表达式进行计算,系统通过Str.ReverseFind('(')+1来反向查找定位第一个“(”所在的位置。 然后通过while循环查找到表达式最内层的括号,又借助于Str=Left+Middle+Right;将有优先级差别同时不带括号的表达式传送到SubCompute()函数中,最终计算出输入到编辑框中的表达式结果Result,并将其返回。 3.3.4验算功能的实现 1.弹出框的实现 在规定的时间内输入算式进行验算,根据不同的情况会出现不同的对话框。 有以下四种情况: 如果用户没在输入算式中输入算式,直接按“验算”按钮,会弹出“表达式不能为空白! ”的提示对话框;如果输入的数字与给出的不符或者符号不合法,会弹出“你的输入不正确! ”的提示对话框;如果输入的数字与四张牌相符、字符亦合法但是答案不正确,会弹出“Theresultis: ! ”;如果输入算式经运算后所得答案正确,则会弹出“你做对了! ”。 具体代码如下: if(Str==""){MessageBox("表达式不能为空白! ","Warning! ",MB_OK);flag=0;} if(Result==24)MessageBox("你输入正确! ","TURE! ",MB_OK); 由于代码太长,只摘取不输入与输入计算结果正确两种情况进行说明。 当输入Str为空时,通过MessageBox()显示“表达式不能为空白! ”。 当输入算式正确,判断计算结果Result==24,通过MessageBox()显示“你输入正确! ”。 当输入字符有错,通过一段很长的程序判断,然后通过MessageBox()显示“你输入的不正确! ”。 2.等分功能的实现 当用户在每局游戏结束后,如果没有计算出正确结果,得分会显示为0分;如果计算出了正确结果,则会显示一个0~100之间的整数值。 用户最终得分的确定是由其选择的游戏级别和游戏所花费时间长短来确定的。 实现代码如下: if(Result==24) {CStringSscore;m_score=100*(m_Hardlevel-SpendTime)/m_Hardlevel; Sscore.Format("%d",m_score); GetDlgItem(IDC_STATIC11)->SetWindowText(""+Sscore+"分"); UpdateData(FALSE); } OnYanSuan()函数来对编辑框中运算出的结果进行验算,如果Result==24,则if语句 被执行。 语句m_score=100*(m_Hardlevel-SpendTime)/m_Hardlevel;说明用户花费时间越长或者游戏剩余时间占总时间比重越小,则本局游戏得分也相应越小。 而通过语句Sscore.Format("%d",m_score);的作用则将int量m_score转换为Cstring量Sscore。 同时,SetWindowText()函数发挥作用,显示出分数Sscore。 4结论与心得体会 VC++的课程设计终于接近尾声了,又到了写课程设计报告的时间了。 这次课设比以往的课设任务重、安排紧。 之所以这么安排,我是这么理解的,这次安排单片机的课设是为了巩固上课所学的知识,将其应用到实践中来,好歹也是这学期学的。 至于安排VC++的课设,我开始是很不能理解,因为我们是大二上学期学的,丢了快一年了,现在做课设又得重新将它捡起来,这很费时间。 后来做完课设,看着自己的游戏界面,可以像平时玩的小游戏一样玩,感觉还挺自豪的,觉得这一星期没有白过。 这一星期走来,我感受颇多,大约有以下几点: 首先,这次课设对VC+起到温故知新的作用。 课程设计之初,思路全无,举步维艰,对于理论知识学习不够扎实的我深感“书到用时方恨少”。 于是,重新捡起课本,对照课本基本控件这一章,将计算器和菜单栏制作这两个范例做了几遍。 对于进程条的设置不清楚,又找同学复制了以前的课件来看,经与同学的再三讨论,终于弄清了进程条的设置。 至于编程这一块,那是忘得更多了,于是又借了基本参考书来看,遇到难处先是仔细的思考然后在向同学请教。 可以说开始的那么几天都是在查找资料,翻阅相关的书籍。 其次,这次课设让我明白了实践出真理的道理。 最初答辩弄完后,还有一些程序不知道怎么写。 于是,又从网上收集相关程序,经分析、查询资料仍有一些地方看不懂。 只能 采用尝试往对话框中添加相应代码的方法。 根据一大段的分析,感觉程序执行某个功能,将这段代码添加到对应位置。 所有的代码添加完后,运行、调试,开始会有很多错误出现。 我记得最多的时候有63个错误,逐条进行修改,再进行运行和调试。 也不知道改了多少次和重做了多少次,终于做出了完美的游戏界面。 再者,让我学会了如何创新。 得到游戏界面后,我又从网上下了几个24点游戏与我的相比较。 相比较发现,网上的游戏出牌比较合理,我的游戏出牌很杂乱,很多情况都是无解,我也相应做了调整。 再者,我发现很多游戏都是倒计时,我也进行了尝试。 除此,我发现有些游戏也加了四张牌的按钮,一发牌,对应的牌就显示在快捷键上,这点我也做了尝试。 以上三点,就是我关于本次课设的创新,虽然最后没能实现,但这个过程的实践是快乐的,代表我开动了脑筋。 最后,这是一场毅力的考验。 课设开始给人感觉很难,但很庆幸我们都没有畏惧,还是尽力去查资料、想办法解决。 怎么说,“态度决定一切”,我们终于跨越了这道障碍,圆满完成了课设。 5参考文献 [1]刘於勋等.C++程序设计.科学出版社,2007 [2]荣钦科技.VisualC++游戏编程基础.电子工业出版社,2004 [3]揣锦华.面向对象程序设计与VC++实践.西安电子科技大学出版社,2005 [4]罗伟坚.VisualC++经典游戏程序设计.人民邮电出版社,2006 6思考题 1.改变难度可以变化游戏的限时和游戏加分的规则,如何实现? 游戏的限时是通过对进度条的设置来实现的,通过定义一个m_Hardlevel变量之后,用它来设置进度条的范围(SetRange(0,m_Hardlevel);),即当用户选择不同级别的游戏时,进度条的范围会随着m_Hardlevel的值而不同,游戏难度越大,m_Hardlevel的值越小(本游戏中共设置了100秒、60秒、50秒三个级别),时间也就越短,反之时间越长。 游戏的加分规则综合考虑了用户选择的游戏级别和一局游戏所花费时间的长短,即: m_score=100*(m_Hardlevel-SpendTime)/m_Hardlevel;也就是说难度的选择和用户所用时间同时决定最后的得分。 2.如何保证程序是根据给出的牌来书写算式的? 答: 首先通过每张纸牌的ID号,将它们加载到Bitmap[]中,通过随机函数得到四个随机数之后,亦即得到四张系统随机发放的纸牌;然后利用指针将得到的纸牌在voidCDingluDlg: : OnStart()中进行相应设置;最后在voidCDingluDlg: : OnYanSuan()中,通过Mid()和intm=(int)(int)(strtod(Mul1.GetBuffer(Mul1.GetLength()),&stopstring));获取用户输入到编辑框中的数据,将m和Number[i]进行比较,从而最终确保程序是根据给出的牌来书写算式的。 3.如何使用随机函数控制扑克牌的显示? 答: 首先在BOOLCDingluDlg: : OnInitDialog()中,用纸牌对应的ID号对纸牌进行加载(如Bitmap[12].LoadBitmap(IDB_BITMAP12)),然后在voidCDingluDlg: : OnStart()中,利用srand((int)time(0));和Number[i]=rand()%13;两条语句选出相对应的四张纸牌,即可得到随机发放的四张扑克牌了。 7附录 7.1调试报告 7.1.1变量未定义造成错误 在代码添加过程中,由于涉及很多的函数和变量,可能会出现某几个变量忘定义的情况,这些变量有可能是在头文件中忘记定义或者在某个函数体中忘记定义。 下面举一个在头文件中变量忘定义的例子,如下所示: 图3因变量未定义而出现的错误截面图 在添加完各个函数的代码完毕后,以为头文件会自动对相应得变量进行定义,但头文件没有对所有的变量都定义,才出现了如上图所示的错误。 打开头文件,双击dingluDlg.h,在classCDingluDlg: publicCdialog类定义函数中添加对m_Hardlevel参数的定义。 添加完毕后,程序不再报这个错误。 7.1.2关键类未添加 在画图对话框中,摆好各种控件后,逐一对每个控件添加类向导。 对话框中出现的控件一般都不会忘记建立类向导,但有1个类向导是容易忘记的,它是IDC_PROGRESS1建立的类向导名称是OnOutofmemoryProgress1。 下面用图形表示这个错误,如下所示: 根据错误提示,重新选中图片,建立OnOutofmemoryProgress1的类向导。 建立完毕后,重新运行程序,不再提示开错误。 图4因关键类未添加而出现的错误截面图 7.1.3进度条错误 类导向和代码添加完后,运行程序,出现游戏界面。 点击游戏界面内的“发牌”按钮,出现四张扑克展开,但是没过2秒钟跳出“TimeOver! ”对话框,并且进度条不动。 下面用图形表示这个错误,如下图所示: 图5进度条设置错误而出现的错误截面图 这个错误可能是计时时间设置的太短,进度条的步长设置的不合理。 重新设置计时时间范围和进度条步长,然后运行程序,错误仍然存在。 再从头到尾把程序检查一遍,做相应修改,再运行,错误仍然存在。 于是将所有类删除后重新添加,并且添加相应程序,重新运行,错误消失。 7.2测试结果 7.2.1在规定时间内完成点击“验算”按钮操作 测试过程中,由于既涉及到纸牌点数和运算符,又会涉及到运算式结果,于是相应地会显示出四种结果,分别是: 如果用户没在输入算式
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 课程设计 24 游戏