当前位置:文档之家› 基于MFC的贪吃蛇游戏设计与实现

基于MFC的贪吃蛇游戏设计与实现

学 号:

课 程 设 计

2013——2014学年 第2学期

课程名称

可视化编程(VC) 学 院 计算机科学与技术学院

专 业

软件工程

级 姓 名 指导教师

岑 丽

目录

基于MFC的贪吃蛇游戏设计与实现 (1)

一.课设要求 (1)

二.简单操作及功能说明 (1)

三.模块功能说明 (2)

四.运行结果 (7)

五.设计过程中自己所遇到的问题及相应的解决方法和解决过程 (8)

六.心得体会 (10)

七.参考资料 (10)

八.附录(主要代码) (11)

基于MFC的贪吃蛇游戏设计与实现一.课设要求:

1.游戏界面设计

2.食物的初始化

3.游戏开始以及具体实现

二.简单操作及功能说明:

这是基于MFC的一个简单的贪吃蛇游戏的制作。他的具体实现在CView类中实现。上图为运行的结果。

(1)有两个简单的选项。

游戏的开始(start追寻荣耀吧);

暂停(歇一会儿呗。);

继续(继续圣战吧兔宝宝!);

离开(先撤了)。

由于这部分功能没什么用,就让他失效了。(2)能够实现简单的上下左右操作。

三.模块说明与介绍:

1.游戏开始功能

void CSnakeView::OnStart()

{

SetTimer(1,2500,NULL); AfxMessageBox("准备好游戏马上开始!"); }

2.游戏暂停功能

void CSnakeView::OnPause()

{

KillTimer(1);

AfxMessageBox("stop the game "); }

3.游戏继续功能

void CSnakeView::OnContinue() {

SetTimer(1,500,NULL);

}

4.游戏退出功能

void CSnakeView::OnExit()

{

AfxMessageBox("我会想念你的主人...");

exit(0);

}

5. 撞界判断

if(Snake[0].x*20<=37||Snake[0].y*20<=37||Snake[0].x*20>=462||Snake[ 0].y*20>=462)

{

KillTimer(1);

AfxMessageBox(soure);

// s=0;

}

6.蛇身相撞判断

if(Snake[0].len>3)

for(int sn=Snake[0].len-1;sn>0;sn--)

