宁夏大学
C#语言设计
题目:彩色贪吃蛇
学 院 数学计算机学院_______
专 业_____计算机科学与技术(师范)_
年级班别_____ ____ ___
学 号
学生姓名_____ ___________
指导教师_____ ___________
成 绩
20 年 月
目 录
1、课程设计目的…………………………………………………………1
2、课程设计要求…………………………………………………………1
3、设计题目分析及内容…………………………………………………1
3.1程序功能………………………………………………………1
3.2设计思想………………………………………………………1
3.3设计的具体实现………………………………………………1
3.4 总体流程图……………………………………………………7
3.5程序代码编写及注释…………………………………………8
3.6调试问题及解决方法…………………………………………13
3.7调试结果………………………………………………………13
4、设计
………………………………………………………14
5、建议…………………………………………………………………15
6、评阅意见……………………………………………………………15
7、参考文献……………………………………………………………15
1、课程设计目的
编写C语言程序实现贪吃蛇游戏,贪吃蛇游戏是一个深受人们喜爱的游戏,一条蛇在密闭的围墙内,在围墙内随机出现一个食物,通过按键盘上的四个光标键控制蛇向上下左右四个方向移动,蛇头撞到食物,则表示食物被蛇吃掉,这时蛇的身体长一节,同时计10分,接着又出现食物,等待被蛇吃掉,如果蛇在移动过程中,撞到墙壁或身体交叉蛇头撞到自己的身体游戏结束。作为一个完整的程序,尤其是一个完整的游戏,必须考虑人机交流与用户体验。游戏的界面不能太丑,更不能连个简单的界面都没有。游戏应该有个比较漂亮的界面,在有必要硬件支持和软件的支持下,游戏开发者必须最大限度的使游戏美观。游戏的美观是一方面,游戏的内在素质是另一方面。一个游戏的优劣,最终由玩家决定。在游戏与玩家见面之前,游戏开发者要设计一种让玩家投入的游戏模式,并且在一定的游戏
下进行。
关键词 贪吃蛇 流程图 c语言 源程序 WIN-TC
2、课程设计要求
(1)分析课程设计题目的要求
(2)写出详细设计说明
(3)编写程序代码,调试程序使其能正确运行
(4)设计完成的软件要便于操作和使用
(5)设计完成后提交课程设计报告
(6)贪吃蛇游戏的要求:
(1)用图形方式实现用键盘操作的贪吃蛇游戏,应有各种颜色、界面良好、操作方便等特点。
(2)收集资料,分析课题,分解问题,形成总体设计思路;深入分析各个小问题,列出大纲,编写各部分程序模块;对于设计中用到的关键函数,要学会通过查资料,弄懂其用法,要联系问题进行具体介绍;完成课程设计报告。
3、设计题目分析
3.1、程序功能
贪吃蛇游戏是一个经典小游戏,一条蛇在封闭围墙里,围墙里随机出现一个食物,通过按键盘四个光标键控制蛇向上下左右四个方向移动,蛇头撞倒食物,则食物被吃掉,蛇身体长一节,同时记10分,接着又出现食物,等待蛇来吃,如果蛇在移动中撞到墙或身体叉蛇头撞倒自己身体游戏结束。
3.2 设计思想
程序关键在于表示蛇的图形及蛇的移动。用一个小矩形快表示蛇的一节身体,身体每长一节,增加一个矩形块,蛇头用俩节表示。移动时必须从蛇头开始,所以蛇不能向相反的方向移动,如果不按任意键,蛇自行在当前方向上前移,但按下有效方向键后,蛇头朝着该方向移动,一步移动一节身体,所以按下有效方向键后,先确定蛇头的位置,而后蛇的身体随蛇头移动,图形的实现是从蛇头新位置开始画出蛇,这时,由于未清屏的原因,原来的蛇的位置和新蛇的位置差一个单位,所以看起来蛇多一节身体,所以将蛇的最后一节用背景色覆盖。食物的出现与消失也是画矩形块和覆盖矩形块。为了便于理解,定义两个结构体:食物与蛇。
3.3.设计的具体实现
(1)函数定义
函数定义是对各个基础函数的定义,并且设置需要运用的信息,便于调用
#define M 100
#define N 100
#define R 100
#define T 100
#include
#include
#include
#define LEFT 0x4b00
#define RIGHT 0x4d00
#define DOWN 0x5000
#define UP 0x4800
#define ESC 0x011b
int i,j,key,q;
int score=0;/*得分*/
long gamespeed=50000;/*游戏速度自己调整*/
struct Food
{
int x;/*食物的横坐标*/
int y;/*食物的纵坐标*/
int yes;/*判断是否要出现食物的变量*/
}food;/*食物的结构体*/
struct Snake
{
int x[M][N];
int y[R][T];
int node;/*蛇的节数*/
int direction;/*蛇移动方向*/
int life;/* 蛇的生命,0活着,1死亡*/
}snake;
void Init(void);/*图形驱动*/
void Close(void);/*图形结束*/
void DrawK(void);/*开始画面*/
void GameOver(void);/*结束游戏*/
void GamePlay(void);/*玩游戏具体过程*/
void PrScore(void);/*输出成绩*/
void main(void)/*主函数*/
(2)主函数main( )
主函数是程序的主流程,首先定义使用到的常数、全局变量及函数原型说明,然后初始化图形系统,调用函数DrawK()画出开始画面,调用函数GamePlay(),即玩游戏的具体过程,游戏结束后调用Close()关闭图形系统,结束程序
/*主函数*/
void main(void)
{
Init();/*图形驱动*/
DrawK();/*开始画面*/
GamePlay();/*玩游戏具体过程*/
Close();/*图形结束*/
}
/*图形驱动*/
void Init(void)
{
int gd=DETECT,gm;
initgraph(&gd,&gm,"c:\\tc");
cleardevice();
}
(3) 画界面函数DrawK( )
主界面是一个封闭的围墙,用两个循环语句分别在水平和垂直方向输出连续的宽度和高度均的矩形方块,表示围墙,为了醒目,设置为白色。
void DrawK(void)/*开始画面,左上角坐标为(50,40),右下角坐标为(610,460)的围墙*/
{
setbkcolor(0);/*设置当前背景颜色*/
setcolor(YELLOW);/*设置当前画线颜色*/
setlinestyle(SOLID_LINE,0,THICK_WIDTH);/*设置线型*/
for(i=50;i<=600;i+=10)/*画围墙*/
{
rectangle(i,40,i+10,49); /*上边*/
rectangle(i,451,i+10,460);/*下边*/
}
for(i=40;i<=450;i+=10)
{
rectangle(50,i,59,i+10); /*左边*/
rectangle(601,i,610,i+10);/*右边*/
}
}
(4)游戏具体过程函数GamePlay( )
这是游戏的主要组成部分,他采用将前一节的坐标赋给后一节,用背景颜色将最后节去除,当蛇头的坐标与食物的坐标相等时,表示食物被吃掉了。
void GamePlay(void)
{
randomize();/*随机数发生器*/
food.yes=1;/*1表示需要出现新食物,0表示已经存在食物*/
snake.life=0;/*活着*/
snake.direction=1;/*方向往右*/
snake.x[0][0]=100;snake.y[0][0]=100;/*蛇头*/
snake.x[0][1]=110;snake.y[0][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(15);
rectangle(food.x,food.y,food.x+10,food.y-10);
}
for(i=snake.node-1,j=snake.node-1;i>0,j>0;i--,j--)/*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/
{
snake.x[i][j]=snake.x[i-1][j-1];
snake.y[i][j]=snake.y[i-1][j-1];
}
/*1,2,3,4表示右,左,上,下四个方向,通过这个判断来移动蛇头*/
switch(snake.direction)
{
case 1:snake.x[0][0]+=10;break;
case 2: snake.x[0][0]-=10;break;
case 3: snake.y[0][0]-=10;break;
case 4: snake.y[0][0]+=10;break;
}
for(i=3,j=3;i595||snake.y[0][0]<55||
snake.y[0][0]>455)/*蛇是否撞到墙壁*/
{
GameOver();/*本次游戏结束*/
snake.life=1; /*蛇死*/
}
if(snake.life==1)/*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/
break;
if(snake.x[0][0]==food.x&&snake.y[0][0]==food.y)/*吃到食物以后*/
{
gamespeed= gamespeed+100;
setcolor(0);/*把画面上的食物东西去掉*/
rectangle(food.x,food.y,food.x+10,food.y-10);
snake.x[snake.node][snake.node]=-20;snake.y[snake.node][snake.node]=-20;
/*新的一节先放在看不见的位置,下次循环就取前一节的位置*/
snake.node++;/*蛇的身体长一节*/
food.yes=1;/*画面上需要出现新的食物*/
score+=10;
PrScore();/*输出新得分*/
}
q=rand()%15;
setcolor(q);/*画出蛇*/
for(i=0,j=0;i书也会变快。通过键盘操控来玩游戏主要由判反向移动模块完成,即当蛇不是反向移动时,按照键盘上方向键指示移动。游戏结束模块功能简单,仅完成输出得分与提示语功能。最后图形结束模块完成关闭图形功能。
3.5、程序代码编写及注释
#define M 100
#define N 100
#define R 100
#define T 100
#include
#include
#include
#define LEFT 0x4b00
#define RIGHT 0x4d00
#define DOWN 0x5000
#define UP 0x4800
#define ESC 0x011b
int i,j,key,q;
int score=0;/*得分*/
long gamespeed=50000;/*游戏速度自己调整*/
struct Food
{
int x;/*食物的横坐标*/
int y;/*食物的纵坐标*/
int yes;/*判断是否要出现食物的变量*/
}food;/*食物的结构体*/
struct Snake
{
int x[M][N];
int y[R][T];
int node;/*蛇的节数*/
int direction;/*蛇移动方向*/
int life;/* 蛇的生命,0活着,1死亡*/
}snake;
void Init(void);/*图形驱动*/
void Close(void);/*图形结束*/
void DrawK(void);/*开始画面*/
void GameOver(void);/*结束游戏*/
void GamePlay(void);/*玩游戏具体过程*/
void PrScore(void);/*输出成绩*/
/*主函数*/
void main(void)
{
Init();/*图形驱动*/
DrawK();/*开始画面*/
GamePlay();/*玩游戏具体过程*/
Close();/*图形结束*/
}
/*图形驱动*/
void Init(void)
{
int gd=DETECT,gm;
initgraph(&gd,&gm,"c:\\tc");
cleardevice();
}
/*开始画面,左上角坐标为(50,40),右下角坐标为(610,460)的围墙*/
void DrawK(void)
{
/*setbkcolor(LIGHTGREEN);*/
setcolor(6);
setlinestyle(SOLID_LINE,0,1);/*设置线型*/
for(i=50;i<=600;i+=10)/*画围墙*/
{
rectangle(i,40,i+10,49); /*上边*/
rectangle(i,451,i+10,460);/*下边*/
}
for(i=40;i<=450;i+=10)
{
rectangle(50,i,59,i+10); /*左边*/
rectangle(601,i,610,i+10);/*右边*/
}
}
/*玩游戏具体过程*/
void GamePlay(void)
{
randomize();/*随机数发生器*/
food.yes=1;/*1表示需要出现新食物,0表示已经存在食物*/
snake.life=0;/*活着*/
snake.direction=1;/*方向往右*/
snake.x[0][0]=100;snake.y[0][0]=100;/*蛇头*/
snake.x[0][1]=110;snake.y[0][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(15);
rectangle(food.x,food.y,food.x+10,food.y-10);
}
for(i=snake.node-1,j=snake.node-1;i>0,j>0;i--,j--)/*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/
{
snake.x[i][j]=snake.x[i-1][j-1];
snake.y[i][j]=snake.y[i-1][j-1];
}
/*1,2,3,4表示右,左,上,下四个方向,通过这个判断来移动蛇头*/
switch(snake.direction)
{
case 1:snake.x[0][0]+=10;break;
case 2: snake.x[0][0]-=10;break;
case 3: snake.y[0][0]-=10;break;
case 4: snake.y[0][0]+=10;break;
}
for(i=3,j=3;i595||snake.y[0][0]<55||
snake.y[0][0]>455)/*蛇是否撞到墙壁*/
{
GameOver();/*本次游戏结束*/
snake.life=1; /*蛇死*/
}
if(snake.life==1)/*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/
break;
if(snake.x[0][0]==food.x&&snake.y[0][0]==food.y)/*吃到食物以后*/
{
gamespeed= gamespeed-100;
setcolor(0);/*把画面上的食物东西去掉*/
rectangle(food.x,food.y,food.x+10,food.y-10);
snake.x[snake.node][snake.node]=-20;snake.y[snake.node][snake.node]=-20;
/*新的一节先放在看不见的位置,下次循环就取前一节的位置*/
snake.node++;/*蛇的身体长一节*/
food.yes=1;/*画面上需要出现新的食物*/
score+=10;
PrScore();/*输出新得分*/
}
q=rand()%15;
setcolor(q);/*画出蛇*/
q=rand()%15;
for(i=0,j=0;i格式 。
C语言实验课刚开课时老师让我们分组做实验,自己写程序,看程序,这让C与语言学的不怎么好的我感到非常的困难,第一天下午在机房做了一个下午却没有一点儿的经验,这让我很失落,也非常后悔平时上课不好好上课,但是在同组成员的帮助与鼓励下,我觉得要慢慢的开始接受,一定要自学,就算不会一定要自己努力去学习,刚开始时,不懂得从哪里入手比较好,就从网上下载了别人的程序代码,先看懂别人的,让后我又试着自己编写了贪吃蛇的游戏,其中让我印象较深的一个函数是随机函数,觉得这个函数特别的神奇,因为如果要让食物随机的出现的话,这个函数就可以达到这样的效果,了解了这个函数之后,我又想如果能让蛇的每一节的颜色都不一样那不是会更好吗,因为这样可以大大的提高视觉上的效果,于是我就试着应用随机函数来达到这样的效果,可是我却失败了,不过虽然失败了,但是却让我发现贪吃蛇的颜色可以整体的变换,运用随机函数可以做到这样的一点,记得还有一次老师在上课时看了我的函数问了一个问题,为什么不用二维数组来做,而选择一维数组,我当时的确在想,我实在是没想到这个问题,只是一味的为了完成课程设计而做的游戏设计,并不是为了了解C语言,运用C语言,当时自己心里真的不好受,下课后,我试着再用二维数组去做这个设计,但是我并没有改掉所有的一位数组,而是留了一部分一位数组,另一部分改为二维数组,用来比较这两种数组,通过比较之后发现,反而一位数组比二维数组更方便去定义,也就是说在C语言里并不是越难越麻烦的语句写出来的语句才是好的,C语言要注意灵活的使用一些基础的,简单的易于理解的一些语句来写,这样更有利于为自己的C与语言程序设计做好基础工作,而且编写程序是一件高精度的事,需要我们特别的细心,在编写程序中,真的是细节决定成败,因为不管程序的语句是多是少,但是只要有一条语句或语法不正确,就不能使程序得到所需要的结果。没能够使自己编写出来的程序等到想要的结果,意味着这是一个不理想的程序,对于本次编写来说则是失败的。否则一个小小的错误也会导致程序运行不了,得不到想要的结果。自己第一次虽然完成了属于自己的程序,但是错误也很多,不过真的耶很幸福因为那是自己编写的,同时也是自己进步的证明,经过自己的努力,与同学的帮助,我终于将程序调好到能够运行了。而且也出来了自己想要的界面。经过此次试验也让我明白,C语言实训和平时上课所 接触的程序是有很大不同的, 所经受的考验和克服的困难是平时所无法比拟的,一定要多上机练习,才能够有所进步,否则只会停滞不前,或者说落后。所以在以后的学习中我想你不管是C与语言课,还是其他的课,我都会注重实践的,否则就算理论学的很好,也起不到一定的作用。
2遇到的问题与解决方法
表示蛇的图形及蛇的移动方向。用一个小矩形块表示蛇的一节身体,身体每长一节,增加一个矩形块。移动时必须从蛇头开始,所以蛇不能向相反的方向移动。如果不安任何键,蛇自行在当前方向上移动,当游戏者按了有效的方向键后,先确定蛇头的位置,然后蛇身体随着蛇头移动。在图形的实现上,从蛇头的新位置开始画出蛇。这时,由于没有清屏的原因,原来蛇的位置和新蛇的位置差一个单位,将蛇的最后一节用背景色覆盖。
检测蛇有无撞到食物、围墙或是自己的身体。当蛇开始移动之后,需要判断蛇头要移动到的新的位置的情况,然后根据新位置是空白、食物、围墙还是蛇的身体来做出相应的操作。可以用不同的值来表示每个位置的情况。
事物的随机产生。当食物被吃掉后,要在场景中重新随机产生。利用C语言提供的随机函数rand()产生随机数并将该随机数缩小到符合场景大小的范围中来,以此作为食物位置的横纵坐标。
蛇的移动速度调节。当分数达增加后,移动速度将进行一定的提升。蛇的两次移动之间的时间间隔,可以使用C函数库中的delay()函数来实现。
在编写程序时,发现蛇可以后退,与一般的C贪吃蛇相比这点不正确,经过查询,并查看相关程序,发现是语句中的错误,缺少一条语句引起的。总之在遇到问题时自己要仔细查询实验程序,修改并运行。当我选择编写小游戏“贪吃蛇”这个题目时,一开始想运用大量函数来完成,但是在慢慢琢磨之后,觉得这个程序可以简化,于是改变了编程思路。当然还有不少文件的读写问题,不过还是通过不断测试之后顺利解决了。
3创新
随机函数,特别的神奇,因为如果要让食物随机的出现的话,这个函数就可以达到这样的效果,了解了这个函数之后,我又想如果能让蛇的每一节的颜色都不一样那不是会更好吗,因为这样可以大大的提高视觉上的效果,于是我就试着应用随机函数来达到这样的效果,可是我却失败了,不过虽然失败了,但是却让我发现贪吃蛇的颜色可以整体的变换,运用随机函数可以做到这样的一点,这让我得到的体会是,书上和老师教的内容是有限的,我们需要不断地靠自己去学习,向他人请教,学习掌握更多的知识,并不断创新,这样我们才能编出更好的C程序。
4不足之处
缺少创新。
5在设计这个程序中我主要学会了如何运用以下有关C语言的知识
1) 函数定义是要做到顾名思义是很重要的,它对读程序的人正确认识程序
十分重要,在修改这个程序的过程中也能很快找到程序各模块的作用,大大增
加了程序的可读性。
2) 分析函数先从main()函数入手。Main()函数是C源程序编译时的开始,
从main()函数开始读函数可将其他函数的功能理解得更透彻。而且在此函数中我对于食物的处理侧重于一位数组,而对蛇侧重于采用二维数组,复习了解了一位数组,二维数组,同时也对二者做了一个比较。在此试验中,我觉得使用一位数组更为简单。
3) 在做程序的时候先列框架,将这个程序所要达到的目的(功能)分析出
来,选择正确的数据结构然后在将程序模块化,按照模块编写函数更加简单合理。
4) 我还了解了很多的库函数的作用,如字符串函数中有很多对字符串进行
处理的函数,起功能我都有所了解。
5) 而且我觉得对我印象特别深的是随机函数,特别的有意思,可以使蛇的颜色变化。同时在设计程序之前,务必要对你所设计的题目和内容有一个系统的了解,
知道所设计的题目和内容包含那些资源。
6) 设计程序采用什么编程语言并不是非常重要,关键要有一个清晰的思路
和一个完整的软件流程图,因而,要先把设计原理与思路搞清楚,再把流程图画出来,这样设计起来就简单多了。
7) 在设计程序时,不能妄想一次就将整个程序设计好,“反复修改,不断改
进”是程序设计的必经之路,发现错误也是取得成绩的一种。
8) 要养成注释程序的好习惯,一个程序的完美与否不仅仅是实现功能,而
应该让人一看就能明白你的思路,这样也为资料的保存和交流提供了方便。
9)我在游戏运行结束的画面上添加了自己的联系方式,因为我想在此次试验结束后将自己的贪吃蛇代码放在百度文档中,希望能与更多的C语言爱好者交流,同时提高自己的水平,加深对C语言的了解。
最后,要感谢学校为我们提供这次实验机会,也要感谢老师的教导和其他同学对我的帮助与支持。
5、建议:在设计过程中应该提高合作交流。
6、评阅意见
教师签名:
年 月 日
7、参考文献
【1】谭浩强著.C程序设计(第二版).北京:清华大学出版社,1999
【2】潘云鹤.董金祥等著.计算机图形学——原理、方法及应用.北京:高等教育出版社,2003.12
【3】C编写组编.常用C语言用法速查手册.北京:龙门书局,1995
【4】陈元琰编著.计算机图形学实用技术.北京:科学出版社,2000
【5】孙家广等.计算机图形学(第三版).清华大学出版社,2004
【6】陆润民.C语言绘图教程.北京:清华大学出版社,1996
【7】Herbert Schildt著.戴健鹏议.C语言大全(第二版).北京:电子工业出版社,1994
【8】Steohen G Kochan著.Programming in ANSI C.Hagden Books Indianapolis:Indiana,U.S.A,1994