贪吃蛇游戏_实习报告

课程设计报告

贪吃蛇游戏设计

                 贪吃蛇                

  ()            信息工程系               

                信息类                  

               20101               

学生姓名               王洪松                 

                 100810518              

 03    28  日至  04    01      1   

指导教师(签字)             

(签字)             

                     

              


贪吃蛇游戏设计

摘要:贪吃蛇是一款经典的休闲游戏,操作小蛇不停的朝食物的方向前进,直到吃掉了食物。每吃一个食物,小蛇都会长长一节,随之而来的难度加大;当小蛇的头撞到墙时或者小蛇的头与身体相撞时,小蛇就会死亡;当然,小蛇的速度越快,每一个食物的分数就越高。

                                                                                                                    

进程安排

328日:规划程序需要调用的各个函数,根据要求要实现的内容

329日:图形驱动函数

330日:开始画面函数

331日:控制玩游戏过程的函数

41日:图形结束函数组装程序,及其调试

开发环境概述

   Visual C++是微软公司的重要产品之一, 是一种功能强大行之有效的可视化编程工具。它提供了MFC类库,使用户可以方便的开发自己想实现的功能。Visual C++6.0的主要特点:

(1)自动化和宏功能。

(2)可以灵活地定制工具栏和菜单。

(3)可以直接运行和调试程序,还可以使用宏语言来自动操作调试器。

(4)支持Internet连接。

(5)一个新的便捷的项目系统可以允许一个工作区内包含多个不同的项目类型。

(6)在工作区内可以包含多个并列的工程文件。

(7)可以在对话框中使用WizardBar将程序同可视化元素联系起来。

(8)Find in File命令支持两个独立的输出窗格,可以保存上一次搜索的结果。

这些新特性可以更好地利用Visual C++开发工具进行Windows应用程序开发。

 


目    录

1、        概述

1.1、用C类环境设计程序的方法…………………………………………1

1.2、简要说明.,…………………………………………………………….1

2、设计要求……………………………………………………………….1

3、系统分析与模块设计…………………………………………………2

3.1、算法设计

3.2、数据结构

3.3、模块设计

3.4、模块枝干图

4、程序流程图

4.1、图形驱动……………………………………………………………..3

4.2、开始画面……………………………………………………………..4

4.3、显示食物……………………………………………………………..5

4.4、蛇向前移动…………………………………………………………..6

4.5、判蛇死………………………………………………………………..7

4.6、吃到食物后处理……………………………………………………..8

4.7、判蛇反向移动………………………………………………………..9

4.8、游戏结束……………………………………………………………..10

4.9、图形结束……………………………………………………………..10

5、程序设计及源代码……………………………………………………10-17

6、运行结果分析…………………………………………………………18-20

7、实习心得………………………………………………………………21


贪吃蛇游戏的设计

1 .概    述       

1.1、用TC设计程序的方法

首先应了解设计要求,然后按照功能设计模块,每个模块完成特定的功能,要使模块间的耦合性小,内聚性高;设计模块是相当重要的一个环节。模块的数量不宜太多,也不宜太少,要使每个模块都能比较简单的转换成流程图。模块设计完成后,就该给每个模块绘制流程图了。流程图要简单,容易理解,多用中文。不宜写过长的代码,增加理解难度。流程图与模块枝干图均可用绘图软件绘制,可适当加些背景色,用以区分。此外,流程图应容易转换成代码。绘制好了流程图,就要编写代码了。直接在TC环境里输入代码,然后运行测试,检查错误,最终,将设计出可行的程序。

1.2、简要说明 

      开始时以界面形式选择快速,中速,慢速,点击回车进入游戏。

以快速为代表,为其设定一个变量,其延时为30000,设定的延时为蛇每前进一步到下一步的相隔时间,并且设定的分数为3分,这样,蛇就能以30000单位的延时和3分的游戏规则进行游戏。慢速和中速一次类推。

在蛇不停的情况下,蛇的每后一节会到达蛇的前一节,依次类推,就是蛇不停的移动。

在靠近界面有围栏,画出围栏,并记录其坐标,蛇头一旦到达这个坐标,即判断蛇死;并且从蛇的第4节开始判断蛇头的位置是否与其相等,如果是的话,也判断蛇死,退出游戏。

通过对蛇头的X.Y坐标的加减蛇的宽度,可以用上下左右键来进行游戏,并且判断是否反方向移动。

食物的坐标用随机数产生,但通过取余再加的方法使之处于围栏的范围之内,并且在坐标的整十的倍数上,保证蛇头能与之相等。

当蛇头的坐标等于食物的坐标时,即蛇吃到了食物,此时,增加的一节暂时没有显现出来,当下一步时在末尾加上一节即可。

当蛇死之后,在屏幕上显示“GAME OVER”,表示游戏结束,显示分数后,退出。

