程序设计创新试验doc.docx
- 文档编号:17298384
- 上传时间:2023-07-23
- 格式:DOCX
- 页数:16
- 大小:82.03KB
程序设计创新试验doc.docx
《程序设计创新试验doc.docx》由会员分享,可在线阅读,更多相关《程序设计创新试验doc.docx(16页珍藏版)》请在冰点文库上搜索。
程序设计创新试验doc
西安交通大学创新实验报告
课程名称
VC++案例开发
系别
电信学院
实验报告日期
2004年3月28日
专业班号
计算机63
姓名
刘侯刚
学号
06055066
一.项目名称
一个简单的小游戏:
贪食蛇
二.试验运行环境
采用的软件及开发平台
MicosoftVisual++6.0
三.游戏的简述
贪食蛇的玩法很简单,用键盘上的方向键控制贪食蛇的运动方向,游戏的目的是控制贪食蛇吃掉更多的食品,但是不能碰到四周的墙壁,也不能让贪食蛇的首和尾相接,否则游戏失败
四.游戏的结构程序设计流程及部分代码
找规律,建立对象模型:
首先从物理的角度来分析蛇得运动规律。
它是蠕动的,像水一样流动。
他有个特性就是身体的每一个点都经过他头部所在的点,他每一个时刻骨节所要运动的目的地是他前一个骨节所在的位置。
不难看出,其中的对象模型为
蛇,骨骼,骨节,头
抽象的接口为
蛇,骨骼,骨节,头,图元
结构图:
接口结构图
骨骼骨骼
对象结构图
给接口添加行为:
图元(GraphicObject)
绘画:
进行图元自身的绘画操作
当前矩形:
得到图元当前所在的矩形,也可考虑使用region,这样使得对图元范围得描述更加具体。
骨节(Condyle)
前一个骨节:
提供前序访问
后一个骨节:
提供后序访问
流动:
进行骨节运动诡计得计算。
骨骼(Cadre)(管理骨节链)
得到头:
得到蛇头
得到尾:
得到蛇尾
新增骨节:
在骨节链中新增骨骼
删除骨节:
在骨节链中删掉指定骨节
头(head)
方向:
能够设定和访问当前运动方向。
蛇(Snake)
增长:
蛇进行自身得增长
完善模型,引入访问者模式
存在的问题:
当前是由具体的骨骼对象来负责图元的绘画以及处理流动的,而骨骼只是管理骨节,没有提供任何访问骨节的方法,我们应该怎样访问骨节呢?
比如我们要每个骨节画出自己的形态,我们可能会这样做。
在骨骼上提供一个绘画方法,然后通过遍历骨节链,调用每个骨节的绘画方法。
这样似乎可以解决问题。
那么,我们要进行骨节流动计算呢?
我们再在骨骼上提供流动方法,然后同样的遍历骨节,调用每个的流动方法。
我们要是加入统计骨节个数功能呢?
我们要是加入其他的需要遍历骨骼的方法呢?
……
这样做的缺点是什么?
1、相似的代码有多份
2、如果骨节的访问结构发生变化,后果会怎样?
3、有新功能需要遍历骨节链该怎么办?
这样会迫使我们拷贝代码.
解决办法,引入访问者模式:
新增加接口如下:
加入行为:
访问者:
(空,无方法,属性)
被访问者:
接受访问者
骨节访问者:
继承自访问者
访问骨节
完整的结构图:
接口结构图
对象结构图
程序的部分代码:
voidCSnakeDlg:
:
OnTimer(UINTnIDEvent)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
m_snake.KeepMoving();//保持原方向移动一步
if(!
m_snake.IsTouch(MAX_X,MAX_Y))
{
//撞墙处理
KillTimer
(1);
MessageBox("刘侯刚为你打气,再来一次!
");
InitGame();
}
else
{
//不撞墙处理
//吃到食物处理
if(m_snake.IsEat(m_food))
{
//蛇变长
m_snake.Grow();
//放置新食物
m_food=SetFood();
}
//显示蛇
ShowSnake();
}
//如果达到最大长度,即过关
if(m_snake.GetBodyLen()==MAX_SNAKE_LEN)
{
KillTimer
(1);
m_time=m_time-30;//下一关,时间间隔减少30MS
//结局
if(m_time<=0)
{
MessageBox("刘侯刚对你的敬仰之情有如滔滔江水连绵不绝,黄河泛滥一发不可收拾!
---THEEND");
return;
}
//挑战下一关
MessageBox("鄙人刘侯刚建议您向下一级挑战!
");
InitGame();
}
}
voidCSnakeDlg:
:
OnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
//游戏的控制
switch(nChar)
{
case'W':
caseVK_UP:
m_snake.MoveUp();
break;
case'S':
caseVK_DOWN:
m_snake.MoveDown();
break;
case'A':
caseVK_LEFT:
m_snake.MoveLeft();
break;
case'D':
caseVK_RIGHT:
m_snake.MoveRight();
break;
caseVK_ESCAPE:
EndDialog
(1);//退出程序
break;
default:
;
}
CDialog:
:
OnKeyDown(nChar,nRepCnt,nFlags);
}
voidCSnakeDlg:
:
ShowSnake()
{
//蛇身包含着坐标,把坐标对应的方块显示出来即可
intlen=m_snake.GetBodyLen();
for(inti=0;i { m_map[m_snake.m_body[i].x][m_snake.m_body[i].y].ShowWindow(SW_SHOW); } //隐藏上一步的尾巴 m_map[m_snake.m_preEnd.x][m_snake.m_preEnd.y].ShowWindow(SW_HIDE); } voidCSnakeDlg: : BreakGame() { if(m_isRun) { KillTimer (1); m_isRun=false; } else { SetTimer(1,m_time,NULL); m_isRun=true; } } voidCSnakeDlg: : InitGame() { m_isRun=false; //全部方块隐藏 for(inti=0;i { for(intj=0;j { m_map[i][j].ShowWindow(SW_HIDE); } } //初始化蛇 m_snake.InitSnake(MAX_X,MAX_Y); //显示蛇 ShowSnake(); //放置食物 m_food=SetFood(); } CPointCSnakeDlg: : SetFood() { intx=0; inty=0; CPointfood; boolflag=true; //随机产生,合适的坐标 while(flag) { srand(time(NULL)); x=rand()%MAX_X; y=rand()%MAX_Y; food.x=x; food.y=y; for(inti=0;i { if(food! =m_snake.m_body[i])//坐标不能与蛇身重合 flag=false; } } //把该坐标对应的方块显示,作为食物 m_map[x][y].ShowWindow(SW_SHOW); returnfood; } BOOLCSnakeDlg: : PreTranslateMessage(MSG*lpmsg) { //对话框默认屏蔽了方向键的消息响应,在这里要处理一下 switch(lpmsg->message) { caseWM_KEYDOWN: switch(lpmsg->wParam) { caseVK_UP: caseVK_DOWN: caseVK_LEFT: caseVK_RIGHT: OnKeyDown(lpmsg->wParam,LOWORD(lpmsg->lParam),HIWORD(lpmsg->lParam)); break; default: ; } default: ; } returnCDialog: : PreTranslateMessage(lpmsg); } voidCSnakeDlg: : OnOK()//回车键消息响应 { BreakGame();//暂停||开始游戏 //CDialog: : OnOK(); } 五.试验结果 六.个人小结 (1)此次实验中我感受最深的是,CWnd类库的无可替代性,并在一定的努力下,对此类库有了一定的了解: 软为了WINDOWS程序设计的方面,提供了各种各样的类库,CWnd类库和其他派生的给大类库是最常见的类库了。 仔细研究这个类的使用大大减少了程序设计的复杂程度,CWnd派生出来的类主要有对话框、视类和控制类。 其中对话框就有各种各样的形式,对于文件操作和字体设定带来方便。 例如通过使用CFileDialog类来获得文件的名字: CFileDialogfileDlg; if(fileDlg.DoModal()==IDOK) { CStringstr; str=fileDlg.GetPathName()+fileDlg.GetFileName()+fileDlg.GetFileExt(); return; } 这样每次执行完成这段代码,str中保存的就是放回的文件的路径和文件名。 如果str定义的是一个全局变量,那么其他地方都可以使用文件对话框操作的结果了。 (2)在此次实验中遇到了一些问题,没能解决,只好绕道而行,现在选其二如下 第一个问题: BOOL CMyWinApp: : InitInstance() { cout << "CMyWinApp: : InitInstance \n"; m_pMainWnd = new CMyFrameWnd; // 引发CMyFrameWnd: : CMyFrameWnd 构造函数 return TRUE; } 这个地方引发CMyFrameWnd: : CMyFrameWnd构造函数那么其父类构造函数为什么没有被授衔调用呢? 而在Frame1中确实自下而上引发的啊。 第二个问题: 在Frame2中还有 BOOL CWnd: : CreateEx() { cout << "CWnd: : CreateEx \n";// 这是一個虚拟函式,CWnd 中有定义,CFrameWnd 也改写了 PreCreateWindow(); 这里到底是呼叫 CWnd: : PreCreateWindow 还是 return TRUE; // CFrameWnd: : PreCreateWindow 呢? } 这点我有迷茫了,既然是由CFrameWnd的构造函数调用引起的,在CMyFrameWnd中又没有改写PreCreateWindow 那么肯定是调用CFrameWnd中定义的函数啊! 怎么会牵扯到Object slicing呢?
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 程序设计 创新 试验 doc