{

if(Snake[0].x*20==Snake[sn].x*20&&Snake[0].y*20==Snake[sn].y*20 {

KillTimer(1);

AfxMessageBox(soure);

//s=0;

}

}

7.行走方向判断

if(Snake[0].direct==1)Snake[0].y--;

if(Snake[0].direct==2)Snake[0].y++;

if(Snake[0].direct==3)Snake[0].x--;

if(Snake[0].direct==4)Snake[0].x++;

pDC->SelectStockObject(BLACK_PEN);

CBrush DrawBrush=(RGB(255,192,203));

CBrush *Drawbrush=pDC->SelectObject(&DrawBrush);

pDC->Rectangle(Snake[0].x*20,Snake[0].y*20,(Snake[0].x+1)*20,(Snak e[0].y+1)*20);

pDC->SelectObject(DrawBrush);

8.判断吃豆的条件,撞到就吃

if(Snake[0].x*20==Food.x*20&&Snake[0].y*20==Food.y*20)

{

Snake[0].len++;

Food.isfood=1;

Snake[Snake[0].len-1].x=Snake[Snake[0].len-2].x;

Snake[Snake[0].len-1].y=Snake[Snake[0].len-2].y;

}

9.如果食物被吃了就生成

if(Food.isfood==1)

{

srand((unsigned)time(NULL));

do

{

for(int isfo=Snake[0].len-1;isfo>=0;isfo--)

if(Snake[0].x*20==Snake[isfo].x*20&&Snake[0].y*20==Snake[isfo].y* 20)

{

Food.x=rand()%25;

Food.y=rand()%25;

}

}

while(Food.x*20<70||Food.y*20<70||Food.x*20>430||Food.y*20>430); pDC->Rectangle(Food.x*20,Food.y*20,(Food.x+1)*20,(Food.y+1)*20);

Food.isfood=0;

}

四.运行结果

开始游戏

食物的初始化

碰壁死显示得分

咬到自己死显示得分

五.设计过程中遇到的问题及相应的解决方法和解决过程。第一次做贪吃蛇,可以说是问题很多,在网上高人的指导和同学的帮助下,还是遇到过这些问题。

(1)蛇和食物的全局变量定义完后,由于对MFC的各个类不了解,一时不知道放在哪个代码中。后来意识到游戏的功能在cview中实现的,就把变量定义放入了csnakeview中。

(2)游戏的继续与退出功能。

void CSnakeView::OnExit()

{

AfxMessageBox("我会想念你的主人...");

exit(0);

}

void CSnakeView::OnContinue()

{

SetTimer(1,500,NULL);

}

之前定义两个功能的顺序刚好反一下,结果编译出来的结果一直错误。试着改了很多参数都没有用。后来才发现不是顺序的问题,是游戏继续功能的类向导忘记建立了。

(3)先前想把蛇身与食物的颜色区分开,但是发现运行之后,蛇身的初始颜色与之后的颜色不一样,最后还是把蛇身与食物改成了相同的颜色。

(4)修改窗口左上角图标。先前不知道如何修改图标,就在IDR_MAINFRAME中手画图标,看了网上的教程之后,就用ico修改了一个图标引入Icon中,并且在IDD_ABOUTBOX中也一并修改了图标,但是执行之后发现图标变是变了,变成可执行文件的标准图标了。后来把Icon中原有的图标删除后,重命名新的图标,把他改成原来图标的名字,就成功了。

六.心得体会

由于平时上课不够认真,自己课下看书经常找不到重点,这导致我在做课程设计时磕磕盼盼,开始做的时候,一发现编译错误,又不知道错在哪里,就把类里面的代码挨个点开,漫无边际的检查错误,看了半天没发现错误在哪里,也不认识代码讲的是什么,经过慢慢的摸索和不断的错误,不懂就问同学,上网查资料,终于完成了。

我觉得课程设计是一个很好的学习契机,他是从功能和应用出发的,从功能和应用我们可以知道我们需要掌握哪些知识,让我们直接从实践中学习,发现错误,并针对应用去学习,并改正错误,而且这样会让我们对知识有更深的印象和记忆,这也是对上课知识的补充和强化,更贴近应用领域,提高了我们动手实践的能力。

在这次课程设计中,我完成了贪吃蛇这一个小游戏,但是更多的,我知道了如何从功能和应用出发去完成MFC小游戏,也知道发现问题后,解决一类问题的方法,而不是一个问题,我觉得这是别的地方很难学来的,在这次课程设计学习后,我感觉真的收获很大。七.参考资料:

1.Visual c++ 面向对象与可视化程序设计(第2版)清华大学出版社黄维通编著

2.https://www.doczj.com/doc/451869153.html,/renyhui/article/details/21463517(MFC对话框贪吃蛇小游戏)

3.https://www.doczj.com/doc/451869153.html,/s/blog_6cbbf04b0100m49k.html(手把手教MFC贪吃蛇)

附录:程序的主要代码

// snakeView.cpp : implementation of the CSnakeView class #include "stdafx.h"

#include "snake.h"

#include "snakeDoc.h"

#include "snakeView.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

struct Snake

{

int x,y;

int len;

int direct;

}Snake[50];

struct Food

{

int x;

int y;

int isfood;

}Food;

// CSnakeView

IMPLEMENT_DYNCREATE(CSnakeView, CView) BEGIN_MESSAGE_MAP(CSnakeView, CView) //{{AFX_MSG_MAP(CSnakeView)

ON_WM_KEYDOWN()

ON_WM_TIMER()

ON_WM_RBUTTONDOWN()

ON_COMMAND(IDM_START, OnStart)

ON_COMMAND(IDM_PAUSE, OnPause)

ON_COMMAND(IDM_CONTINUE, OnContinue)

ON_COMMAND(IDM_EXIT, OnExit)

//}}AFX_MSG_MAP

// Standard printing commands

ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP()

// CSnakeView construction/destruction

CSnakeView::CSnakeView()

{

// TODO: add construction code here

}

CSnakeView::~CSnakeView()

{

}

BOOL CSnakeView::PreCreateWindow(CREATESTRUCT& cs)

{

// TODO: Modify the Window class or styles here by modifying

// the CREATESTRUCT cs

return CView::PreCreateWindow(cs);

}

// CSnakeView drawing

void CSnakeView::OnDraw(CDC* pDC)

{

CSnakeDoc* pDoc = GetDocument();

ASSERT_V ALID(pDoc);

// TODO: add draw code for native data here

CBrush backBrush(RGB(123,104,238));

CBrush* pOldBrush = pDC->SelectObject(&backBrush);

CRect rect;

pDC->GetClipBox(&rect);

pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(),PATCOPY);

pDC->SelectObject(pOldBrush);

pDC->Rectangle(19,19,501,501);

oninit();

}

