贪吃蛇游戏 C语言程序设计
来源:互联网 发布:剑网3女神脸数据 编辑:程序博客网 时间:2024/05/22 23:59
《计算机程序设计》课程设计报告
课 题 名 称 贪吃蛇游戏
班 级 软件1班
姓 名 neolone
目录
1 需求分析... 1
2 系统分析和设计... 1
2.1 数据结构的设计和选择的理由... 1
2.2 系统模块划分和模块结构... 2
2.3 流程图... 3
2.4 数据类型、全局变量和函数说明... 3
3 程序测试和运行结果... 4
4 课程报告小结... 5
4.1分数重叠显示... 5
4.2速度太快... 5
4.3食物可能出现在蛇身上... 5
附录A:程序源代码... 6
1 需求分析
【阐述课程设计应该完成的功能】
使用键盘的上下左右,来控制蛇的运动方向,ESC键退出,并显示得分。
2 系统分析和设计
2.1 数据结构的设计和选择的理由
本游戏中涉及的主要数据结构是如何表示运动的蛇、食物状态等问题。
2.1.1 从游戏参考画面中我们可以看到,贪吃蛇的身体是一节节的,由一个个大小相同的方块组成,那么我们可以用一个(x,y)坐标为左上角的、固定宽度的正方形来表示一节蛇身。为表示连续的多节身体,那么我们可以采用数组(或链表,或线性表)等数据结构来表示。下面以数组方式为例:
struct Point {
int x, y;
}
struct Point nodes[MAX_LENGTH]; //蛇身数组,MAX_LENGTH为最大蛇长
贪吃蛇是在不断的运动的,我们研究蛇的运动可以发现这样的特点:
1. 蛇头由键盘控制,键盘不操作时,保持原有方向运动;(用 intdirection;表示)
2. 运动时,蛇身后面一节移动到前面一节的位置。当我们用nodes[0]表示蛇头的时候,nodes[1]运动到nodes[0]处;nodes[2]运动到nodes[1]处...。
3. 吃到一个食物以后,蛇身会增加一节。即该数组中的有效数据个数加一。(用int length;表示)
根据上面的情况,我们可以设计蛇的数据结构如下:
struct Snake {
struct Point nodes[MAX_LENGTH]; //蛇身数组,保存每节蛇身的坐标。MAX_LENGTH为最大蛇长
int length; //当前蛇长
int direction; //蛇头运动方向
int live; //蛇活的,还是已经死了?
}
2.1.2 关于食物,有两个属性:
1. 坐标位置
2. 状态:存在,或被吃。
故我们用以下结构表示:
struct Food {
struct Point position; //食物的位置
int exist; //存在?还是被吃?
}
2.2 系统模块划分和模块结构
void main() {
init(); /*初始化*/
l=1;
while(l) /*循环游戏*/
{
select(); /*游戏速度和结束的选择菜单*/
gamePlay(); /*游戏主程序*/
}
close(); /*关闭游戏*/
}
2.3 流程图
2.4 数据类型、全局变量和函数说明
2.4.1数据类型
struct Point { /*一个存放点坐标的结构体*/
intx, y; /*被多个结构体调用的基本参数,所以统一用point结构体来表示*/
};
struct Snake { /*用来模拟蛇状态的结构体*/
structPoint nodes[MAX_LENGTH]; /*用来存放蛇每一节的位置*/
intlength; /*蛇长*/
intdirection; /*蛇移动的方向*/
intlive; /*蛇是否活着*/
} snake;
/*比较形象的把蛇抽象为一个数据类型*/
struct Food { /*用来模拟食物状态的结构体*/
structPoint position; /*食物的位置*/
intexist; /*食物是否存在*/
} food;
2.4.2全局变量
Score \\得分
left,top,right,bottom \\游戏区域范围
lastx,lasty \\用来保存最后一节蛇的位置
keyCode \\用来保存按下的键
2.4.3函数说明
void init(void); \\初始化程序,给一些初始值赋值
void gamePlay(void); \\游戏主循环
void close(void); \\关闭游戏
void drawWall(void); \\画墙
void createFood(void); \\创造一个食物
void drawFood(void); \\画出食物
void drawSnake(void); \\画出蛇
void drawScore(void); \\画出分数
int touchWall(void); \\判断是否碰到墙
int touchSelf(void); \\判断是否碰到自己
void gameOver(void); \\游戏结束
void moveSnake(void); \\移动蛇
int oppositeDirection(int keyCode); \\判断是否方向有误
int foodEat(void); \\判断是否吃到食物
void expandSnake(void); \\把蛇增长一节
3 程序测试和运行结果
----------------------------------------------------------------------------选择速度开始或退出
----------------------------------------------------------------------------------------游戏运行中
--------------------------------------------------------------------------------------------------------游戏结束
4 课程报告小结
【遇到的问题及解决方法分析等】
4.1分数重叠显示
解决方法:每次都用一块黑的矩形覆盖
setfillstyle(1,16);
bar(45,45,150,80);
4.2速度太快
解决方法:循环delay
for(d=0;d<4;d++)
delay(GAME_SPEED);
4.3食物可能出现在蛇身上
解决方法:依次判断,若重叠则重新生成食物
void createFood() {
inti;
label:
food.position.x=left+10*((int)rand()%11);
food.position.y=top+10*((int)rand()%11);
for(i=0;i<=snake.length-1;i++){
if(snake.nodes[i].x==food.position.x&&snake.nodes[i].y==food.position.y)
gotolabel;
}
附录A:程序源代码
/*writer: neolone*/#include<graphics.h>#include<stdlib.h>#include<time.h>#include<stdio.h>#include<dos.h>#include<conio.h>#include<bios.h> #define TRUE 1#define FALSE 0 #define UP0x4800#define DOWN0x5000#define LEFT0x4B00#define RIGHT0x4D00#define ESC0x011B#define SPEED10x0231#define SPEED20x0332#define SPEED30x0433#defineQUIT 0x0B30#define ENTER 0x1C0D #defineMAX_LENGTH 100 /* max length ofsnake nodess */#defineGAME_SPEED 100 /* game speed */ /* datastructure */struct Point { int x, y;}; struct Snake { struct Pointnodes[MAX_LENGTH]; int length; int direction; int live;} snake; struct Food { struct Pointposition; int exist;} food; intscore=0,max,max1,max2,max3,left=200,top=200,right=300,bottom=300,lastx,lasty,keyCode,keyCode2,sp,l,sel,times=1;char text[80]; /* functionsdeclaration */void init(void);voidgamePlay(void);voidclose(void);voiddrawWall(void);voidcreateFood(void);voiddrawFood(void);voiddrawSnake(void);voiddrawScore(void);inttouchWall(void);inttouchSelf(void);voidgameOver(void);void moveSnake(void);intoppositeDirection(int keyCode);intfoodEat(void);voidexpandSnake(void);voidselect(void);/*------------------------*/void main() { init(); l=1; while(l) { select(); gamePlay(); } close();} void init() { int gdriver=VGA ,gmode=VGAHI ; snake.nodes[0].x=250; snake.nodes[0].y=250; snake.nodes[1].x=250; snake.nodes[1].y=260; snake.length=2; snake.live=1; snake.direction=UP; score=0; food.exist=0; initgraph(&gdriver,&gmode,"C:\\tc20\\BGI"); randomize();/*sui ji shu fa sheng qi*/ drawWall(); } void close() { FILE *fp; closegraph(); if((fp=fopen("data.txt","w"))==NULL) /*关闭时保存最高分*/ { exit(0); } else { fprintf(fp,"%d,%d,%d",max1,max2,max3); fclose(fp); } printf("pessany key to continue");} void gamePlay() { int keyCode,d; getch(); while(TRUE) { drawScore(); drawWall(); if(touchWall() || touchSelf()) { gameOver(); return; } if(!food.exist) createFood(); food.exist=1; drawFood(); drawSnake(); for(d=0;d<sp;d++) delay(GAME_SPEED); if(bioskey(1) != 0) { keyCode= bioskey(0); switch(keyCode){ caseESC: gameOver(); return; default: lastx=snake.nodes[snake.length-1].x; lasty=snake.nodes[snake.length-1].y; if(!oppositeDirection(keyCode)) { snake.direction= keyCode; } } } moveSnake(); if(foodEat()) { food.exist= FALSE; score+= 10; expandSnake(); } }} void drawWall(){ rectangle(left,top,right+10,bottom+10);} voidcreateFood() { int i;label: food.position.x=left+10*((int)rand()%11); food.position.y=top+10*((int)rand()%11); for(i=0;i<=snake.length-1;i++){ if(snake.nodes[i].x==food.position.x&&snake.nodes[i].y==food.position.y) goto label; } } void drawFood(){ setfillstyle(1,2); bar(food.position.x,food.position.y,food.position.x+10,food.position.y+10); } void drawSnake(){ int j; setfillstyle(1,4); for(j=0;j<=snake.length-1;j++) { bar(snake.nodes[j].x,snake.nodes[j].y,snake.nodes[j].x+10,snake.nodes[j].y+10); } } voiddrawScore(void) { setfillstyle(1,16); bar(45,45,150,80); setcolor(WHITE); sprintf(text,"writer:neolone"); outtextxy(170,50,text); sprintf(text,"score:%5d",score); outtextxy(50,50,text); } int touchWall(){ int x1=snake.nodes[0].x; int y1=snake.nodes[0].y; if(x1<left||x1>right||y1<top||y1>bottom) return TRUE; else return FALSE; } int touchSelf(){ int i; for (i=3;i<snake.length-1;i++) { if(snake.nodes[0].x==snake.nodes[i].x&&snake.nodes[0].y==snake.nodes[i].y) return TRUE; } return FALSE; } void gameOver(){ FILE *fp; int x2,y2; x2=180; y2=250; setcolor(WHITE); sprintf(text,"Gameover !!your score is %d,%d",score,sel); outtextxy(x2,y2,text); delay(1000); getch(); switch(sel%4) { case 1: if(score>max1) { max1=score; } break; case 2: if(score>max2) { max2=score; } break; case 3: if(score>max3) { max3=score; } break; default : { break; } }} void moveSnake(){ int k; setfillstyle(1,16); lastx=snake.nodes[snake.length-1].x; lasty=snake.nodes[snake.length-1].y; bar(snake.nodes[snake.length-1].x,snake.nodes[snake.length-1].y,snake.nodes[snake.length-1].x+10,snake.nodes[snake.length-1].y+10); for(k=snake.length-2;k>=0;k--) { snake.nodes[k+1].x=snake.nodes[k].x; snake.nodes[k+1].y=snake.nodes[k].y; } if(snake.direction==UP) snake.nodes[0].y-=10; else if(snake.direction==DOWN) snake.nodes[0].y+=10; else if(snake.direction==LEFT) snake.nodes[0].x-=10; else if(snake.direction==RIGHT) snake.nodes[0].x+=10; else ;} intoppositeDirection(int keyCode) { if(keyCode==UP&&snake.direction==DOWN){ return 1; } elseif(keyCode==DOWN&&snake.direction==UP) { return 1; } elseif(keyCode==LEFT&&snake.direction==RIGHT){ return 1; } elseif(keyCode==RIGHT&&snake.direction==LEFT){ return 1; } else return 0;} int foodEat() { if(snake.nodes[0].x==food.position.x&&snake.nodes[0].y==food.position.y) return 1; else return 0;} voidexpandSnake() { if(keyCode==UP){ lastx-=10; } else if(keyCode==DOWN) { lastx+=10; } else if(keyCode==LEFT){ lasty-=10; } else if(keyCode==RIGHT){ lasty+=10; } else ; snake.nodes[snake.length].x=lastx; snake.nodes[snake.length].y=lasty; snake.length++;} void select(){ setfillstyle(1,7); /*实现选择速度的可视化菜单*/ bar(420,220,490,310); setfillstyle(1,9); bar(430,230,480,240); setfillstyle(1,5); setcolor(WHITE); sprintf(text,"speed1"); outtextxy(430,230,text); bar(430,250,480,260); sprintf(text,"speed2"); outtextxy(430,250,text); bar(430,270,480,280); sprintf(text,"speed3"); outtextxy(430,270,text); bar(430,290,480,300); sprintf(text," quit "); outtextxy(430,290,text); sel=1; t=1; while(t){ delay(10); if (bioskey(1) != 0) { keyCode =bioskey(0); switch(keyCode){ caseUP: sel--;break; caseDOWN: sel++;break; caseENTER: t=0;break; default : break; } switch(sel%4) { case0: setfillstyle(1,9); bar(430,290,480,300); setcolor(WHITE); setfillstyle(1,5); bar(430,230,480,240); sprintf(text,"speed1"); outtextxy(430,230,text); bar(430,250,480,260); sprintf(text,"speed2"); outtextxy(430,250,text); bar(430,270,480,280); sprintf(text,"speed3"); outtextxy(430,270,text); sprintf(text,"quit "); outtextxy(430,290,text); break; case1: setfillstyle(1,9); bar(430,230,480,240); setfillstyle(1,5); setcolor(WHITE); sprintf(text,"speed1"); outtextxy(430,230,text); bar(430,250,480,260); sprintf(text,"speed2"); outtextxy(430,250,text); bar(430,270,480,280); sprintf(text,"speed3"); outtextxy(430,270,text); bar(430,290,480,300); sprintf(text,"quit "); outtextxy(430,290,text); break; case2: setfillstyle(1,9); bar(430,250,480,260); setfillstyle(1,5); bar(430,230,480,240); setcolor(WHITE); sprintf(text,"speed1"); outtextxy(430,230,text); sprintf(text,"speed2"); outtextxy(430,250,text); bar(430,270,480,280); sprintf(text,"speed3"); outtextxy(430,270,text); bar(430,290,480,300); sprintf(text,"quit "); outtextxy(430,290,text); break; case3: setfillstyle(1,9); bar(430,270,480,280); setfillstyle(1,5); bar(430,230,480,240); setcolor(WHITE); sprintf(text,"speed1"); outtextxy(430,230,text); bar(430,250,480,260); sprintf(text,"speed2"); outtextxy(430,250,text); sprintf(text,"speed3"); outtextxy(430,270,text); bar(430,290,480,300); sprintf(text,"quit "); outtextxy(430,290,text); break; default: break; } } } /*ch=getch();*/ if(times==1) /*读取历史最高分*/ { if((fp=fopen("data.txt","r"))==NULL) { sprintf(text,"Can not open thefile"); exit(0); } else { fscanf(fp,"%d,%d,%d",&max1,&max2,&max3); } fclose(fp); times=0; } switch(sel%4) { /*选择速度*/ case0: l=0; gameOver(); close(); break; case1: sp=5; init(); sprintf(text,"Hightestscore:%d",max1); outtextxy(50,90,text); break; case2: sp=3; init(); sprintf(text,"Hightestscore:%d",max2); outtextxy(50,90,text); break; case3: sp=1; init(); sprintf(text,"Hightestscore:%d",max3); outtextxy(50,90,text); break; default: break; } }
这是资源地址,源代码http://download.csdn.net/source/3483954
设计报告http://download.csdn.net/source/3483963
- 贪吃蛇游戏 C语言程序设计
- C语言贪吃蛇游戏
- C语言版贪吃蛇游戏
- C语言:贪吃蛇游戏
- C语言游戏:贪吃蛇
- 贪吃蛇游戏(c实现)
- 贪吃蛇 第二个C游戏
- C语言之贪吃蛇游戏源码
- C 语言 win32 游戏编程 - 贪吃蛇
- 基于c语言的贪吃蛇游戏
- c语言"贪吃蛇"游戏源码
- C语言贪吃蛇游戏2
- 贪吃蛇游戏的C语言实现
- C语言小项目--贪吃蛇游戏
- C语言之贪吃蛇游戏
- 纯C语言贪吃蛇游戏
- 贪吃蛇游戏
- brew贪吃蛇游戏
- 华为公司的笔试题:写一个Stack,注意处理异常。这里给出一个exception c++上讨论的一个简易版本代码。
- hdu 3415 Max Sum of Max-K-sub-sequence
- Linux系统下挂载windows分区方法
- android画图性能分析
- 利用标准遗传算法求解函数
- 贪吃蛇游戏 C语言程序设计
- gcc和g++的区别
- 《悟透JavaScript》学习札记十一之原型真谛一
- 关于CTO 和 职业经理人
- poj 2971 Give Me the Number
- window.parent与window.opener的区别
- LINUX 多线程编程
- delphi2010安装
- 利用HttpSessionListener统计在线人数