贪吃蛇游戏程序设计说明书
题目:贪吃蛇游戏
学校:
系别:
专业
班级:
姓名:
学号:
指导老师:
日期:
一、设计题目:
贪吃蛇是一款经典的休闲游戏,一条蛇在密闭的围墙内,随机出现一个食物,通过控制方向键操作小蛇不停的朝着食物前进,直到吃掉食物。每吃一个食物,小蛇都会长长一截,随之难度增大;当小蛇头撞到墙或自己时,小蛇死亡。
二、功能设计:
本游戏要求实现以下几个功能:
(1)用上、下、左、右键控制游戏区蛇的运动方向,使之吃食而使身体变长;
(2)用户可以调节蛇的运行速度来选择不同的难度;
(3)游戏分多个难度级别;
(4)用户可自选颜色;
(5)记录成绩前五名的游戏玩家;
(6)增加背景音乐;
(7)提高障碍物和游戏级别。
三、程序模块图:
贪吃蛇游戏
初始化
画
图
模
块
控
制
模
块
设
置
模
块
帮
助
模
块
墙
体
蛇
身
食
物
移
动
食
物
死
亡
变
长
成
绩
等
级
音
效
四、 算法流程图:
是 否
否
是
否 是
开 始
初始化界面和蛇身
放置食物
获取按键
开始运动
碰到边界
蛇吃到食 蛇长大
蛇死亡
继续
结束
五、函数原型与功能
1.主函数:void main()
启动程序,触动其他函数。
2.初始化:void init ()
设置背景框大小、蛇体初始值,随机产生食物。
3.随机产生食物:void setfoodcrd()
设置食物生成坐标,0表示食物被吃。
4.画食物:void showfood()
用矩形框来画食物
5.画蛇:void showsnake()
根据蛇的坐标和节数,循环用矩形框来画蛇。
6.蛇移动:void snakemove()
根据按键,重设坐标
7.改变蛇的方向:void changeskdir()
响应用户的运动方向
8.判断蛇是否死亡:void judgeslod
判断蛇是否碰到自己或墙。
9.判断蛇是否吃到食物:void judgefood()
判断是否吃到食物,吃食后变0,蛇增长一节。
10.结束游戏:void gameover()
结束话语,并执行下一步。
六、基本代码
#include
#include
#include
#pragma comment(lib,"Winmm.lib")
#include "MyTimer.h"
#define SIZEMAX 100 /*蛇最大长度*/
#define SPEED 100 /*初始速度*/
#define len 20 /*蛇宽度*/
#define lm 10 /*蛇每次移动距离*/
#define initlen 600 /*初始化窗口正方形的长度*/
#define Min_snakelen 2 /*蛇的最小长度*/
typedef struct {
int x,y;
}DIR;
int snakelen=Min_snakelen; /*蛇的长度*/
int isfood=1; /*食物状态*/
int isover=0; /*游戏状态*/
int ispause=1; /*暂停状态*/
int ismusic=1; /*音乐播放状态*/
char dir; /*记录蛇运动的方向*/
char c='d';
DIR snake[500],food; /*定义蛇节点和食物的类型*/
int speed=SPEED;
void drawmap() /*画地图函数*/ {
IMAGE img;
char str[10];
loadimage(&img,"贪吃蛇.jpg"); /*游戏界面*/ putimage(0,0,&img);
loadimage(&img,"7.jpg"); /*侧栏提示*/
putimage(600,0,&img);
sprintf(str,"%d",snakelen);
setfont(30,0,"宋体");
setbkmode(TRANSPARENT);
outtextxy(620,10,"操作说明:");
setfont(20,0,"宋体");
outtextxy(615,50,"awsd控制方向键");
outtextxy(615,80,"p键暂停");
outtextxy(615,110,"o键继续");
outtextxy(615,200,"esc键退出");
outtextxy(615,140,"l键暂停音乐");
outtextxy(615,170,"k键继续播放");
outtextxy(730,250,str);
outtextxy(620,250,"蛇当前长度");
}
void init() /*初始化蛇函数*/ {
int i;
IMAGE img;
snake[0].x=9*len+lm;
snake[0].y=4*len+lm;
loadimage(&img,"1.jpg");
putimage(snake[0].x-lm,snake[0].y-lm,&img);
for(i=1;i { snake[i].x=len*(9-i)+lm; snake[i].y=len*4+lm; loadimage(&img, "2.jpg"); putimage(snake[i].x-lm,snake[i].y-lm, &img); } } void showsnake() /*画蛇函数*/ { int i; IMAGE img; loadimage(&img, "1.jpg"); putimage(snake[0].x-lm,snake[0].y-lm , &img); loadimage(&img, "2.jpg"); for(i=1;i putimage(snake[i].x-lm,snake[i].y-lm, &img); } void snakemove() /*画动蛇函数*/ { int i; int mx=snake[0].x; int my=snake[0].y; switch(dir) { case 'a':mx-=len;break; case 'd':mx+=len;break; case 'w':my-=len;break; case 's':my+=len;break; default:break; } for(i=snakelen-1;i>=0;i--) { snake[i+1].x=snake[i].x; snake[i+1].y=snake[i].y; } snake[0].x=mx; snake[0].y=my; showsnake(); } int ceshiover() /*检测游戏结束函数*/ { int i; if(snake[0].x<0||snake[0].x>30*len-lm||snake[0].y<0||snake[0].y>30*len-lm) return 1; for(i=1;i { if(snake[0].x==snake[i].x&&snake[0].y==snake[i].y) return 1; } return 0; } int foodinsnake() /*检测食物是否在蛇上函数*/ { for(int i=0;i if(food.x==snake[i].x&&food.y==snake[i].y) return 1; else return 0; } void showfood() /*画食物函数*/ { IMAGE img; do{ food.x=(rand()%30)*len+lm; food.y=(rand()%30)*len+lm; } while(foodinsnake()); loadimage(&img, "3.jpg"); putimage(food.x-lm,food.y-lm , &img); isfood=0; } void kmusic() { if(ismusic==0) mciSendString("pause mymusic",NULL,0,NULL); if(ismusic==1) mciSendString("resume mymusic",NULL,0,NULL); } void playbkmusic() /*播放背景音乐函数*/ { mciSendString("open 超级玛丽.mp3 alias mymusic", NULL, 0, NULL); mciSendString("play mymusic repeat", NULL, 0, NULL); } void playgame() /*玩游戏函数*/ { c='d'; //蛇开始向右移动 isover=0; snakelen=Min_snakelen; dir='d'; IMAGE img; MyTimer t; //定义精确延时对象 int T=200; // 延长时间 drawmap(); //画游戏地图 init(); //画小蛇初始位置 while(!isover) { if(ispause) { snakemove(); FlushBatchDraw(); //批量绘图 EndBatchDraw(); //结束批量绘图 if(snake[0].x==food.x&&snake[0].y==food.y){ snakelen++; isfood=1; } if(isfood) showfood(); if(snakelen<35) T=200-3*snakelen; t.Sleep(T); BeginBatchDraw(); // 开始批量绘图模式,防止闪烁问题 drawmap(); loadimage(&img, "3.jpg"); // 加载食物图片 putimage(food.x-lm,food.y-lm , &img); }; //按键控制 if(kbhit()) c=getch(); switch(c){ case 'a': if(dir!='d'){ dir=c; }break; case 'd': if(dir!='a'){ dir=c; }break; case 'w': if(dir!='s'){ dir=c; }break; case 's': if(dir!='w'){ dir=c; }break; case 27: exit(0); break; //游戏退出 case 'p': ispause=0;break; //p暂停 case 'o': ispause=1;break; //o继续游戏 case 'l': ismusic=0;break; //l暂停音乐 case 'k': ismusic=1;break; //k继续播放 default:break; } kmusic(); //音乐控制播放 //判断游戏结束 if(ceshiover()) isover=1; //判断是否重新再来 HWND wnd = GetHWnd(); //获取窗口句柄 if(isover) if (MessageBox(wnd, "游戏结束。\n重来一局吗?", "询问", MB_YESNO | MB_ICONQUESTION) == IDYES) playgame(); //递归判断出口 } EndBatchDraw(); //结束批量绘图模式 } void gameover() //游戏结束函数 { IMAGE img; loadimage(&img,"结束.jpg"); putimage(0,0,&img); setcolor(BLUE); setfont(30,0,"宋体"); settextcolor(YELLOW); outtextxy(280,100,"125042120 郭栋"); outtextxy(320,150,"感谢您玩,谢谢"); Sleep(2000); } void gamebegin() //游戏开始函数 { MOUSEMSG m; IMAGE img,img2; mciSendString("open bk.mp3 alias mymusic", NULL, 0, NULL);//打开音乐 mciSendString("play mymusic", NULL, 0, NULL); //播放音乐 loadimage(NULL, "开始.jpg"); putimage(0,0,&img); getimage(&img2,260,250,211,71); settextcolor(BLUE); setfont(70,0,"宋体"); setbkmode(TRANSPARENT); //设置字体背景为透明 outtextxy(260,100,"贪吃蛇"); RECT r = {260,250,470,320}; setfont(40,0,"黑体"); setcolor(YELLOW); drawtext("开始游戏", &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE); while(1) { m=GetMouseMsg(); //获取鼠标消息 switch(m.uMsg) { case WM_MOUSEMOVE : //鼠标移动 if(m.x>260&&m.x<470&&m.y>250&&m.y<320){ setfillcolor(RED); fillrectangle(260,250,470,320); drawtext("开始游戏", &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE); } else{ putimage(260,250,&img2); setcolor(YELLOW); drawtext("开始游戏", &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE); }break; case WM_LBUTTONDOWN: //鼠标左键按下 if(m.x>260&&m.x<470&&m.y>250&&m.y<320){ mciSendString("close mymusic", NULL, 0, NULL); //关闭音乐 playbkmusic(); cleardevice(); playgame(); }break; default: break; } if(isover==1) break; } } void main() { initgraph(initlen+160,initlen); HWND hWnd=GetHWnd(); SetWindowText(hWnd,"贪吃蛇游戏-郭栋"); gamebegin(); gameover(); getch(); closegraph(); }