程序设计创新试验doc.docx

上传人:b****8 文档编号:29484292 上传时间:2023-07-23 格式:DOCX 页数:16 大小:82.03KB
下载 相关 举报
程序设计创新试验doc.docx_第1页
第1页 / 共16页
程序设计创新试验doc.docx_第2页
第2页 / 共16页
程序设计创新试验doc.docx_第3页
第3页 / 共16页
程序设计创新试验doc.docx_第4页
第4页 / 共16页
程序设计创新试验doc.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

程序设计创新试验doc.docx

《程序设计创新试验doc.docx》由会员分享,可在线阅读,更多相关《程序设计创新试验doc.docx(16页珍藏版)》请在冰豆网上搜索。

程序设计创新试验doc.docx

程序设计创新试验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呢?

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 笔试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1