《24点游戏设计报告.doc》由会员分享,可在线阅读,更多相关《24点游戏设计报告.doc(29页珍藏版)》请在三一办公上搜索。
1、基本功能描述24点游戏是一种常见的数学运算游戏,玩游戏者只需根据系统给出的四张19的纸牌算出24即可,而程序主要负责实现随机发牌、结果验算、计算得分和难度设置等功能。设计的程序要求具有如下功能:(1)按下“发牌”按钮时开始游戏,桌面上显示4张翻开的扑克牌,并且游戏开始计时,进度条开始前进。(2)当用户能够将4张牌计算出24时,可以按下“输入算式”按钮,此时游戏计时停止,用户可在编辑框中输入。(3)输入结束,用户按下“验算”按钮,计算输入的多项式。验算通过,显示“正确”;验算出错,显示“错误”。(4)如果用户希望继续游戏,则可按下“发牌”按钮;否则按下“结束游戏”按钮。在运行游戏时,还可以通过难
2、度级别的下拉列表来改变游戏的难度。改变难度可以变化游戏的限时和游戏加分的规则。运行后的初始界面为:运行成功后的界面为:设计框图运行调试出错调试出错调试出错功能调试功能调试功能调试添加进度条完成调试通过编写消息处理代码编写消息处理代码编写消息处理代码添加列表控件添加组合框添 加按钮添加静态控件应用程序界面设计导入扑克牌资源创建基于对话框的应用程序原理、功能分析开始加载菜单资源软件设计过程一、应用程序界面设计首先创建一个名为“24点游戏”的工程。启动VC6.0,依次点击“文件新建”,在弹出的对话框中选择工程类型为“MFC AppWizard(exe)”,工程名取为“24点游戏”,保存在“D:赵志刚
3、24点游戏”目录下,选择基于对话框的应用程序类型,生成与用户交互的应用程序界面。程序界面如图1所示(图1)通过对应用程序基本功能的描述,可以知道要实现该程序的功能,在所设计的基于对话框的应用程序中应包括以下资源及控件:(一)资源扑克牌资源:由于Windows系统自带的纸牌游戏中存放有扑克牌,故可以将所需的扑克牌资源导入应用程序。首先找到位于WINDOWS目录下的cards.dll文件,然后选择VC IDE中的“文件 | 打开”,文件类型选择Executable Files(.exe;.dll;.ocx),“打开方式” 选择Resource,然后打开cards.dll文件(如下图2所示)。打开c
4、ards.dll,选择其中所需的Bitmap,按住鼠标左键不放,将Bitmap直接拖入应用程序的Workspace工作区。本程序选择各种花色从A9以及用于程序运行后初始显示为背面的纸牌总计37张牌。将所需纸牌全部导入应用程序后,更改其属性,将ID设置为从137这些整数值。 图(2) 图(3)菜单资源:依次点击“插入资源”,在弹出的对话框中双击“Menu”项(如图3所示),即实现了向应用程序中加载菜单资源。(二)控件(1)静态控件:共9个,其中4个用于显示随机产生的4张扑克牌,另外5个分别用于显示提示文字“耗时标识:”、“难度级别:”、“当前得分:”、“历史记录:”以及累计游戏得分值。具体为:
5、耗时标识:提示用户计时时间。 难度级别:提示用户当前选择的难度级别。 当前得分:提示用户累计总得分信息。历史记录:提示用户有关游戏次数及正误信息。显示累计游戏得分值,初始设置为0(2)按钮:共4个,分别是:“发牌”按钮:点击此按钮,随机产生4张扑克牌并在4个静态控件上显示,同时启动计时器,进度条开始计时。游戏开始。“输入算式”按钮:当用户能够将4张牌计算出24时,点击此按钮即可在编辑框中输入计算式,同时停止游戏计时,进度条停止前进。“验算”按钮:点击此按钮,应用程序即对用户输入的计算式进行检验,如果判断用户输入的计算式恰为所发牌的点数,则对输入算式进行验算,同时将计算结果以消息框的形式告知用户
6、,并在历史记录列表框中加以显示。若计算结果正确,程序还根据难度级别在“当前得分:”中加分;若输入算式不合乎要求,则告知用户一个错误消息。最后,为防止游戏者不断点击此按钮以增加得分,当用户一次点击后即被禁止,呈灰色显示。“结束游戏”按钮:点击此按钮则游戏结束,退出应用程序。(3)组合框:共1个,此框中设置有“热身运动”和“智力比拼”两个难度级别以供游戏者选择,不同的难度级别在一次游戏得分和耗时标识进度条计时快慢上有所不同。游戏者点击不同的选项即可设定不同的难度级别。(4)列表控件:共1个,用于记录游戏者总的游戏次数以及相关的对错信息。(5)编辑框:共1个,用于接收游戏者输入的计算式。 (6)进度
7、条:共1个,游戏者单击发牌按钮后,计时器启动,耗时标识进度条同时开始计时,游戏者必须在耗时标识进度条计时终止前思考出计算式,然后单击“输入算式”按钮,此时耗时标识进度条停止计时。否则,耗时标识进度条计时终止,应用程序以消息框的形式报告真遗憾,时间到了!。添加这些控件后,再设置其属性,如ID及Caption等。各控件的相关设置信息列表如下:控件对象IDCaption显示纸牌的静态控件1IDC_STATIC1/显示纸牌的静态控件2IDC_STATIC2/显示纸牌的静态控件3IDC_STATIC3/显示纸牌的静态控件4IDC_STATIC4/耗时标识提示静态控件IDC_STATIC耗时标识:难度级别
8、提示静态控件IDC_STATIC5难度级别:当前得分提示静态控件IDC_STATIC6当前得分:显示当前得分静态控件IDC_STATIC7/历史记录提示静态控件IDC_STATIC8历史记录发牌按钮IDC_BUTTON1发牌输入算式按钮IDC_BUTTON2输入算式验算按钮IDC_BUTTON3验算结束游戏按钮IDC_BUTTON4结束游戏进度条IDC_PROGRESS1/输入算式编辑框IDC_EDIT1/显示历史记录列表控件IDC_COMBO1/难度级别选择组合框IDC_LIST1/添加控件以及设置属性等完成后,应用程序的界面如下图4所示(图4)(注:由于用于显示随机产生的4张牌及当前得分的
9、静态控件其Caption并未设置任何内容,故在界面中并未显示。)二、编写应用程序代码(一)为添加的各个控件定义成员变量在进行程序的代码编写过程之前需要为某些控件连接变量。定义成员变量可以在“建立类向导”中完成,其操作步骤为:在欲添加成员变量的控件上右击,点击弹出的快捷菜单中的“建立类向导”项,在随后弹出的对话框中选择“Member Variables”选项卡,单击欲添加变量的控件ID标识,接着点击“Add Variable”按钮,在弹出的对话框中设定“Member variable name”、“Category”及“Variable type”,然后点击OK按钮,则为该控件添加了一个成员变量
10、。其他控件成员变量的添加可以仿此完成。其演示过程如下图57所示: 图(5) 图(6)图(7)比较图5和图7,可以看到,在图7中已经为编辑框控件添加了一个成员变量m_edit,其类型为CString类。重复此过程,为所有需要添加变量的控件连接变量,结果如下表所示:控件对象变量名类型IDC_STATIC1m_bmp1CStaticIDC_STATIC2m_bmp2CStaticIDC_STATIC3m_bmp3CStaticIDC_STATIC4m_bmp4CStaticIDC_COMBO1m_cbCComboBoxIDC_EDIT1m_editCString(二)为按钮及组合框控件添加消息响应函
11、数由于按钮及组合框控件均能发送消息,故应用程序中应有对此消息的响应函数,以处理这些消息并实现相应的功能。此程序中为这些控件添加的方法如下表所示:控件对象方法IDC_BUTTON1OnButton1()IDC_BUTTON2OnButton2()IDC_BUTTON3OnButton3()IDC_BUTTON4OnButton4()IDC_LIST1OnSelchangeCombo1()(三)方法的实现A应用程序启动时会自动显示4张背面的纸牌,并且难度级别默认为“热身运动”(可以选择“热身运动”或“智力比拼”),当前得分为0,列表控件无历史记录,由此则需要在构造函数CMy24Dlg(CWnd*
12、pParent /*=NULL*/)及初始化函数OnInitDialog( )中添加如下代码:/定义一个结构体变量lvItemLV_ITEM lvItem;CMy24Dlg:CMy24Dlg(CWnd* pParent /*=NULL*/)/设置列表控件列属性 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;lvItem.state = 0; lvItem.stateMask = 0; lvItem.iImage = 0;BOOL CMy24Dlg:OnInitDialog() /初始化组合框m_cb.InsertString(0,智力比拼)
13、; /为组合框添加子项m_cb.InsertString(1,热身运动); /为组合框添加子项m_cb.SetCurSel(1); /默认为“热身运动”SetDlgItemText(IDC_STATIC7,0); /开始时得分为0/设置列表控件风格LV_COLUMN lvColumn; /定义一个结构体变量lvColumn lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;lvColumn.fmt = LVCFMT_CENTER;lvColumn.cx = 52;/设置列表控件列标题lvColumn.iSubIte
14、m = 0;lvColumn.pszText = 题数;(CListCtrl*)GetDlgItem(IDC_LIST1)-InsertColumn(0, &lvColumn);lvColumn.iSubItem = 1;lvColumn.pszText = 对错;(CListCtrl*)GetDlgItem(IDC_LIST1)-InsertColumn(1, &lvColumn); /通过强制类型转换以获得列表控件的指针,并对它进行相关操作/设置初始发牌显示为背面的纸牌m_bmp1.ModifyStyle(0,SS_BITMAP);HBITMAP hBmp1; hBmp1=LoadBitm
15、ap(AfxGetInstanceHandle(),MAKEINTRESOURCE(37);m_bmp1.SetBitmap(hBmp1);m_bmp2.ModifyStyle(0,SS_BITMAP);HBITMAP hBmp2; hBmp2=LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOURCE(37);m_bmp2.SetBitmap(hBmp2);m_bmp3.ModifyStyle(0,SS_BITMAP);HBITMAP hBmp3; hBmp3=LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOU
16、RCE(37);m_bmp3.SetBitmap(hBmp3);m_bmp4.ModifyStyle(0,SS_BITMAP);HBITMAP hBmp4; hBmp4=LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOURCE(37);m_bmp4.SetBitmap(hBmp4);/设置进度条的初始位置为0,范围为0100 CProgressCtrl *pProg=(CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);pProg-SetRange(0,100);pProg-SetPos(0);B当发牌时,进度条开始计时。
17、当输入算式时进度条停止计时。需要设置进度条的范围和当前位置。范围表示整个操作的持续时间,当前位置表示当前进行到的位置。进度条根据当前位置来判断进行的百分比并显示进度。进度条的初始化在初始化函数OnInitDialog( )中完成,添加的代码如前所示。进度条的停止计时控制在OnButton1( )消息响应中完成。按下按钮1时,系统要随机发出4张牌,进度条同时开始计时,编辑框中前一次输入的内容被清除。给按钮IDC_BUTTON1添加代码,OnButton1( )方法的实现代码如下: int suiji4;void CMy24Dlg:OnButton1() / TODO: Add your cont
18、rol notification handler code hereGetDlgItem(IDC_BUTTON3)-EnableWindow(1); /重新发牌时激活验算按钮3CString s(); /清除前一次输入的内容m_edit=s;UpdateData(FALSE);/产生136之间的四个随机数,并存放在一个整型数组中srand( (unsigned)time( NULL ) );/产生四个随机数for (int i=0;iSetPos(0);SetTimer(1000,100,NULL); /步进时间设置为0.1秒C按下按钮2时进度条停止计时,游戏者在编辑框中输入计算式。为按钮ID
19、C_BUTTON2添加代码,OnButton2( )方法的实现代码如下:void CMy24Dlg:OnButton2() / TODO: Add your control notification handler code here KillTimer(1000);D按下按钮3时,应用程序判断游戏者输入是否符合要求,若计算式所得结果正确,则加分并修改历史记录,否则,以消息框的形式告知游戏者“错误”并修改历史记录。若输入操作数不符合要求,则弹出操作数个数不符消息框;若输入的操作数不是所发牌的点数,则弹出输入数据与所发牌不一致,游戏结束!消息框。最后两者都对历史记录进行修改。为按钮IDC_BUT
20、TON3添加代码,OnButton3( )方法的实现代码如下:首先添加头文件:#include #include #include stdio.h然后添加方法的实现代码:typedef struct /表达式处理函数 int top; double array50;NumStack;typedef struct int top;char array50;OpStack;int Cint(char mychar) return (mychar-48);void PushNum(NumStack *numstack,double num) numstack-top+; numstack-array
21、numstack-top-1=num;void PopNum(NumStack *numstack,double *num) *num=numstack-arraynumstack-top-1; numstack-top-;void PushOp(OpStack *opstack,char op) opstack-top+; opstack-arrayopstack-top-1=op;void PopOp(OpStack *opstack,char *op) *op=opstack-arrayopstack-top-1; opstack-top-;double Calc(double a,do
22、uble b,char c) double result; switch(c) case +: result=a+b;break; case -: result=a-b;break; case *: result=a*b;break; case /: result=a/b;break; return result;char Priority(char y,char x) char priority=;break; case *: case /: if(y=( | y=#| y=+ | y=-)priority=;break; case (: priority=;break; case ): i
23、f(y=()priority=;break; case #: if(y=#)priority=;break; default: priority=E; return priority;void Process(NumStack *numstack,OpStack *opstack,char x)double a,b;char c;static double tempnum=0.00000000;static int len=10;static int dot=0,flags=0;if(isdigit(x) | x=.) if(x=.) dot=1; else if(dot=0) tempnum
24、=tempnum*10+Cint(x); else tempnum=tempnum+(double)Cint(x)/len; len*=10; else if(flags=0& x!=() PushNum(numstack,tempnum);tempnum=0.00000000;len=10;dot=0; switch(Priority(opstack-arrayopstack-top-1,x) case : PushOp(opstack,x);flags=0;break; case : PopOp(opstack,&c); PopNum(numstack,&b); PopNum(numsta
25、ck,&a); PushNum(numstack,Calc(a,b,c);flags=1; Process(numstack,opstack,x);break; case =: PopOp(opstack,&c);flags=1;break; int checkequ(int s,int m) /判断编辑框中输入的数字是否为所发牌的点数 int a=0,b=0; for(int k=0;k4;k+)int qiuyu=sk%9; if(qiuyu=0) sk=9; else sk%=9; for(int t=0;t4;t+)/判断编辑框输入的每个数字能否都在随机数中找到与之相同的项 if(st
26、=m0|st=m1|st=m2|st=m3) a+=1; for(int j=0;j4;j+)/判断随机数中的每个数字能否都与编辑框输入的数据相匹配 if(mj=s0|mj=s1|mj=s2|mj=s3) b+=1; if(a=4)&(b=4)/对判断结果的处理,若一致则返回1值,否则返回0值 return 1;else return 0;CString input; /定义一个字符串类int proceed(LPCTSTR L)/验算输入计算式,若结果等于24则返回真值,否则为假,并提示 NumStack numstack;OpStack opstack;int i=0; numstack.
27、top=0;opstack.top=0; PushOp(&opstack,#); for(i=0;istrlen(L);i+) Process(&numstack,&opstack,Li);if(numstack.arraynumstack.top-1=24) AfxMessageBox(正确);input=正确;return 1;elseAfxMessageBox(错误);input=错误;return 0;/为响应函数OnButton3()添加代码,判断操作数是否合乎要求,修改当前得分及历史记录void CMy24Dlg:OnButton3() / TODO: Add your contr
28、ol notification handler code hereint m=0,i=0, shuju100; CString biaoda; UpdateData(TRUE);biaoda=m_edit;biaoda=biaoda+#; for(i=0;i0)&(biaodaiEnableWindow(0);/个数不匹配,点按钮3后即被禁止 else int r=checkequ(suiji,shuju);if(r=1) int flag=proceed(biaoda); if(flag) /若计算式正确,则根据难度级别加分,修改当前得分记录 defen+=jiafen; CString s
29、tr; str.Format(%d,defen); SetDlgItemText(IDC_STATIC7,str); else AfxMessageBox(输入数据与所发牌不一致,游戏结束!); GetDlgItem(IDC_BUTTON3)-EnableWindow(0);/ 防止刷分,点按钮3后即被禁止 int count=0; char s;count+=1; /根据程序运行结果修改历史记录wsprintf(&s,%d,count);lvItem.iItem = count-1;lvItem.iSubItem = 0;lvItem.pszText = &s;(CListCtrl*)Get
30、DlgItem(IDC_LIST1)-InsertItem(&lvItem);(CListCtrl*)GetDlgItem(IDC_LIST1)-SetItemText(count-1, 1,input);UpdateData(FALSE);E按下按钮4时游戏结束,退出应用程序。为按钮IDC_BUTTON4添加代码,OnButton4( )方法的实现代码如下:void CMy24Dlg:OnButton4() / TODO: Add your control notification handler code hereOnOK();F.游戏启动后,在发牌之前,游戏者首先选择难度级别(如果不进行
31、选择的话,则默认为“热身运动”),程序根据游戏者设置的级别来进行计时和加分。因此当游戏者进行选择时,列表框会发出CBN_SELCHANGE消息,其处理函数为OnSelchangeCombo1( ),其实现方法如下:void CMy24Dlg:OnSelchangeCombo1() / TODO: Add your control notification handler code hereCString msg;m_cb.GetLBText(m_cb.GetCurSel(),msg);if(strcmp(msg,智力比拼)sudu=1;jiafen=5;if(strcmp(msg,热身运动)s
32、udu=3;jiafen=10;(四)添加菜单项及其消息响应代码(1)添加菜单项打开Workspace工作区,展开“Menu”文件夹并双击“IDM_MENU1”,在右边窗格中右击有虚线框标识的菜单,在随后弹出的对话框中设置其属性:“标题”中填入“游戏”,选中“弹出”复选框,这样就不必设置其ID。如图8所示图(8)单击“游戏”菜单项,在弹出的中右击虚框标识的菜单项,随后设置其属性:以添加“开始B”菜单项为例,设置其ID为“IDM_Begin” ,“标题”填入“开始&B”如下图9所示。完成后回车,其界面变为重复此过程,为菜单添加菜单项“开始”、“退出”、“帮助”以及“关于”。(2)将菜单资源链接到
33、主对话框展开“Dialog”文件夹,双击“IDD_MY24_DIALOG”项,在随后弹出的应用程序界面上右击标题栏,在弹出的对话框中设置“菜单:”项为“IDD_MENU1”,则将菜单链接到了主对话框中。如图10所示图(10)回车后运行程序,则可以看到已经将菜单成功加入。(3)为菜单项添加消息响应代码“开始”菜单项用于控制发牌和启动计时器,使进度条前进。为其添加消息响应函数及代码如下:void CMy24Dlg:OnBegin() / TODO: Add your command handler code hereGetDlgItem(IDC_BUTTON3)-EnableWindow(1);C
34、String s();m_edit=s;UpdateData(FALSE); srand( (unsigned)time( NULL ) );for (int i=0;iSetPos(0);SetTimer(1000,100,NULL); “退出”菜单项用于结束游戏并退出应用程序。为其添加消息响应函数及代码如下:void CMy24Dlg:OnExit() / TODO: Add your command handler code hereOnOK();“关于”菜单项用于给用户以提示信息。为其添加消息响应函数及代码如下:void CMy24Dlg:OnAbout() / TODO: Add y
35、our command handler code hereCAboutDlg dlg;dlg.DoModal();至此,整个软件设计过程完成。接下来进入调试过程,对所编写的代码进行调试。若无误,即可进入运行阶段。否则继续重复上述步骤。结论1 根据设计要求,所编写的软件实现了全部的功能,完成了设计任务。测试结果附于后。2 该设计并没有充分发挥VC+的优势,面向对象程序设计思想贯彻不够彻底。3 程序所采用的对表达式进行处理的算法不够完善(因而也称不上是一个好的算法,但是从原理上讲是没有问题的。对此,我参考了各种版本的数据结构教材(参考书籍附于后)。基于教材中对“利用堆栈求表达式的值”的介绍,编写了此算法。不过还是存在bug,偶尔也会出现判断失误现象。关于这个问题,我请教了本班同学及高中同学,结果还是不能得到完善的解决。这是本次设计最大的遗憾。4 对VC+学习不够深入,未能领会利用MFC进行可视化程序设计的要旨,因此在调试程序的过程中出现了好多现象都难以解释。例如,为列表控件(ListControl)定义一个变量后,程序不能正常运行,不得已只好改用指
链接地址:https://www.31ppt.com/p-2546963.html