// CSnakeView printing

BOOL CSnakeView::OnPreparePrinting(CPrintInfo* pInfo)

{

// default preparation

return DoPreparePrinting(pInfo);

}

void CSnakeView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {

// TODO: add extra initialization before printing

}

void CSnakeView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {

}

// CSnakeView diagnostics

#ifdef _DEBUG

void CSnakeView::AssertValid() const

{

CView::AssertValid();

}

void CSnakeView::Dump(CDumpContext& dc) const

{

CView::Dump(dc);

}

CSnakeDoc* CSnakeView::GetDocument() // non-debug version is inline {

ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSnakeDoc)));

return (CSnakeDoc*)m_pDocument;

}

#endif //_DEBUG

// CSnakeView message handlers

void CSnakeView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {

switch(nChar)

{

case VK_UP:if(Snake[0].direct!=2)Snake[0].direct=1;break;

case VK_DOWN:if(Snake[0].direct!=1)Snake[0].direct=2;break;

case VK_LEFT:if(Snake[0].direct!=4)Snake[0].direct=3;break;

case VK_RIGHT:if(Snake[0].direct!=3)Snake[0].direct=4;break; }

CView::OnKeyDown(nChar, nRepCnt, nFlags);

CView::OnKeyDown(nChar, nRepCnt, nFlags);

}

void CSnakeView::OnTimer(UINT nIDEvent)

{

// TODO: Add your message handler code here and/or call default

CDC *pDC=GetDC();

CString soure;

if(Snake[0].len==2)SetTimer(1,370,NULL);

if(Snake[0].len==3)SetTimer(1,270,NULL);

if(Snake[0].len==6)SetTimer(1,200,NULL);

if(Snake[0].len==9)SetTimer(1,100,NULL);

soure.Format("bravo!score:%d!",(Snake[0].len-3)*10);

//撞界判断

if(Snake[0].x*20<=37||Snake[0].y*20<=37||Snake[0].x*20>=462||Snake[0].y*20>=46 2)

{

KillTimer(1);

AfxMessageBox(soure);

// s=0;

}

//蛇身相撞判断

if(Snake[0].len>3)

for(int sn=Snake[0].len-1;sn>0;sn--)

{

if(Snake[0].x*20==Snake[sn].x*20&&Snake[0].y*20==Snake[sn].y*20)

{

KillTimer(1);

AfxMessageBox(soure);

// s=0;

}

}

pDC->SelectStockObject(WHITE_PEN);

pDC->Rectangle(Snake[Snake[0].len-1].x*20,Snake[Snake[0].len-1].y*20,(Snake[Sn ake[0].len-1].x+1)*20,(Snake[Snake[0].len-1].y+1)*20);

for(int i=Snake[0].len-1;i>0;i--)

{

Snake[i].x=Snake[i-1].x;

Snake[i].y=Snake[i-1].y;

}

//行走方向判断

if(Snake[0].direct==1)Snake[0].y--;

if(Snake[0].direct==2)Snake[0].y++;

if(Snake[0].direct==3)Snake[0].x--;

if(Snake[0].direct==4)Snake[0].x++;

pDC->SelectStockObject(BLACK_PEN);

CBrush DrawBrush=(RGB(255,192,203));

CBrush *Drawbrush=pDC->SelectObject(&DrawBrush);

pDC->Rectangle(Snake[0].x*20,Snake[0].y*20,(Snake[0].x+1)*20,(Snake[0].y+1)*2 0);

pDC->SelectObject(DrawBrush);

//判断吃豆的条件,撞到就吃

if(Snake[0].x*20==Food.x*20&&Snake[0].y*20==Food.y*20)

{

Snake[0].len++;

Food.isfood=1;

Snake[Snake[0].len-1].x=Snake[Snake[0].len-2].x;

Snake[Snake[0].len-1].y=Snake[Snake[0].len-2].y;

}

//如果食物被吃了就生成

if(Food.isfood==1)

{

srand((unsigned)time(NULL));

do

{

for(int isfo=Snake[0].len-1;isfo>=0;isfo--)

if(Snake[0].x*20==Snake[isfo].x*20&&Snake[0].y*20==Snake[isfo].y*20)

{

Food.x=rand()%25;

Food.y=rand()%25;

}

}

while(Food.x*20<70||Food.y*20<70||Food.x*20>430||Food.y*20>430);

pDC->Rectangle(Food.x*20,Food.y*20,(Food.x+1)*20,(Food.y+1)*20);

Food.isfood=0;

}

CView::OnTimer(nIDEvent);

}

