24点游戏开发课程设计.docx
- 文档编号:15520438
- 上传时间:2023-07-05
- 格式:DOCX
- 页数:26
- 大小:120.49KB
24点游戏开发课程设计.docx
《24点游戏开发课程设计.docx》由会员分享,可在线阅读,更多相关《24点游戏开发课程设计.docx(26页珍藏版)》请在冰点文库上搜索。
24点游戏开发课程设计
24点游戏
1.基本功能描述
(1)游戏开始之前可以进行难度选择(默认为简单),难度选定后点击“发牌”按钮,程序上方会随机显示4张扑克牌,进度条开始工作,用以标识耗时,同时“发牌”按钮名称变为“重新开始”。
(2)在规定时间范围内,用户可以思考并输入算式。
输入完成后,点击“验算”按钮,系统将对输入结果进行检验。
若结果正确,显示“你真行!
”,同时计分栏将根据难度给予不同的分值奖励;若结果不是24,则显示“输入错误!
”,计分栏分数不变。
(3)若在规定时间内没有完成输入或没有点击“验算”按钮,则会弹出“时间到!
”对话框。
(4)菜单可同样实现“发牌”和“结束”功能,同时还有“帮助”菜单,下面的“关于”项写入程序信息。
(5)完成一次游戏后,若用户想继续游戏,点击“重新开始”即可;若不想继续,点击“退出”按钮即可关闭程序。
2.设计思路
本程序采用基本对话框,初始化过程中载入位图,位图资源从系统的纸牌游戏资源Card.dll中获得。
点击“发牌”调用OnStart函数,完成随机发牌和计时功能,时间长短根据难度的不同,由变量m_length控制。
用户完成输入后,点击“验算”调用OnCalc函数(OnCalc函数调用qiuzhi函数对输入的多项式进行计算),完成对输入的正误判断并给出相应提示,计分栏显示分值,每次得分分值大小由m_PScore变量根据难度设置。
若想重新开始,点击“重新开始”,重新执行OnStart函数;若想结束,点击“结束”,调用OnOK函数,即可退出游戏。
程序流程图如下:
初始化:
难度默认为初级;LoadBitMap()加载位图资源;初始化进度条
发牌:
随机函数Rand产生0~12的随机数,利用SetBitMap()显示纸牌图案;GetCheckRadioButton获取难度,用m_length控制进度条变化范围,m_Pscore控制分值;SetTimer设置计时器
Y
显示“时间到!
”
N
验算:
调用OnCalc计算用户输入
N
显示“输入错误!
”
Y
显示“你真行!
”,同时m_Score增加并显示分数
Y
Y
N
结束:
OnOK
图124点游戏程序流程图
3.软件设计
3.1设计步骤
1)进入VC++程序后,创建MFCAppWizard(exe)工程,以自己姓名的拼音作为工程名,在应用程序类型中选择基本对话框,完成对话框的创建。
2)在对话框中根据设计要求添加控件,包括按钮,单选按钮,编辑框,进度条,组合框,静态文本和位图。
修改其属性,并建立类向导,在相应的地方添加代码。
3)添加菜单,关联到主窗口。
4)对程序进行调试,修改其中的错误,直到实现所要求的各项功能。
3.2界面设计
表1界面控件表
控件序号
控件名称
控件类型
属性
对应变量
1
发牌
按钮
IDC_START
2
验算
按钮
IDC_CALC
3
退出
按钮
IDC_OK
4
简单
单选按钮
IDC_Easy
5
中等
单选按钮
IDC_Middle
6
困难
单选按钮
IDC_Hard
7
算式输入框
编辑框
IDC_EDIT1
m_Input
8
得分栏
编辑框
IDC_EDIT2
m_Score
9
耗时标识
进度条
IDC_PROGRESS
10
难度
组框
IDC_STATIC
11
输入算式(以=结束)
静态文本
IDC_STATIC
12
时间进度
静态文本
IDC_STATIC
13
得分
静态文本
IDC_STATIC
14
纸牌1
位图
IDC_Picture1
15
纸牌2
位图
IDC_Picture2
16
纸牌3
位图
IDC_Picture3
17
纸牌4
位图
IDC_Picture4
18
游戏
菜单
19
帮助
菜单
20
发牌
菜单
ID_START
21
验算
菜单
ID_CALC
22
结束
菜单
ID_OK
23
关于
菜单
ID_ABOUT
3.3关键功能的实现
1)纸牌显示:
在BOOLCHukunDlg:
:
OnInitDialog()中,使用LoadBitmap()加载纸牌位图,然后在voidCHukunDlg:
:
OnStart()中,通过SetBitmap()显示纸牌。
2)随机发牌:
在voidCHukunDlg:
:
OnStart()中,通过随机函数Number[i]=rand()%13得到随机数,控制纸牌的显示。
同时为了使每次运行程序时发牌都不一样,需要调用系统时间做种子,语句srand((unsigned)time(&t))来实现。
3)计时:
使用SetTimer()函数设置计时器,使用SetRange(),SetStep()和SetPos()函数设置进度条,将控制进度条的函数置于OnTimer()函数中。
每次计时器向窗口发送消息WM_TIMER时会触发函数OnTimer(),从而使进度条前进。
4)难度变化:
三种难度有各自不同的ID值,通过获取ID值使系统明白所选难度。
通过变量m_length改变进度条的变化范围,即通过改变函数SetRange()来控制不同难度下游戏时间的长短。
通过变量m_PScore控制不同难度下每答对一题给予的分值奖励。
5)验算结果:
利用堆栈思想编写多项式算法,通过voidCHukunDlg:
:
OnCalc()调用算法函数qiuzhi()。
系统通过GetWindowText()获取用户的输入后,调用voidCHukunDlg:
:
OnCalc()对用户输入进行检验,并根据结果给出相应提示和加分。
6)结束:
调用函数voidCHukunDlg:
:
OnOk()。
4.结论与心得体会
通过对各项功能的测试,发现本程序均能达到要求。
因此,本程序从设计思路到代码编写到最后的结果都是符合设计规范的,是正确无误的。
这次课程设计,给了我很多启发。
在一开始拿到选题表时,仅仅是因为感觉24点游戏有意思才选择了它。
当进行程序流程图的绘制时,也感觉比较容易,因为仅仅只写个函数名,主要是对MFC运行过程的熟悉。
而真正开始编程时才发现,自己平时学的都是纸上谈兵。
虽然课本已经看了个遍,MFC编程部分更是看了几遍,可真正动手起来,还是无从下手。
且不说编得如何,单单对控件的设计就是丢三落四的,不是忘了添加变量,就是菜单没有进行关联。
总之,平时不注意的一些小细节,反而造成了大错误,而且还不容易发现。
在编写代码过程中,更是困难重重,漏洞百出。
最开始编写结束后我印象极为深刻,当时一共有30多个错误,当然,不少是重复的。
尽管如此,也让我一阵眩晕,一个完美的程序果然是要经过无数次修改才行的。
编程遇到的最大的问题就是多项式算法的编写,尽管通过数据结构的学习已经知道需要用到栈来实现,同时对其原理也理解了,但是实际应用中还是存在不少问题,而且开始时在网上还找不到资料(实际是查阅方法不对),代码的编写总是不能很好的应用起来。
后来通过询问老师和查阅资料,反复试验后终于成功了,当时用欣喜若狂形容也不为过,那种感觉大概就是无数编程员能坦然面对枯燥繁杂的代码,孜孜不倦的追求更人性化、多功能化程序的动力吧。
在课程设计即将结束时,我总结得到的启发:
1.对于编程这类实践性的课程,绝对不要停留在书本上,看十本书不如动手一次;2.查阅资料是一门学问,具有一定的技巧,学会正确快速查询是我们必备的能力;3.准备要充分,方向要明确,定下来后就不要因旁人影响东添西改,否则容易出错且混乱不堪;4.不要妄想一步登天,任何一件事情都需要从基本到高级一步步来;5.不要怕出错,对于初学者来说,改错是一种极好的学习过程,快速又有效。
通过这次课程设计,对于C++认识终于从理论提升到了实践,尽管我们编写的都是极其简单的程序,但起码掌握了一个程序的设计制作过程,MFC应用程序的启动流程,和简单代码的编写。
总而言之,对于C++的编程,可以说是初窥门径了。
5.参考文献
[1]刘卫宏、陈培.Visualc++编程基础.上海理工大学出版社.2003
[2]侯伯亨.24点游戏的各种开发工具.西安电子科技大学出版社.2001
[3]揣锦华.面向对象程序设计与VC++实践.西安电子科技大学出版社.2005
6.思考题
(1)改变难度可以变化游戏的限时和游戏加分的规则,如何实现?
答:
游戏的限时是通过改变进度条的SetRange()函数来实现的。
定义变量m_length,将函数设置为m_Progress->Setrange(0,m_lenght),用变量来设置进度条的变化范围,选择不同难度的时候m_length的值也会不同,难度越大它的值越小,时间也就越短,反之时间越长。
同理,加分也定义变量m_PScore,不同的难度m_PScore值不同。
即每答对一题,给予的加分各不相同,难度越大分值越高,反之越小。
(2)如何使用随机函数控制扑克牌的显示?
答:
先利用语句srand((unsigned)time(&t))以系统时间做种子,使每次打开程序时扑克牌显示不会重复。
再通过Number[i]=rand()%13,可以获得0~12这13个数字,在初始化函数OnInitDialog()中,加载位图时已经通过语句Bitmap[0].LoadBitmap(IDB_BITMAP27)(其余类似)将这13个数字分别与13张扑克牌位图对应。
故在OnStart函数中,通过语句((CStatic*)GetDlgItem(IDC_Picture1))->SetBitmap(Bitmap[Number[0]])(其余类似)显示对应的扑克牌图案。
(3)如何保证程序是根据给出的牌来书写算式的?
答:
定义数组与扑克牌点数关联,每一项一一对应。
当用户点击“验算”后,系统将把输入的四个运算数与数组元素(即显示的四张牌)相比较,一样则进行下面的各项操作,否则提示错误。
7.附录
7.1调试报告
1)运行程序出错,错误显示:
d:
\我的文档\桌面\课程设计胡坤\hukun\hukunDlg.cpp(412):
errorC2065:
'm_PScore':
undeclaredidentifier
d:
\我的文档\桌面\课程设计胡坤\hukun\hukunDlg.cpp(447):
errorC2065:
'm_length':
undeclaredidentifier
这两个错误都是没有给定义的变量添加声明造成的。
只需要在hukunDlg.h中的classCHukunDlg:
publicCdialog中将变量声明添加入public里即可。
2)一次输入结束后重新开始发现进度条没有清零,仍然接着上次的进度继续走。
其原因为在OnStart()函数中没有设定进度条的初始状态,应该添加m_Progress->SetPos(0)。
3)添加菜单后,将各个菜单项与对应按钮地ID值改为相同,同时给菜单连接了类,但运行时仍未显示菜单栏。
开始一直以为是ID的问题,结果是菜单没有与主窗口连接。
这都是菜单添加不熟悉造成得。
7.2测试结果
1)程序正确运行后,界面显示与要求相符合,难度默认为简单,得分栏为零。
图2进入程序初始界面
2)选定难度后,点击“发牌”,进度条走动,“发牌”按钮名称变为“重新开始”。
在正确输入后点击“验算”后弹出“你真行!
”对话框,同时得分栏分数增加。
图3点击“发牌”后界面
图4输入正确时界面
3)输入结果不为24时弹出“输入错误!
”对话框。
图5输入错误界面
4)在规定时间内没完成输入,弹出“时间到!
”对话框。
图6时间到界面
7.3关键源代码
1)在hukunDlg.h中的classCHukunDlg:
publicCDialog类中添加公有成员:
intNumber[4];
CStatic*m_Static[4];
CBitmapBitmap[13];
intm_length;
intm_PScore;
2)在hukunDlg.cpp中开头部分添加定义:
#include"string.h"
#include"math.h"
#include"stdlib.h"
#include"stdio.h"
#definestack_init_size100
#definestackincrement10
#definemaxlen100
#defineok1
#defineerror0
typedefintstatus;
#defineoverflow-2
3)以下为关键代码:
BOOLCHukunDlg:
:
OnInitDialog()
{
CDialog:
:
OnInitDialog();
//Add"About..."menuitemtosystemmenu.
Bitmap[0].LoadBitmap(IDB_BITMAP27);//载入已经创建好的纸牌位图对象
Bitmap[1].LoadBitmap(IDB_BITMAP28);
Bitmap[2].LoadBitmap(IDB_BITMAP29);
Bitmap[3].LoadBitmap(IDB_BITMAP30);
Bitmap[4].LoadBitmap(IDB_BITMAP31);
Bitmap[5].LoadBitmap(IDB_BITMAP32);
Bitmap[6].LoadBitmap(IDB_BITMAP33);
Bitmap[7].LoadBitmap(IDB_BITMAP34);
Bitmap[8].LoadBitmap(IDB_BITMAP35);
Bitmap[9].LoadBitmap(IDB_BITMAP36);
Bitmap[10].LoadBitmap(IDB_BITMAP37);
Bitmap[11].LoadBitmap(IDB_BITMAP38);
Bitmap[12].LoadBitmap(IDB_BITMAP39);
CProgressCtrl*m_Progress=(CProgressCtrl*)GetDlgItem(IDC_PROGRESS);//设置指向进度条的指针
m_Progress->SetStep
(1);//设置进度条每次向前1个单位
m_Progress->SetPos(0);//设置进度条初始状态处于0位
GetDlgItem(IDC_CALC)->EnableWindow(FALSE);//使“验算”按钮不可用
CheckRadioButton(IDC_Easy,IDC_Hard,IDC_Easy);//使难度默认为“简单”
}
//多项式算法
typedefstruct
{
char*base,*top;
intstacksize;
}sqstack1;//定义运算符栈
typedefstruct
{
float*base,*top;
intstacksize;
}sqstack2;//定义运算数栈
intisp(chara)//栈内优先数
{
inte;
if(a=='*'||a=='/')e=2;
if(a=='+'||a=='-')e=1;
if(a=='(')e=0;
if(a=='=')e=-1;
returne;
}
inticp(chara)//栈外优先数
{
inte;
if(a=='*'||a=='/')e=2;
if(a=='+'||a=='-')e=1;
if(a=='(')e=3;
returne;
}
statusinitstack1(sqstack1&s)//运算符栈的初始化
{
s.base=(char*)malloc(stack_init_size*sizeof(char));
if(!
s.base)exit(overflow);
s.top=s.base;
s.stacksize=stack_init_size;returnok;
}
statusgettop1(sqstack1s,char&e)//取栈顶元素
{
if(s.top==s.base)returnerror;
e=*(s.top-1);returnok;
}
statuspush1(sqstack1&s,chare)//进栈
{
if(s.top-s.base>=s.stacksize)
{
s.base=(char*)realloc(s.base,(s.stacksize+stackincrement)*sizeof(char));
if(!
s.base)exit(overflow);
s.top=s.base+s.stacksize;
s.stacksize+=stackincrement;
}
*s.top++=e;returnok;
}
statuspop1(sqstack1&s,char&e)
{
if(s.top==s.base)returnerror;
e=*--s.top;returnok;
}
statusinitstack2(sqstack2&s)//运算数栈的初始化
{
s.base=(float*)malloc(stack_init_size*sizeof(float));
if(!
s.base)exit(overflow);
s.top=s.base;
s.stacksize=stack_init_size;returnok;
}
statusgettop2(sqstack2s,float&e)//取栈顶元素
{
if(s.top==s.base)returnerror;
e=*(s.top-1);returnok;
}
floatpush2(sqstack2&s,floate)//进栈
{
if(s.top-s.base>=s.stacksize)
{
s.base=(float*)realloc(s.base,(s.stacksize+stackincrement)*sizeof(float));
if(!
s.base)exit(overflow);
s.top=s.base+s.stacksize;
s.stacksize+=stackincrement;
}
*s.top++=e;returnok;
}
floatpop2(sqstack2&s,float&e)//出栈
{
if(s.top==s.base)returnerror;
e=*--s.top;returnok;
}
statuspostfix(charla[],charlb[])
{
inti,j,k;
charc,ea,eb,ec;
sqstack1optr;
initstack1(optr);ec='=';
push1(optr,ec);//optr栈的初始化,栈底为=
i=0;j=0;
c=la[0];
while(c!
='='&&i { if((c>='0'&&c<='9')||c=='.'){lb[i++]=c;k=0;} else { if(c==')')//遇")"则一直退到"(" { lb[i++]='';gettop1(optr,ea); while(ea! ='(') { pop1(optr,eb);lb[i++]=eb;lb[i++]='';k=1; gettop1(optr,ea); } pop1(optr,eb); } else { if(i>1&&k==0)lb[i++]=''; gettop1(optr,ea); while(isp(ea)>=icp(c))//比较优先级 { pop1(optr,eb);gettop1(optr,ea); lb[i++]=eb;lb[i++]='';k=1; } push1(optr,c);lb[i++]=''; } } c=la[++j]; } gettop1(optr,ea); while(ea! ='=')//退栈到栈底 { lb[i++]='';pop1(optr,eb);lb[i++]=eb;gettop1(optr,ea); } if(i==maxlen)return(overflow); elselb[i++]='';lb[i]='='; returnok; } floatqiuzhi(charlb[]) { inti,j,k,n,flag; floatm,e,ta,tb,d,t;float*p; charc; sqstack2opnd; initstack2(opnd);//opnd栈的初始化 i=j=n=0;flag=0; c=lb[0]; while(c! ='=') { if(c=='') { if(j>=2)//把字符转化为实数 {m=0;k=j; while(j>0) { pop2(opnd,e);//弹出栈顶元素 m+=e*(float)pow(10,k-j);j--; } m=m/(float)pow(10,n); push2(opnd,m); } elsej=0; n=0;flag=0;//flag指示小数点的起始,n指示小数点后的位数 } else {if((c>='0'&&c<='9')||c=='.') {if(c=='.')flag=1; else {if(flag==1)n++; d=(float)(c-'0');push2(opnd,d);j++; } } else//遇运算符则取数进行运算 { pop2(opnd,ta);pop2(opnd,tb);//弹出栈顶两个元素进行运算 if(c=='*')t=ta*tb; if(c=='/'){if(ta==0)returnerror;elset=tb/ta;}//除数为0返回0 if(c=='+')t=ta+tb; if(c=='-')t=tb-ta; push2(opnd,t); } }p=opnd.base; c=lb[++i]; } gettop2(opnd,e); returne;//返回计算结果 } voidCHukunDlg: : OnCa
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 24 游戏 开发 课程设计