完整word版24点游戏设计.docx
《完整word版24点游戏设计.docx》由会员分享,可在线阅读,更多相关《完整word版24点游戏设计.docx(36页珍藏版)》请在冰豆网上搜索。
完整word版24点游戏设计
24点游戏程序设计报告
1基本功能描述
1.124点游戏介绍
24点游戏是一款与计算有关的益智游戏,其游戏规则如下:
从一副扑克牌中抽去大小王剩下52张,任意抽取4张牌,把牌面上的数运用加、减、乘、除和括号等进行运算得出24便可获胜。
值得注意的是每张牌都必须使用一次,但不能重复使用,其中,J代表数值11,Q代表数值12,K代表数值13。
1.2游戏功能介绍
“游戏难度可选”功能设计。
将游戏难度分别为初级、中等和高级。
每次发牌前可进行难度设置,若不设置,系统默认为难度级别数为初级。
难度级别设置完后,点击“开始游戏”按钮,便可以开始游戏,并开始计时。
“游戏规则可查看”功能设计。
此功能是在Dialog类创建ID为IDD_DIALOG_NEW对话框,并在对话中添加静态文本,其中文本内容即为1.1中陈述的游戏规则。
“游戏时间限制即进度条”功能设计。
在规定的时间内,用户可以在输入算式编辑框中输入想好的算式,并按下“结果”按钮。
如果不输入任何数字和算符,会弹出“输入有误!
”;如果输入的数字与给出的不符或者符号不合法,会弹出“输入有误!
”;如果输入的数字与四张牌相符、字符亦合法但是答案不正确,就会出现“回答不正确!
”;如果输入算式经运算后所得答案正确,则会弹出“你做对了!
”。
如果在规定的时间内,没有点击验算按钮,则会弹出一个对话框,上面显示“TimeOver!
”。
“菜单栏”功能设计。
在设计界面时,添加了菜单栏功能,菜单栏的主要选项有:
游戏选项,游戏难度,帮助。
以上就是此次24点游戏主要的基本功能,其具体游戏功能,以及功能实现将在下文详述。
2设计思路
2.1游戏过程简述
在游戏开始前有难度设置选项,用户可根据自己的实际水平进行设置。
难度级别有三个级别,分别为初级、中等和高级。
三个级别是通过时间来区别的,级别越高,可用时间越少。
三个级别的对应时间分别是60秒、40秒和20秒。
该设置不是必选项。
如果用户不设置,系统默认为初级。
下面详细介绍各个功能模块的实现过程。
运行程序LiPingLin_24后,当单击按钮“游戏规则”时,编译器会调用函数OnOperString()来弹出对话框IDD_DIALOG_NEW;从而实现“游戏规则可查看”功能。
运行程序LiPingLin_24后,当点击单选按钮“初级”“中等”“困难”(选择游戏难度)时,编译器会设置游戏难度。
intiRADIO=GetCheckedRadioButton(IDC_RADIO1,IDC_RADIO3);
if(iRADIO==IDC_RADIO1)
{m_Hardlevel=60;}//初级,允许时间为60秒——初级
if(iRADIO==IDC_RADIO2)
{m_Hardlevel=40;}//中等,允许时间为40秒——中等
if(iRADIO==IDC_RADIO3)
{m_Hardlevel=20;}//高级,允许时间为20秒——高级
运行程序LiPingLin_24后,当单击按钮“开始游戏”时,编译器会调用函数OnStart()来实现编辑框清零,耗时初始化为零,读取游戏难度即允许时间,随机产生4张扑克牌并加载到扑克牌的位置。
voidCLiPingLin_24Dlg:
:
OnStart()
{
S=1;
m_Edit1=_T("");//对编辑框清空
UpdateData(FALSE);//用负给控件变量的值来刷新控件,让控件把操作后的变量显示出
srand((int)time(0));//以(int)time(0)做为srand()函数的种子seed
for(inti=0;i<4;i++)//应用for语句来为四张牌赋值
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]]));
…
}
单击按钮“开始游戏”后,当编辑框输入完毕单击按钮“结果验证”时,编译器会函数OnYanSuan()来停止计时,刷新数据,验证数据是否满足24。
系统通过对SubCompute()和TotalCompute()两函数的调用进行相应运算,紧接着系统调用OnYanSuan()函数对编辑框中运算出的结果进行验算,根据验算情况给出相应的结果。
出现的结果有以下四中情况:
如果用户没在输入算式中输入算式,直接按“结果验证”按钮,会弹出“表达式不能为空白!
”的提示对话框。
如果输入的数字与给出的不符或者符号不合法,会弹出“输入有误!
”的提示对话框。
如果输入的数字与四张牌相符、字符亦合法但是答案不正确,会弹出“回答不正确!
”。
如果输入算式经运算后所得答案正确,则会弹出“你做对了!
”
voidCLiPingLin_24Dlg:
:
OnYanSuan()
{…}
运行程序LiPingLin_24后,当单击按钮“游戏结束”时,编译器会调用函数OnOk()来实现退出。
voidCLiPingLin_24Dlg:
:
OnOk()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
OnOK();
}
本轮游戏结束后,用户可以选择重新开始,否则,可以点击“结束游戏”按钮退出游戏。
2.2游戏设计流程图
综合2.1游戏过程简述,分析游戏功能,其24点游戏程序设计流程图见图1。
图124点游戏程序设计流程图
3软件设计
3.1设计步骤
下面详细介绍24点游戏的具体设计步骤。
创建MFCAppWizard(exe)工程,键入对应的工程名(dinglu),在应用程序类型中选择基本对话框,其余的都采用默认选项,完成对话框的创建。
通过插入-资源-Bitmap加载图片,图片通过拷贝和复制等操作加载完成。
加载完成的图片在对应的工作区可以找到,选中对其名字进行修改。
在对话框中添加4个图像、9个按钮、3个编辑框、1个进度条和3个单选按钮。
然后,根据属性对以上所添加的控件进行属性修改,主要是对其进行重命名。
图像内的属性修改除改名外,还要添加位图。
下一步是对以上控件建立类向导,主要包括AddFunction、AddVariable和EditCode这三项的添加。
在类的原文件中添加实现功能所需要的各种函数,并添加相应的代码,同时在头文件中添加对各种函数及变量的声明。
对完成的程序进行保存,然后开始调试,根据错误进行修改,直至程序不在报错,并且可以实现预计的各种功能。
3.2关键功能的实现
3.2.1随机发牌功能的实现
首先,通过BOOLCDingluDlg:
:
OnInitDialog()中,根据纸牌对应的ID号加载纸牌,例如:
Bitmap[7].LoadBitmap(IDB_BITMAP7)这条语句加载标有7的纸牌。
利用该函数加载了标号1~10的十张纸牌和两张背景纸牌。
然后运行中的以下一段代码,即可在图像框中得到四张铺开的纸牌。
srand(seed)用来设置rand()产生随机数时的随机数种子。
参数seed必须是个整数,通常可以利用geypid()或time(0)的返回值来当做seed。
如果每次seed都设相同值,rand()所产生的随机数值每次就会一样。
rand的内部实现是用线性同余法做的,他不是真的随机数,只不过是因为其周期特别长,所以有一定的范围里可看成是随机的,rand()会返回一随机数值,范围在0至RAND_MAX间。
在调用此函数产生随机数前,必须先利用srand()设好随机数种子,如果未设随机数种子,rand()在调用时会自动设随机数种子为1。
rand()产生的是假随机数字,每次执行时是相同的。
若要不同,以不同的值来初始化它.初始化的函数就是srand()。
3.2.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.2.3计算功能的实现
对于输入结果的验算,主要是通过intLastPos(CStringStr),intFirstPos(CStringStr),charFirstF(CStringStr),intSubCompute(CStringStr),intTotalCompute(CStringStr)等函数来来确定运算式各符号优先级和最终计算出输入算式的结果。
Pluspos表示+号出现的位置,如果没有+号出现,对pluspos负一个不可能的值;如果+号存在,将pluspos与pos比较大小。
如果pluspos小于pos,将pluspos的值负给pos。
pluspos再与tempos比较,如果在减号之前出现,显示的结果是+号。
代码1:
intCLinPingLin_24Dlg:
:
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;
}
代码1的作用是对于编辑框中输入的表达式进行计算,系统通过Str.ReverseFind('(')+1来反向查找定位第一个“(”所在的位置。
然后通过while循环查找到表达式最内层的括号,又借助于Str=Left+Middle+Right;将有优先级差别同时不带括号的表达式传送到SubCompute()函数中,最终计算出输入到编辑框中的表达式结果Result,并将其返回。
3.2.4验算功能的实现
在规定的时间内输入算式进行验算,根据不同的情况会出现不同的对话框。
有以下四种情况:
如果用户没在输入算式中输入算式,直接按“结果验证”按钮,会弹出“表达式不能为空白!
”的提示对话框;如果输入的数字与给出的不符或者符号不合法,会弹出“输入有误!
”的提示对话框;如果输入的数字与四张牌相符、字符亦合法但是答案不正确,会弹出“回答不正确!
”;如果输入算式经运算后所得答案正确,则会弹出“你做对了!
”。
由于代码太长,只摘取不输入与输入计算结果正确两种情况进行说明。
当输入Str为空时,通过MessageBox()显示“表达式不能为空白!
”。
当输入算式正确,判断计算结果Result==24,通过MessageBox()显示“你输入正确!
”。
当输入字符有错,通过一段很长的程序判断,然后通过MessageBox()显示“输入有误!
”。
4结论与心得体会
此次课设比以往的课设任务重、安排紧。
之所以这么安排,这次安排单片机的课设是为了巩固上课所学的知识,将其应用到实践中来,好歹也是这学期学的。
至于安排VC++的课设,我开始是很不能理解,因为我们是大二上学期学的,丢了快一年了,现在做课设又得重新将它捡起来,这很费时间。
后来做完课设,看着自己的游戏界面,可以像平时玩的小游戏一样玩,感觉还挺自豪的,觉得这一星期没有白过。
这一星期走来,我感受颇多,大约有以下几点:
首先,这次课设对VC+起到温故知新的作用。
课程设计之初,思路全无,举步维艰,对于理论知识学习不够扎实的我深感“书到用时方恨少”。
于是,重新捡起课本,对照课本基本控件这一章,将计算器和菜单栏制作这两个范例做了几遍。
对于进程条的设置不清楚,又找同学复制了以前的课件来看,经与同学的再三讨论,终于弄清了进程条的设置。
至于编程这一块,那是忘得更多了,于是又借了基本参考书来看,遇到难处先是仔细的思考然后在向同学请教。
可以说开始的那么几天都是在查找资料,翻阅相关的书籍。
其次,这次课设让我明白了实践出真理的道理。
最初答辩弄完后,还有一些程序不知道怎么写。
于是,又从网上收集相关程序,经分析、查询资料仍有一些地方看不懂。
只能
采用尝试往对话框中添加相应代码的方法。
根据一大段的分析,感觉程序执行某个功能,将这段代码添加到对应位置。
所有的代码添加完后,运行、调试,开始会有很多错误出现。
我记得最多的时候有34个错误,逐条进行修改,再进行运行和调试。
也不知道改了多少次和重做了多少次,终于做出了完美的游戏界面。
此外,让我学会了如何创新。
得到游戏界面后,我又从网上下了几个24点游戏与我的相比较。
相比较发现,网上的游戏出牌比较合理,我的游戏出牌很杂乱,很多情况都是无解,我也相应做了调整。
再者,我发现很多游戏都是倒计时,我也进行了尝试。
除此,我发现有些游戏也加了四张牌的按钮,一发牌,对应的牌就显示在快捷键上,这点我也做了尝试。
以上三点,就是我关于本次课设的创新,虽然最后没能实现,但这个过程的实践是快乐的,代表我开动了脑筋。
总之,在此课设中收获了很多知识,学习到更多的MFC知识,为我日后的发展有更大的帮助。
5思考题
1.改变难度可以变化游戏的限时和游戏加分的规则,如何实现?
游戏的限时是通过对进度条的设置来实现的,通过定义一个m_Hardlevel变量之后,用它来设置进度条的范围(SetRange(0,m_Hardlevel);),即当用户选择不同级别的游戏时,进度条的范围会随着m_Hardlevel的值而不同,游戏难度越大,m_Hardlevel的值越小(本游戏中共设置了60秒、40秒、20秒三个级别),时间也就越短,反之时间越长。
游戏的加分规则综合考虑了用户选择的游戏级别和一局游戏所花费时间的长短,即:
m_score=100*(m_Hardlevel-SpendTime)/m_Hardlevel;也就是说难度的选择和用户所用时间同时决定最后的得分。
2.如何保证程序是根据给出的牌来书写算式的?
答:
首先通过每张纸牌的ID号,将它们加载到Bitmap[]中,通过随机函数得到四个随机数之后,亦即得到四张系统随机发放的纸牌;然后利用指针将得到的纸牌在voidCLinPingLin_24Dlg:
:
OnStart()中进行相应设置;最后在voidCLinPingLin_24Dlg:
:
OnYanSuan()中,通过Mid()和intm=(int)(int)(strtod(Mul1.GetBuffer(Mul1.GetLength()),&stopstring));获取用户输入到编辑框中的数据,将m和Number[i]进行比较,从而最终确保程序是根据给出的牌来书写算式的。
3.如何使用随机函数控制扑克牌的显示?
答:
首先在BOOLCLinPingLin_24Dlg:
:
OnInitDialog()中,用纸牌对应的ID号对纸牌进行加载,然后在voidCLinPingLin_24Dlg:
:
OnStart()中,利用srand((int)time(0));和Number[i]=rand()%13;两条语句选出相对应的四张纸牌,即可得到随机发放的四张扑克牌了。
附录
1调试实验报告
1.1变量未定义造成错误
错误:
在代码添加过程中,由于涉及很多的函数和变量,可能会出现某几个变量忘定义的情况,这些变量有可能是在头文件中忘记定义或者在某个函数体中忘记定义。
:
修改:
在添加完各个函数的代码完毕后,以为头文件会自动对相应得变量进行定义,但头文件没有对所有的变量都定义,才出现了如上图所示的错误。
打开头文件,双击LinPingLin_24Dlg.h,在classCLinPingLin_24Dlg:
publicCdialog类定义函数中添加对m_Hardlevel参数的定义。
添加完毕后,程序不再报这个错误。
1.2关键类未添加
错误:
在对话框中,摆好各种控件后,逐一对每个控件添加类向导。
对话框中出现的控件一般都不会忘记建立类向导,但有1个类向导是容易忘记的,它是IDC_PROGRESS1建立的类向导名称是OnOutofmemoryProgress1。
修改:
根据错误提示,重新选中图片,建立OnOutofmemoryProgress1的类向导。
建立完毕后,重新运行程序,不再提示开错误。
1.3进度条错误
错误:
类导向和代码添加完后,运行程序,出现游戏界面。
点击游戏界面内的“开始游戏”按钮,出现四张扑克展开,但是没过2秒钟跳出“TimeOver!
”对话框,并且进度条不动。
修改:
这个错误可能是计时时间设置的太短,进度条的步长设置的不合理。
重新设置计时时间范围和进度条步长,然后运行程序,错误仍然存在。
再从头到尾把程序检查一遍,做相应修改,再运行,错误仍然存在。
于是将所有类删除后重新添加,并且添加相应程序,重新运行,错误消失。
2测试结果
2.1页面验证
下面详细验证下页面的功能,以及各功能是否能实现。
菜单栏验证,见图2。
图2菜单栏验证
控件“游戏规则验证”,见图3。
图3游戏规则验证
2.1运算测试
测试过程中,由于既涉及到纸牌点数和运算符,又会涉及到运算式结果,于是相应地会显示出四种结果,分别是:
如果用户没在输入算式中输入算式,直接按“结果”按钮,会弹出“表达式不能为空!
”的提示对话框;如果输入的数字与给出的不符或者符号不合法,会弹出“你的输入不正确!
”的提示对话框;如果输入的数字与四张牌相符、字符亦合法但是答案不正确,会弹出“输入有误!
”;如果输入算式经运算后所得答案正确,则会弹出“你做对了!
”。
下面用图形做相应说明。
输入算式为空,点击“验算”,显示“表达式不能为空!
”,如下图4所示。
图4空白验证
输入的数字与给出的不符或者符号不合法,点击“结果验证”,会弹出“你的输入不正确!
”,如下图5所示。
图5输入有误验证
规定时间内未进行输入,或输入后未完成点击“验算”按钮操作,显示“TimeOver!
”,如下图5所示。
图6时间限制验证
3关键源代码
charCLiPingLin_24Dlg:
:
FirstF(CStringStr)
{
intSubPos=Str.Find('-')+1;//从字符串Str中查找减号的位置
intPluPos=Str.Find('+')+1;//从字符串Str中查找加号的位置
intMulPos=Str.Find('*')+1;//从字符串Str中查找乘号的位置
intDivPos=Str.Find('/')+1;//从字符串Str中查找除号的位置
intPos=200;//设定一个变量,并赋初值200
if(SubPos==0)
SubPos=200;//如果没有减号,给SubPos赋一个不可能的值
if(PluPos==0)
PluPos=200;//如果没有加号,给PluPos赋一个不可能的值
if(MulPos==0)
MulPos=200;//如果没有乘号,给MulPos赋一个不可能的值
if(DivPos==0)
DivPos=200;//如果没有除号,给DivPos赋一个不可能的值
if(Pos>SubPos)
Pos=SubPos;//减号存在,并且把SubPos的值赋给Pos
if(Pos>PluPos)
Pos=PluPos;//加号存在,并且把PlusPos的值赋给Pos
if(Pos>MulPos)
Pos=MulPos;//乘号存在,并且把MulPos的值赋给Pos
if(Pos>DivPos)
Pos=DivPos;//除号存在,并且把DivPos的值赋给Pos
charResult='-';//将'-'赋给Result
inttempPos=SubPos;//定义变量tempPos,并将SubPos的值赋给tempPos
if(PluPos{
Result='+';
tempPos=PluPos;//如果+号在-号之前出现,Result的值为'+'
}
if(MulPos{
Result='*';
tempPos=MulPos;//如果*号在-号之前出现,Result的值为'*'
}
if(DivPos{
Result='/';
tempPos=DivPos;//如果/号在-号之前出现,Result的值为'/'
}
returnResult;//将Result的值返回
}
//定位第一个算术符号的位置
intCLiPingLin_24Dlg:
:
FirstPos(CStringStr)
{
intSubPos=Str.Find('-')+1;//从字符串Str中查找减号的位置
intPluPos=Str.Find('+')+1;//从字符串Str中查找加号的位置
intMulPos=Str.Find('*')+1;//从字符串Str中查找乘号的位置
intDivPos=Str.Find('/')+1;//从字符串Str中查找除号的位置
intPos=200;
if(SubPos==0)//如果没有-号
SubPos=200;//将SubPo