2.设计要求

       外观为矩形,食物随机产生,添加注释,统计得分、每吃到一个食物获得相应分数。蛇碰到自己或墙壁,游戏均结束。游戏结束时输出得分。画出模块枝干图与每个模块的程序流程图。修改某些代码,改变其外观及功能。

游戏操作应尽量简单。

界面美观,让人看了觉得舒服。

3、系统分析与模块设计

3.1、算法设计

        玩游戏过程采用递归算法,由while(1)控制循环过程,可使游戏重复玩,在蛇死之前不停的玩。判断蛇死的算法是通过判断蛇有没有碰到自己及墙壁。使蛇向前移动采用递归算法,通过递归将蛇的每一节依次向前移动,横坐标与纵坐标依次向前赋值,从而达到使蛇前移的目的。蛇的前进方向通过if结构判断。

3.2、数据结构

     蛇与食物信息分别用两个结构体存储与表示。将食物的横坐标x、纵坐标y和判断是否要出现食物的变量yes分别作为食物的结构体的成员。蛇的横坐标数组x[n],纵坐标数组y[n],蛇的节数node,蛇的移动方向direction、蛇的生命life分别作为蛇的结构体的成员。结构体内每个成员的存储类型均为整型。

3.3、模块设计

模块应具有高内聚性,低耦合性。这样,程序运行才更稳定,效率更高。

据功能将贪吃蛇游戏划分成四个大模块,九个小模块。每个模块均具有自己的功能,而且,比较容易画出各个模块的流程图。

3.4、模块枝干图

    

简要说明:图形驱动即完成初始化图形系统功能;开始画面模块的主要作用是根据设置绘制出玩游戏区域四周的墙壁;玩游戏的过程是游戏此游戏程序的核心,又可细分为好多小的功能模块;其中,显示食物模块仅完成显示食物功能;蛇前移模块即通过递归算法实现蛇的向某方向移动;判蛇死模块的功能是通过判断蛇是否碰到自己或墙壁来判断蛇有没有死亡。吃到食物后小模块只有蛇吃到食物后才起作用。即当蛇吃到食物后,蛇自身延长一节并绘出蛇,同时加10分。通过键盘操控来玩游戏主要由判反向移动模块完成,即当蛇不是反向移动时,按照键盘上方向键指示移动。游戏结束模块功能简单,仅完成输出得分与提示语功能。最后图形结束模块完成关闭图形功能。

4、程序流程图

4.1、图形驱动

                      

4.2、开始画面

                              

        

4.3、  显示食物

                                

4.4、  蛇向前移动

          

       

                                                                                                                                                                                                                                                                                                                                                                                       

4.5、  判蛇死

                        

4.6、  吃到食物后处理

                        

4.7、  判蛇反向移动

          

                             

4.8、  游戏结束

                                  

 

4.9、  图形结束

                                                   

5、程序设计及关键源代码

 /*函数定义是对各个基础函数的定义,并且设置需要运用的信息,便于调用

*/

#define N 200//宏定义

#include <graphics.h>//TC中特有的与图形有关的函数

#include <stdlib.h>//标准库函数

#include <dos.h>//包含很多BIOS调用函数

#define LEFT 0x4b00//键盘扫描码

#define RIGHT 0x4d00//键盘扫描码

#define DOWN 0x5000//键盘扫描码

#define UP 0x4800//键盘扫描码

#define ESC 0x011b//键盘扫描码

int i,key;

int score=0;/*得分*/

int gamespeed=0;/*游戏速度自己调整*/

int choice=0;

struct Food

{

   int x;/*食物的横坐标*/

   int y;/*食物的纵坐标*/

   int yes;/*判断是否要出现食物的变量*/

}food;/*食物的结构体*/

struct Snake

{

   int x[N];

   int y[N];

   int node;/*蛇的节数*/

   int direction;/*蛇移动方向*/

   int life;/* 蛇的生命,0活着,1死亡*/

}snake; /*蛇的结构体*/

void Init(void);/*图形驱动*/

void Close(void);/*图形结束*/

void DrawK();/*开始画面*/

void GameOver(void);/*结束游戏*/

void GamePlay(void);/*玩游戏具体过程*/

void PrScore(void);/*输出成绩*/

void speed(void);

void get(void);

/*主函数是程序的主流程,首先定义使用到的常数、全局变量及函数原型说明,然后初始化图形系统,调用函数DrawK()画出开始画面,调用函数GamePlay(),即玩游戏的具体过程,游戏结束后调用Close()关闭图形系统,结束程序

*/

void main(void)

{

   speed();

   Init();/*图形驱动*/

   DrawK();/*开始画面*/

   GamePlay();/*玩游戏具体过程*/

   Close();/*图形结束*/

}

