贪吃蛇项目报告.docx
- 文档编号:24770834
- 上传时间:2023-06-01
- 格式:DOCX
- 页数:54
- 大小:383.20KB
贪吃蛇项目报告.docx
《贪吃蛇项目报告.docx》由会员分享,可在线阅读,更多相关《贪吃蛇项目报告.docx(54页珍藏版)》请在冰豆网上搜索。
贪吃蛇项目报告
贪吃蛇项目报告
C语言项目设计报告
——贪吃蛇游戏
课程:
标准C语言
指导老师:
XXX
项目:
贪吃蛇游戏
班级:
XXXX班
组员:
XXX、XXX、XXX、XXX
姓名:
XXX
学号:
XXXXXXX
日期:
2012/7/7
一.项目开发文档…………………………(3)
1项目基本分析……………………………(3)
1.1项目目标…………………………(4)
1.2功能描述…………………………(4)
1.3小组分工…………………………(7)
2总体设计报告……………………………(8)
2.1函数分块…………………………(9)
2.2接口设计…………………………(9)
3详细设计报告……………………………(14)
3.1程序结构…………………………(14)
3.2算法流程…………………………(17)
4操作指南…………………………………(29)
4.1运行及结果截图…………………(29)
5项目总结…………………………………(32)
5.1优点与不足………………………(32)
5.2我的收获与总结(※)……………(33)
二.项目代码…………………………………(36)
贪吃蛇游戏
一项目开发文档
1项目基本分析
在我进行编写贪吃蛇游戏之前,我所做的必须是可行性分析,因为一旦进行贪吃蛇游戏项目的开发,就必须保证自己在规定的时间内能够独立的完整整个程序的所有功能,而且必须是最优的,因此,在开发贪吃蛇游戏之前,我必须要做的是可行性分析。
通过查找相关文档和技术支持,了解了VS环境下的开发过程,熟悉了C语言的开发技巧,通过以下几个方面,进行可行性分析:
1.参考文献:
《贪吃蛇游戏用户描述文档》、在网上找了相关源代码,确定自己能够在自己能力范围内开发出这个贪吃蛇游戏项目。
2.功能要求:
在进行整个项目开发之前,我必须要做的就是确定贪吃蛇游戏的主要功能,必须明确贪吃蛇游戏的功能,因为要进行游戏功能可行性分析,经过自己的查阅相关资料,我确定了贪吃蛇游戏的具体功能,详见后续部分详细设计。
3.性能需求:
必须保证自己开发的贪吃蛇游戏能够整体尽可能做到高效快速,不占用大量的使用资源,因为我做的是一个应用窗体控制台的游戏开发项目,必须要考虑资源使用情况,要求尽可能少用资源,在有限的资源范围内实现最大的可利用价值。
4.运行环境:
VS2010上编写并进行调试,经过安装软件,确定可以进行项目程序的编写。
5.界面要求:
采用Win7应用窗体标准界面,只需要使用键盘。
6.完成期限,一个学期完成整个系统,包括程序的编写以及最终的调试,测试阶段。
键入,当玩家玩到一定的分数时(例如是100)关卡加一,变为第二关,同时,蛇前进速度相应增加一个等级,障碍物的设置也变化,这样就实现了不同关卡,不同速度的贪吃蛇,从而增加了游戏的难度。
蛇:
1、能够实现贪吃蛇自动前线移动,也就是贪吃蛇能够“活动”的外观效果,根据相同的时间间隔,每一次将贪吃蛇自身的蛇头向前移动一个小格子,同时蛇尾向前移动一个小格子,移动方向为贪吃蛇行走的方向。
2、每当一个食物时,蛇长度增加一格
3、蛇头碰到自身时则游戏结束
4、通过键盘来控制蛇的移动
食物:
1、每当蛇吃到食物时,重置食物
2、吃到特定食物时,蛇的长度能够缩短
边界和障碍物:
1、遇到边界和障碍物则游戏终止
成绩统计:
1、当贪吃蛇吃到果实时,玩家的分数就应该随着吃到的果实而增加,增加的规则就是每一个吃到一个食物则乘以10得到分数。
2、能够与历史成绩进行比较,显示高分排行榜
输入与输出:
1、通过键盘选择障碍物关卡数
2、通过键盘选择蛇的速度
3、显示游戏指南
4、能够即时显示当次游戏的关卡数及游戏分数
5、显示游戏界面
贪吃蛇的总体功能图
1.3小组成员分工
小组成员
XXX
XXX
XXX
XXX
功能分析
小组讨论,确定项目题目和基本方案,
组员提出想实现的功能,分析可行性
讨论建议
整理方案
分工安排
接口实现
成绩,特效
蛇的基本功能
障碍物功能
边界问题
关卡递进
最初源代码
添加注释
基本功能
添加边界
成绩存档
食物重置
特殊效果
障碍物
关卡功能
汇总整理
测试改进
1总体设计报告
考虑到要实现的功能太多,所以宜采用模块化设计,把功能分块(在介绍功能时已经按这个方式介绍了),然后设计各个模块之间参数的传递,衔接起来,最后实现每个功能的算法。
首先我们定义了所需要的数据类型
1.Node(结点)型定义
用来作为蛇的头,身,尾的数据类型以及障碍物的数据类型
每个成员的设计已在注释中注明,其中蛇和障碍物均用链表结构表示
structNode
{
intx;/*蛇某一节的横坐标*/
inty;/*蛇某一节的纵坐标*/
structNode*pre;/*蛇某一节的前驱结点*/
structNode*next;/*蛇某一节的后继结点*/
};
2.Food(食物)型定义
用来储存食物的横纵坐标及显示的字母
3.Player(玩家)型定义
储存玩家的姓名和成绩
2.1函数分块
总的来说,我们把所有功能分成了以下几个大块:
main
snake
food
barrierandblock
grade
共五个大块,分别实现相应功能,见名知意,各块的功能显而易见,依次实现主要的运行(main),蛇的控制、移动、增减(snake),食物的重置(food),障碍物的设置及边界的判断(barrierandblock),成绩的统计与存档(grade)
每个模块均存在一个CPP中,截图如下:
2.2接口设计
下面分别介绍每个大块的内部函数接口设计
main:
主函数:
intmain()
其中main函数里定义了游戏必须的一些变量
输入函数:
intinput(char*pname,int*barrierkind)
第一个形参为char*类型,用来接收main函数里面的玩家名字,便于输入赋值,因为要进行写操作修改其值,所以定义成一级指针;第二个形参为障碍物类型,即初始化的障碍物分布,同样要在input里赋值,所以用int*型。
返回值为速度值,是一个整数,游戏通过这个数来控制蛇前进的速度,所以定义为int
屏幕显示函数:
voidscreenshow(intscore,intstage,Node*head,Node*firstbar,Food*food)
要显示当前的分数和关卡,所以传两个整型参数score和stage;又要通过二位数组扫描,根据横纵坐标来看输出“”(空格)还是蛇“■”,或障碍物“※”,或食物,所以要传结构体参数Node*和Food
Snake:
蛇的初始化函数:
voidinitalsnake(int*grade,Node**head,Node**rear)
顺便把成绩也初始化,所以传了个int型参数grade;然后由于要修改main函数中Node*head目标空间的的横纵坐标,所以这里用了一个二级指针,否则,若设计成Node*型,则形参改的值只在该函数有效,对main函数里的head无影响(此处曾调试很久,在5.2.2心得体会里在详细说明)
方向输入函数:
chardirectioninput(charc)
由键盘键入一个值,传回有效值,故返回值类型为char,由主函数传过来而不内部定义时避免输入无效值时出错,所以此处相当于输入无效值则还是原值(内部最后一句为returnc)。
蛇移动函数:
voidsnakeheadmove(charc,Node**head)
传前进的方向,为字母值,用char,头要移动,需要改值,所以用二级指针
添加和删除结点函数:
voidaddpoint(Node**head,Node**rear)
voiddeletepoint(Node**head,Node**rear)
由于用的是双向链表,所以要传头尾两个参数,需改值,故用二级指针
Food:
食物重置函数:
voidfoodreset(charc,Food*food,Node*head,Node*firstbar)
当玩到最后蛇身较长时,重置多次可能还不行,所以会内定为在蛇前进方向的前两个出食物,所以要传前进方向,用char;需改变食物的横纵坐标及显示字母,故第二个参数用一级指针;要判断食物是否重置到蛇身或障碍物上,所以传二者参数,由于只是判断不需要改值,所以一级指针即可
barrierandblock:
障碍物初始化函数:
voidinitalbarrier(intbarrierkind,Node**firstbar,Node**lastbar)
要调用障碍物重置函数voidbarrierset(intbarrierkind,Node**firstbar,Node**lastbar)
,需要主函数里的实参,所以第一个参数用int,便于内部传值调用其他函数;要修改主函数中firstbar和lastbar的目标空间的值,所以用二级指针;
判断出界函数
intBlock(Node*head)
看头部的坐标是否出界,所以只需Node*即可;对判断结果进行记录,返回0或1,所以用int;
障碍物重置函数
voidbarrierset(intbarrierkind,Node**firstbar,Node**lastbar)
接收关卡数,故第一个参数定义为int;要修改主函数中firstbar和lastbar的目标空间的值,所以用二级指针;
判断游戏结束函数:
intGameover(Node*head,Node*firstbar)
需要判断头是否触到障碍物,所以传参数Node*;对判断结果进行记录,返回0或1,所以用int;
Grade:
成绩插入函数:
voidscorecompare(Player*top,Player*player)
把该次的成绩与原来的前十名成绩进行比较,需要记录名字,所以传结构体Player*;
历史成绩复制函数:
voidfileinital(Player*topplayer)
由于要把文件中的历史成绩赋值给主函数的结构体数组,所以传一级指针Player*
成绩存档函数:
voidfile(Player*top)
把排序后的新的TOP10的成绩写入文档,由于是一维数组,所以只能传指针;
参数传递图:
maingradesnake
bolck
注明:
单项箭头的指向为参数传递的方向;
双向箭头说明有传递返回值;
主要采取指针参数改动值,所以很少有返回值;
2详细设计报告
3.1程序结构
程序流程图
3.1.1各种宏定义以及说明
#defineboundary15/*边界定义为15*15*/
#defineN10/*只存取和展示前10名玩家*/
3.1.2主要函数声明如下
intinput(char*,int*);
显示最初的提示界面,实现难度和关卡的选择输入;
voidfoodreset(charc,Food*food,Node*head,Node*firstbar);
实现食物的随机重置;
voidinitalsnake(int*,Node**,Node**);
给蛇头动态分配空间,顺便初始化成绩;
voidinitalbarrier(int,Node**,Node**);
给障碍物初始化空间,同时调用食物重置函数;
voidbarrierset(int,Node**,Node**);
根据现在的关卡信息重置障碍物;
intBlock(Node*head);
判断头是否出界
chardirectioninput(char);
方向控制键入函数;从键盘过去键入值;
voidsnakeheadmove(char,Node**);
根据键入的值执行蛇头移动;
voidaddpoint(Node**,Node**);
吃到食物时增加结点,蛇身增长;
voiddeletepoint(Node**,Node**);
吃到特定食物蛇身变短;
intGameover(Node*,Node*);
判断游戏是否终止;
voidscreenshow(int,int,Node*,Node*,Food*);
显示游戏界面;
voidscorecompare(structPlayer*,structPlayer*);
每个玩家游戏结束即时排序插入高分榜;
voidfileinital(Player*);
文件初始化;
voidfile(Player*);
成绩存档;
3.2算法流程
3.2.1main模块的函数算法:
intmain()
{
//初始化信息,调用文件初始化函数;
while
(1)//玩家循环(外循环)
{
定义必要的变量;
初始化该玩家信息(姓名“XXX”,0分);
清屏;
调用输入函数,返回速度值;
调用蛇和障碍物的初始化函数;
利用time函数产生随机数;
While
(1)//游戏的进程循环(内循环)
{
if(蛇头吃到食物)
{
(字母“o”)?
(减短):
(增长);
调用食物重置函数;
玩家成绩增加;
}
if(有键盘输入)
{调用方向输入函数;}
pt=rear;
while(pt不指向蛇头)
{将蛇头后面的结点分别等于前驱结点;}//相当于前移
调用蛇头移动函数;
if(游戏过关)
{
速度延时减(20毫秒*关卡等级),直到为零;
释放障碍物空间;
重置障碍物;
}
if(游戏结束)
{
输出鼓励的话;
跳出本次循环;
}
调用屏幕显示函数;
调用Sleep函数延时;
}//内循环结束
释放蛇头空间;
释放障碍物空间;
调用分数插入函数;
调用文件存档函数;
延时一秒;
清屏;
显示英雄榜;
判断继续游戏还是退出;
}//外循环结束
return0;
}
intinput(char*pname,int*barrierkind)
{
定义速度变量;
printf("欢迎来到贪吃蛇游戏");
printf("请输入名字");
scanf("%s",pname);
………………
(后面是类似的输入障碍物类型和难度)
returnspeed*50;
}
voidscreenshow(intscore,intstage,Node*head,Node*firstbar,Food*food)
{
定义要用的变量;
清屏;
输出提示游戏规则的话;
for(i=1;i printf("—"); printf("\n");//上边界输出 for(i=0;i { printf("|"); for(j=1;j { if(是蛇的坐标) { 是蛇头,printf("■"); 是蛇身,printf("□"); } if(障碍物坐标) {printf("※");} if(食物坐标) {显示食物的字母;} 都不是则printf(“”); }//j循环完 printf("|"); putchar('\n'); }//i的循环完 printf(""); for(i=1;i printf("—"); printf("\n"); printf("现在的关卡等级: %d\n当前您的成绩为: %d\n",stage,score); } 3.2.2snake模块的函数算法: voidinitalsnake(int*grade,Node**head,Node**rear) { 分配蛇头初始空间; 初始化蛇头坐标; } chardirectioninput(charc) { charc1='d'; c1=getch(); if(c1==27)/*当输入的是Esc时,直接退出*/ exit (1); /*判断输入是否有效,不能逆向前进*/ if(c! ='d'&&c1=='a') c=c1; elseif(c! ='a'&&c1=='d') c=c1; elseif(c! ='w'&&c1=='s') c=c1; elseif(c! ='s'&&c1=='w') c=c1; return(c); } voidsnakeheadmove(charc,Node**head) { switch(c) { case'd': (*head)->y+=1; if((*head)->y>=boundary) (*head)->y-=boundary; break; …………………… (后面几个同理) } voidaddpoint(Node**head,Node**rear) { structNode*pt,*p; p=(structNode*)malloc(sizeof(structNode)); pt=*head;/*分配结点p的地址空间并将其指向蛇头结点*/ while(pt->next! =NULL) pt=pt->next;/*当p的next域不为空时将p指向下一个结点*/ p->pre=pt; pt->next=p; p->next=NULL; *rear=p;/*将p结点插到蛇链表的末尾,后插法*/ } voiddeletepoint(Node**head,Node**rear) { (*head)->next=*rear; (*rear)->pre=*head;//删除所有节点,只留首尾 } 3.2.3food模块的函数算法: voidfoodreset(charc,Food*food,Node*head,Node*firstbar) { 定义变量; 重置食物; for(t=0,flag=1;flag==1;t++) { for(pt=head;pt! =NULL;pt=pt->next) { if(食物坐标等于蛇身坐标) { 重置食物; break; } } for(pt=firstbar;pt! =NULL;pt=pt->next) { if(食物坐标等于蛇身坐标) { 重置食物; break; } } } if(t>5)/*当5次重置,食物坐标均等于蛇的坐标,则将食物置于蛇的前进方向的前一格*/ { switch(c) { case'd': food->x=head->x+1; food->y=head->y; if(food->x>=boundary) food->x-=boundary; break; ……………… (后面的选项类似) } } } 3.2.4blockandbarrier模块函数算法: voidinitalbarrier(intbarrierkind,Node**firstbar,Node**lastbar) { *firstbar=newNode[5];//用new运算动态分配空间 (*firstbar)->x=10;//设置初始坐标 (*firstbar)->y=10; (*firstbar)->pre=NULL; (*firstbar)->next=NULL; *lastbar=*firstbar; barrierset(barrierkind,firstbar,lastbar);//调用障碍物设置函数 } intBlock(Node*head) { if(蛇头坐标出界) return1; elsereturn0; } voidbarrierset(intbarrierkind,Node**firstbar,Node**lastbar) { 定义变量; for(i=0;i<5;i++)//用后插法一次插入五个障碍物 { p=*firstbar+i; pt=*firstbar; while(pt->next! =NULL) pt=pt->next; p->pre=pt; pt->next=p; p->next=NULL; *lastbar=p; } switch(barrierkind)//给障碍物赋坐标值 { case1: (*lastbar)->x=(*lastbar)->pre->x-1; (*lastbar)->y=(*lastbar)->pre->y; break; case2: (*lastbar)->x=(*lastbar)->pre->x; (*lastbar)->y=(*lastbar)->pre->y-1; break; default: (*lastbar)->x=(*lastbar)->pre->x-1; (*lastbar)->y=(*lastbar)->pre->y-1; } } intGameover(Node*head,Node*firstbar) { 定义变量; for(pt=head->next;pt! =NULL;pt=pt->next) { if(蛇头坐标等于蛇身的坐标) return1; } for(pt=firstbar;pt! =NULL;pt=pt->next) { if(蛇头坐标等于障碍物坐标) return1; } if(Block(head))//调用Block函数 { return1; } return0; } 3.2.5grade模块函数的算法: voidscorecompare(Player*top,Player*player) { 定义变量; 遍历top数组比较大小,标记下player的成绩的位置; 从后往前遍历,把player的信息插入到标记的位置; (详细代码见源代码,此处只写算法和思路) } voidfileinital(Player*topplayer) { FILE*fp;//定义结构体FILE型的指针 if(打开的只读文件为空) { if(打开的只写文件为空)//此处
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 贪吃 项目 报告