XXX班贪吃蛇小组XXXXXXXXXXXX—1—C语言项目设计报告——贪吃蛇游戏课程:标准C语言指导老师:XXX项目:贪吃蛇游戏班级:XXXX班组员:XXX、XXX、XXX、XXX姓名:XXX学号:XXXXXXX日期:2012/7/7XXX班贪吃蛇小组XXXXXXXXXXXX—2—目录一.项目开发文档…………………………(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)XXX班贪吃蛇小组XXXXXXXXXXXX—3—贪吃蛇游戏一项目开发文档1项目基本分析在我进行编写贪吃蛇游戏之前,我所做的必须是可行性分析,因为一旦进行贪吃蛇游戏项目的开发,就必须保证自己在规定的时间内能够独立的完整整个程序的所有功能,而且必须是最优的,因此,在开发贪吃蛇游戏之前,我必须要做的是可行性分析。通过查找相关文档和技术支持,了解了VS环境下的开发过程,熟悉了C语言的开发技巧,通过以下几个方面,进行可行性分析:1.参考文献:《贪吃蛇游戏用户描述文档》、在网上找了相关源代码,确定自己能够在自己能力范围内开发出这个贪吃蛇游戏项目。2.功能要求:在进行整个项目开发之前,我必须要做的就是确定贪吃蛇游戏的主要功能,必须明确贪吃蛇游戏的功能,因为要进行游戏功能可行性分析,经过自己的查阅相关资料,我确定了贪吃蛇游戏的具体功能,详见后续部分详细设计。3.性能需求:必须保证自己开发的贪吃蛇游戏能够整体尽可能做到高效快速,不占用大量的使用资源,因为我做的是一个应用窗体控制台的游戏开发项目,必须要考虑资源使用情况,要求尽可能少用资源,在有限的资源范围内实现最大的可利用价值。4.运行环境:VS2010上编写并进行调试,经过安装软件,确定可以进行项目程序的编写。5.界面要求:采用Win7应用窗体标准界面,只需要使用键盘。6.完成期限,一个学期完成整个系统,包括程序的编写以及最终的调试,测试阶段。XXX班贪吃蛇小组XXXXXXXXXXXX—4—1.1项目目标1熟悉函数的调用与程序的模块化设计,加深对所学知识的理解2加强自学能力,遇到不了解的函数或者方法,通过图书及网络资源学习,提高学习能力3完成贪吃蛇游戏,通过小项目来检验一学期的学习效果,增加学习兴趣1.2功能描述该游戏在继承传统同类游戏规则的基础上,我们添加了我们自己的想法与功能,设计如下:游戏规则包括蛇的运动范围、蛇的生命周期问题、分数统计、关卡判断。其中蛇的运动范围是一个15*15的数组呢,蛇运动的地图抽象成为一个15*15的二维整形数组,每个数组值代表一个小方块的坐标值,这样,蛇只能在规定好的二维数组内运动当蛇遇到数组左右边界值(我们在这里抽象成为上、下、左、右四个边界,其中上边界坐标值中纵坐标都是0,横坐标任意,下边界为纵坐标是15,同理横坐标不变,左边界为横坐标为0,纵坐标任意,同理右边界为横坐标为15,纵坐标任意)时,宣告蛇生命周期结束(上下边界不限定),贪吃蛇死亡,这个是第一个规则;另外,当蛇自己吃到自己身体的某一部分时,也宣告游戏结束,在程序里通过循环判断蛇头下一个前进方向的节点是不是蛇身上的某一部分节点即可,如果是那么蛇死亡,否则继续运行游戏。分数统计算法的思想是每次蛇吃到一个果实时,相加的分数为一个定值10来记录分数,这样可以随着游戏难度的增加,分数值也随之增多。关卡功能设置通过与分数相关联而体现的,初始化游戏分数为0,关卡障碍物选择由玩家键入,当玩家玩到一定的分数时(例如是100)关卡加一,变为第二关,同时,蛇前进速XXX班贪吃蛇小组XXXXXXXXXXXX—5—度相应增加一个等级,障碍物的设置也变化,这样就实现了不同关卡,不同速度的贪吃蛇,从而增加了游戏的难度。蛇:1、能够实现贪吃蛇自动前线移动,也就是贪吃蛇能够“活动”的外观效果,根据相同的时间间隔,每一次将贪吃蛇自身的蛇头向前移动一个小格子,同时蛇尾向前移动一个小格子,移动方向为贪吃蛇行走的方向。2、每当一个食物时,蛇长度增加一格3、蛇头碰到自身时则游戏结束4、通过键盘来控制蛇的移动食物:1、每当蛇吃到食物时,重置食物2、吃到特定食物时,蛇的长度能够缩短边界和障碍物:1、遇到边界和障碍物则游戏终止成绩统计:1、当贪吃蛇吃到果实时,玩家的分数就应该随着吃到的果实而增加,增加的规则就是每一个吃到一个食物则乘以10得到分数。2、能够与历史成绩进行比较,显示高分排行榜输入与输出:1、通过键盘选择障碍物关卡数2、通过键盘选择蛇的速度3、显示游戏指南4、能够即时显示当次游戏的关卡数及游戏分数5、显示游戏界面XXX班贪吃蛇小组XXXXXXXXXXXX—6—贪吃蛇的总体功能图XXX班贪吃蛇小组XXXXXXXXXXXX—7—1.3小组成员分工小组成员XXXXXXXXXXXX功能分析小组讨论,确定项目题目和基本方案,组员提出想实现的功能,分析可行性讨论建议整理方案分工安排接口实现成绩,特效蛇的基本功能障碍物功能边界问题关卡递进最初源代码添加注释基本功能添加边界成绩存档食物重置特殊效果障碍物关卡功能汇总整理测试改进XXX班贪吃蛇小组XXXXXXXXXXXX—8—2总体设计报告考虑到要实现的功能太多,所以宜采用模块化设计,把功能分块(在介绍功能时已经按这个方式介绍了),然后设计各个模块之间参数的传递,衔接起来,最后实现每个功能的算法。首先我们定义了所需要的数据类型1.Node(结点)型定义用来作为蛇的头,身,尾的数据类型以及障碍物的数据类型每个成员的设计已在注释中注明,其中蛇和障碍物均用链表结构表示structNode{intx;/*蛇某一节的横坐标*/inty;/*蛇某一节的纵坐标*/structNode*pre;/*蛇某一节的前驱结点*/structNode*next;/*蛇某一节的后继结点*/};2.Food(食物)型定义用来储存食物的横纵坐标及显示的字母3.Player(玩家)型定义储存玩家的姓名和成绩XXX班贪吃蛇小组XXXXXXXXXXXX—9—2.1函数分块总的来说,我们把所有功能分成了以下几个大块:mainsnakefoodbarrierandblockgrade共五个大块,分别实现相应功能,见名知意,各块的功能显而易见,依次实现主要的运行(main),蛇的控制、移动、增减(snake),食物的重置(food),障碍物的设置及边界的判断(barrierandblock),成绩的统计与存档(grade)每个模块均存在一个CPP中,截图如下:2.2接口设计下面分别介绍每个大块的内部函数接口设计main:XXX班贪吃蛇小组XXXXXXXXXXXX—10—主函数:intmain()其中main函数里定义了游戏必须的一些变量输入函数:intinput(char*pname,int*barrierkind)第一个形参为char*类型,用来接收main函数里面的玩家名字,便于输入赋值,因为要进行写操作修改其值,所以定义成一级指针;第二个形参为障碍物类型,即初始化的障碍物分布,同样要在input里赋值,所以用int*型。返回值为速度值,是一个整数,游戏通过这个数来控制蛇前进的速度,所以定义为int屏幕显示函数:voidscreenshow(intscore,intstage,Node*head,Node*firstbar,Food*food)要显示当前的分数和关卡,所以传两个整型参数score和stage;又要通过二位数组扫描,根据横纵坐标来看输出“”(空格)还是蛇“■”,或障碍物“※”,或食物,所以要传结构体参数Node*和FoodSnake:蛇的初始化函数:voidinitalsnake(int*grade,Node**head,Node**rear)顺便把成绩也初始化,所以传了个int型参数grade;然后由于要修改main函数中Node*head目标空间的的横纵坐标,所以这里用了一个二级指针,否则,若设计XXX班贪吃蛇小组XXXXXXXXXXXX—11—成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;需改变食物的横纵坐标及显示字母,故第二个参数用一级指针;要判断食物是否重置到蛇身或障碍物上,所以传二者参数,由于只是判断不需要改值,所以一级指针即可XXX班贪吃蛇小组XXXXXXXXXXXX—12—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*;XXX班贪吃蛇小组XXXXXXXXXXXX—13—历史成绩复制函数:voidfileinital(Player*topplayer)由于要把文件中的历史成绩赋值给主函数的结构体数组,所以传一级指针Player*成绩存档函数:voidfile(Player*top)把排序后的新的TOP10的成绩写入文档,由于是一维数组,所以只能传指针;参数传递图:maingradesnakebolck注明:单项箭头的指向为参数传递的方