void speed(void)

{

   printf("******************Welcome into the greesnake game******************\n");

   printf("Choice 1 is slow\nChoice 2 is middle\nChoice 3 is quick\nYour choice:");

   scanf("%d",&choice);

   if(choice==1)

   gamespeed=50000;

   if(choice==2)

   gamespeed=40000;

   if(choice==3)

   gamespeed=30000;

}

/*图形驱动*/

void Init(void)

{

   int gd=DETECT,gm; /*宏定义,当GD为0时,自动检测显卡,不需要自己赋值*/

   initgraph(&gd,&gm,"c:\\tc"); /*GD为图形驱动器,GM为图形模式*/

   cleardevice(); /*清屏*/

}

/*主界面是一个封闭的围墙,用两个循环语句分别在水平和垂直方向输出连续的宽度和高度均的矩形方块,表示围墙,为了醒目,设置为绿色。

*/

/*开始画面,左上角坐标为(50,40),右下角坐标为(610,460)的围墙*/

void DrawK(void)

{

/*setbkcolor(LIGHTGREEN);*/

   setcolor(11);

   setlinestyle(SOLID_LINE,0,THICK_WIDTH);/*设置线型*/

   for(i=40;i<=450;i+=10)

  {

     rectangle(50,i,59,i+10); /*左边*/

     rectangle(601,i,610,i+10);/*右边*/

  }

   for(i=50;i<=600;i+=10)/*画围墙*/

   {

      rectangle(i,40,i+10,49); /*上边*/

      rectangle(i,451,i+10,460);/*下边*/

   }

}

/*计分器*/

void get(void)

{

   if(choice==1)

   score=1+score;

   if(choice==2)

   score=2+score;

   if(choice==3)

   score=3+score;

}

/*玩游戏具体过程,这是游戏的主要组成部分,他采用将前一节的坐标赋给后一节,用背景颜色将最后节去除,当蛇头的坐标与食物的坐标相等时,表示食物被吃掉了。

*/

void GamePlay(void)

{

   randomize();/*随机数发生器*/

   food.yes=1;/*1表示需要出现新食物,0表示已经存在食物*/

   snake.life=0;/*活着*/

   snake.direction=1;/*方向往右*/

   snake.x[0]=100;snake.y[0]=100;/*蛇头*/

   snake.x[1]=110;snake.y[1]=100;

   snake.node=2;/*节数*/

   PrScore();/*输出得分*/

   while(1)/*可以重复玩游戏,压ESC键结束*/

   {

      while(!kbhit())/*在没有按键的情况下,蛇自己移动身体*/

      {

  if(food.yes==1)/*需要出现新食物*/

  {

      food.x=rand()%400+60;

      food.y=rand()%350+60;

      while(food.x%10!=0)/*食物随机出现后必须让食物能够在整格内,这样才可以让蛇吃到*/

  food.x++;

      while(food.y%10!=0)

  food.y++;

  food.yes=0;/*画面上有食物了*/

  }

  if(food.yes==0)/*画面上有食物了就要显示*/

  {

              setcolor(GREEN);

              rectangle(food.x,food.y,food.x+10,food.y-10);

  }

         for(i=snake.node-1;i>0;i--)/*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/

         {

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

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

  }

       /*1,2,3,4表示右,左,上,下四个方向,通过这个判断来移动蛇头*/

  switch(snake.direction)

  {

     case 1:snake.x[0]+=10;break;

     case 2: snake.x[0]-=10;break;

     case 3: snake.y[0]-=10;break;

     case 4: snake.y[0]+=10;break;

  }

  for(i=3;i<snake.node;i++)/*从蛇的第四节开始判断是否撞到自己了,因为蛇头为两节,第三节不可能拐过来*/

  {

     if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0])

     {

               GameOver();/*显示失败*/

               snake.life=1;

               break;

     }

        }

 if(snake.x[0]<55||snake.x[0]>595||snake.y[0]<55||

    snake.y[0]>455)/*蛇是否撞到墙壁*/

 {

     GameOver();/*本次游戏结束*/

     snake.life=1; /*蛇死*/

 }

 if(snake.life==1)/*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/

           break;

 if(snake.x[0]==food.x&&snake.y[0]==food.y)/*吃到食物以后*/

 {

           setcolor(0);/*把画面上的食物东西去掉*/

           rectangle(food.x,food.y,food.x+10,food.y-10);

    snake.x[snake.node]=-20;snake.y[snake.node]=-20;

          /*新的一节先放在看不见的位置,下次循环就取前一节的位置*/

    snake.node++;/*蛇的身体长一节*/

    food.yes=1;/*画面上需要出现新的食物*/

    get();

    PrScore();/*输出新得分*/

 }

 setcolor(4);/*画出蛇*/

 for(i=0;i<snake.node;i++)

    rectangle(snake.x[i],snake.y[i],snake.x[i]+10,

               snake.y[i]-10);

 delay(gamespeed);

 setcolor(0);/*用黑色去除蛇的的最后一节*/

 rectangle(snake.x[snake.node-1],snake.y[snake.node-1],

 snake.x[snake.node-1]+10,snake.y[snake.node-1]-10);

     }  /*endwhile(!kbhit)*/

    if(snake.life==1)/*如果蛇死就跳出循环*/

        break;

    key=bioskey(0);/*接收按键*/

    if(key==ESC)/*按ESC键退出*/

       break;

    else

       if(key==UP&&snake.direction!=4)