void CSnakeView::OnRButtonDown(UINT nFlags, CPoint point)

{

CString str;

str.Format("%d,%d",point.x,point.y);

AfxMessageBox(str);

CView::OnRButtonDown(nFlags, point);

CView::OnRButtonDown(nFlags, point);

CView::OnRButtonDown(nFlags, point);

}

void CSnakeView::oninit()

{

CDC *pDC=GetDC();

CBrush DrawBrush=(RGB(255,192,203));

CBrush *Drawbrush=pDC->SelectObject(&DrawBrush);

for(int i=0;i<=Snake[0].len-1;i++)

pDC->Rectangle(Snake[i].x*20,Snake[i].y*20,(Snake[i].x+1)*20,(Snake[i].y+1)*20); pDC->SelectObject(DrawBrush);

}

void CSnakeView::OnInitialUpdate()

{

CView::OnInitialUpdate();

Snake[0].x=10;

Snake[0].y=10;

Snake[1].x=11;

Snake[1].y=10;

Snake[2].x=12;

Snake[2].y=10;

Snake[0].direct=3;

Snake[0].len=3;

Food.isfood=1;

}

void CSnakeView::OnStart()

{

SetTimer(1,2500,NULL);

AfxMessageBox("准备好游戏马上开始!");

}

void CSnakeView::OnPause()

{

KillTimer(1);

AfxMessageBox("stop the game ");

}

void CSnakeView::OnExit()

{

AfxMessageBox("我会想念你的主人..."); exit(0);

}

void CSnakeView::OnContinue()

{

SetTimer(1,500,NULL);

}

本科课程论文评分标准

班级学号姓名

论文题目基于MFC的贪吃蛇游戏设计与实现

评阅点评分标准(细则)分值给分

功能及算

法(40分)正确实现本程序所需全部功能,算法设

计正确合理且有一定创意

40分实现所需功能,算法正确30分基本实现所需功能15分有明显重大错误5分无法实现程序功能0分

界面和操

作性(20分)界面美观、合理,可操作性强20分界面合理,可操作15分界面尚可,基本可操作10分可操作较差5分

程序可读、可维护性(15分)程序可读性好、逻辑清晰,程序完整,

可维护性好,

15分程序可读、可维护10分基本可读可维护5分逻辑混乱、不可读0分

论文质量(25分)论文规范,行文流畅,层次清晰25分

论文书写基本规范,文理较通畅20分

结构较合理,层次较清楚,基本符合要

15分

结构混乱,文不对题目,或者有明显抄

袭现象

5分

总分

教师签名:

相关主题
文本预览
相关文档 最新文档