/*判断是否往相反的方向移动*/

   snake.direction=3;

       else

   if(key==RIGHT&&snake.direction!=2)

      snake.direction=1;

   else

      if(key==LEFT&&snake.direction!=1)

  snake.direction=2;

      else

  if(key==DOWN&&snake.direction!=3)

     snake.direction=4;

   }/*endwhile(1)*/

}

/*游戏结束,清除屏幕,输出分数,显示游戏结束信息。*/

void GameOver(void)

{

    cleardevice();

    PrScore();

   setcolor(RED);

   settextstyle(0,0,4);

   outtextxy(200,200,"GAME OVER");

   getch();

}

/*输出成绩*/

void PrScore(void)

{  

   char str[10];

   setfillstyle(SOLID_FILL,YELLOW);

   bar(50,15,220,35);

   setcolor(6);

   settextstyle(0,0,2);

   sprintf(str,"score:%d",score);

   outtextxy(55,20,str);

}

/*图形结束*/

void Close(void)

{  

    getch();/*getch()观察屏幕输出*/

    closegraph();

}

6、运行结果分析

   

通过运行,我对自己的设计比较满意。运行结果正如我所料,此贪吃蛇游戏具有易操作性及充满活力的外观。

截图及描述:

第一个开始DOS界面

图6-1 开始画面

     此图为开始画面图,蛇有三节,墙壁颜色为绿色,显得较有活力。

                   

图6-2 蛇吃到两个食物后

蛇吃到食物后,得分为2分,蛇延长两节。

图6-3 游戏结束画面

7、实习心得

为了提高我们的实践能力,让我们学以致用,能灵活运用所学的知识进行再创造,学校特安排我们进行为期一周的Visual C++课程设计实习,并安排了指导老师帮助辅导,让我们在规范化、严谨化、实用化上面有了很大进展。

在此次字符统计程序开发过程中,有很多东西值得我们思考并总结。

开发过程大体可分为以下几个步骤:

  (1)思考总体设计方案:总体结构和模块外部设计,功能分配。思考要实现整个程序大体需要的几个模块和其中用到的Visual C++语言基本操作符、语句等。

  (2)画出总体设计方案流程图:用流程图的形式展现你的基本编程思想。

  (3)流程图具体化:即将流程图中的几大模块的具体实现思考清楚,可以用流程图的形式展现.并想好实现的关键代码。

  (4)编辑程序代码:这是一个至关重要复杂而且需要反复修改的环节,在此环节中你将发现总体设计和模块思想会存在很多问题,需不断改进.如何实现各函数功能,达到预期效果也将是一项繁复的工作。

  (5)代码的调试:在Visual C++6.0环境下输入代码并进行调试和正确运行。在调试过程中会遇到很多需要精化的地方,需要十足的耐心与细心,不断改进完善程序。

  (6)最后修饰:程序可以正确运行之后,再不影响程序功能的情况下,运用各种辅助性符号,使界面更加美观漂亮,操作更人性化.增强程序的新意与可行性。 

通过这次课程设计,使我们更加熟悉的掌握了Visual C++语言的运用。帮助我们熟悉了更多Visual C++语言的功能,提高了我们的动手能力,学到了许多解决实际问题的宝贵经验.同时也挖掘出了我们潜在的能力,使我们对自己更有自信,对编程也更有兴趣。我相信,只要努力、勤奋、坚持不懈,就没有什么做不到的事,不能还没开始就退缩,要勇于拼搏,敢于创新。

总之,通过这次实习,我学到了好多书本以外的知识!

参考文献

[1]谭浩强《c程序设计》

[2] 张岳新《Visual C++程序设计》。

[3] 张岳新《Visual C++程序设计基础实验指导书》。

[4]沈被娜 刘祖照 《计算机软件技术基础》

[5] 李强,贾云霞. Visual C++项目开发实践.北京:中国铁道出版社,2004

[6] 郑莉,董渊,张瑞丰.C++语言程序设计.2003.

[7] H.M.Deitel,P.J.Deitel. Small C++ How to Program.2006.

成 绩 评 定 表

相关推荐