• 633.50 KB
  • 55页

贪吃蛇项目报告.doc

  • 55页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'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.完成期限,一个学期完成整个系统,包括程序的编写以及最终的调试,测试阶段。 1.1项目目标1熟悉函数的调用与程序的模块化设计,加深对所学知识的理解2加强自学能力,遇到不了解的函数或者方法,通过图书及网络资源学习,提高学习能力3完成贪吃蛇游戏,通过小项目来检验一学期的学习效果,增加学习兴趣1.2功能描述该游戏在继承传统同类游戏规则的基础上,我们添加了我们自己的想法与功能,设计如下:游戏规则包括蛇的运动范围、蛇的生命周期问题、分数统计、关卡判断。其中蛇的运动范围是一个15*15的数组呢,蛇运动的地图抽象成为一个15*15的二维整形数组,每个数组值代表一个小方块的坐标值,这样,蛇只能在规定好的二维数组内运动当蛇遇到数组左右边界值(我们在这里抽象成为上、下、左、右四个边界,其中上边界坐标值中纵坐标都是0,横坐标任意,下边界为纵坐标是15,同理横坐标不变,左边界为横坐标为0,纵坐标任意,同理右边界为横坐标为15,纵坐标任意)时,宣告蛇生命周期结束(上下边界不限定),贪吃蛇死亡,这个是第一个规则;另外,当蛇自己吃到自己身体的某一部分时,也宣告游戏结束,在程序里通过循环判断蛇头下一个前进方向的节点是不是蛇身上的某一部分节点即可,如果是那么蛇死亡,否则继续运行游戏。分数统计算法的思想是每次蛇吃到一个果实时,相加的分数为一个定值10来记录分数,这样可以随着游戏难度的增加,分数值也随之增多。关卡功能设置通过与分数相关联而体现的,初始化游戏分数为0,关卡障碍物选择由玩家键入,当玩家玩到一定的分数时(例如是100 )关卡加一,变为第二关,同时,蛇前进速度相应增加一个等级,障碍物的设置也变化,这样就实现了不同关卡,不同速度的贪吃蛇,从而增加了游戏的难度。蛇:1、能够实现贪吃蛇自动前线移动,也就是贪吃蛇能够“活动”的外观效果,根据相同的时间间隔,每一次将贪吃蛇自身的蛇头向前移动一个小格子,同时蛇尾向前移动一个小格子,移动方向为贪吃蛇行走的方向。2、每当一个食物时,蛇长度增加一格3、蛇头碰到自身时则游戏结束4、通过键盘来控制蛇的移动食物:1、每当蛇吃到食物时,重置食物2、吃到特定食物时,蛇的长度能够缩短边界和障碍物:1、遇到边界和障碍物则游戏终止成绩统计:1、当贪吃蛇吃到果实时,玩家的分数就应该随着吃到的果实而增加,增加的规则就是每一个吃到一个食物则乘以10得到分数。2、能够与历史成绩进行比较,显示高分排行榜输入与输出:1、通过键盘选择障碍物关卡数2、通过键盘选择蛇的速度3、显示游戏指南4、能够即时显示当次游戏的关卡数及游戏分数5、显示游戏界面 贪吃蛇的总体功能图 1.3小组成员分工小组成员XXXXXXXXXXXX功能分析小组讨论,确定项目题目和基本方案,组员提出想实现的功能,分析可行性讨论建议整理方案分工安排接口实现成绩,特效蛇的基本功能障碍物功能边界问题关卡递进最初源代码添加注释基本功能添加边界成绩存档食物重置特殊效果障碍物关卡功能汇总整理测试改进 1总体设计报告考虑到要实现的功能太多,所以宜采用模块化设计,把功能分块(在介绍功能时已经按这个方式介绍了),然后设计各个模块之间参数的传递,衔接起来,最后实现每个功能的算法。首先我们定义了所需要的数据类型1.Node(结点)型定义用来作为蛇的头,身,尾的数据类型以及障碍物的数据类型每个成员的设计已在注释中注明,其中蛇和障碍物均用链表结构表示structNode{intx;/*蛇某一节的横坐标*/inty;/*蛇某一节的纵坐标*/structNode*pre;/*蛇某一节的前驱结点*/structNode*next;/*蛇某一节的后继结点*/};2.Food(食物)型定义用来储存食物的横纵坐标及显示的字母3.Player(玩家)型定义储存玩家的姓名和成绩 2.1函数分块总的来说,我们把所有功能分成了以下几个大块:mainsnakefoodbarrierandblockgrade共五个大块,分别实现相应功能,见名知意,各块的功能显而易见,依次实现主要的运行(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*和FoodSnake:蛇的初始化函数: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的成绩写入文档,由于是一维数组,所以只能传指针;参数传递图:maingradesnakebolckfileinitalInputinitalsnakeinitalbarrierderectioninputBlocksnakemovemainbarriersetaddpointgameoverdeletepointscorecomparefilescreenshow 注明:单项箭头的指向为参数传递的方向;双向箭头说明有传递返回值;主要采取指针参数改动值,所以很少有返回值;1详细设计报告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;iy+=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(打开的只写文件为空)//此处一般不为空,因为打开只写没有的话会自动创建{提示运行错误;exit(0);}Playerinital[N];//定义结构体Pinti;for(i=0;ix=rand()%(boundary);看似不错,但有0这个隐患,直接加1的话又会超出上界,最后我想出了这样处理:food->x=rand()%(boundary-2)+1;即余数的最大值比原来小二,而加一的话下届又加一了,所以不会出现食物BUG了。这是最后一天调试出来了,很幸运。1.1.1总结这次项目我真的学到了很多东西,很多功能我基本自己独立编写的,大大提高了我的C语言编写能力,而且我还学习了链表和文件储存。其实有个小秘密就是,这个代码我们改了很久,分几个阶段。1.找到源代码时什么附加功能都没有,而且一个主函数包罗所有信息,很庞杂,于是我花了一个晚上把找的代码看懂并根据功能剥离出各个函数;2.当时对参数掌握的不是特别好,所以就把那几个结构体指针的变量全部定义为外部全局变量;在各分CPP里面用extern来说明;同时,策划并添加我们自己设计的一些功能,如关卡,障碍物,吃“o”变短,成绩统计等。3.后来觉得全局变量影响了函数的独立性,所以我又一个个把函数根据功能重新设计接口,从而去掉了全局变量,感觉改的比较成功。备注:闪屏问题我们还没解决,我觉得只能通过图形界面来实现,我暑假会尽量自学图形界面,尽量实现。(完) 特别鸣谢老师一学期来的无私敬业!二项目代码附原代码:头文件:game.h#include"stdafx.h"#include#include#include#include #include#defineboundary15#defineN10structNode{intx;/*蛇某一节的横坐标*/inty;/*蛇某一节的纵坐标*/structNode*pre;/*蛇某一节的前驱结点*/structNode*next;/*蛇某一节的后继结点*/};/*蛇的某一节*/structFood{intx;/*食物的横坐标*/inty;/*食物的纵坐标*/charc;/*用字母表示食物*/};/*食物*/structPlayer{charname[20];/*玩家姓名*/intgrade;/*成绩*/}; intinput(char*,int*);//输入voidfoodreset(char,Food*food,Node*head,Node*firstbar);//食物重置voidinitalsnake(int*,Node**,Node**);//蛇头重置voidinitalbarrier(int,Node**,Node**);//障碍物初始化空间intBlock(Node*head);//判断出界chardirectioninput(char);//方向输入voidsnakeheadmove(char,Node**);//蛇头移动voidaddpoint(Node**,Node**);//增加结点intGameover(Node*,Node*);//游戏结束条件voidscreenshow(int,int,Node*,Node*,Food*);//屏幕显示voidscorecompare(structPlayer*,structPlayer*);//成绩排序voidfileinital(Player*);//初始化文件及提取成绩voidfile(Player*);//文件储存成绩voidbarrierset(int,Node**,Node**);//障碍物重置voiddeletepoint(Node**,Node**);//删除结点//头尾和临时结点的结构体指针源文件:main.cpp#include"stdafx.h"#include"game.h"intmain(){structNode*firstbar=NULL,*lastbar=NULL,*pb;/*障碍物的首尾结点,为Node*型*/structFoodfood={2,2,"A"};/*食物,为Food型*/structNode*head=NULL,*p,*rear=NULL,*pt;/*蛇的头尾,为Node*型*/inta[boundary][boundary]={0};intnumber=0,speed=0;structPlayertopplayer[N]; fileinital(topplayer);while(1){charc="d";/*d为蛇右进的控制键,即默认为向右前进*/intgameover=0,STAGE=1,flag=0;//定义游戏结束,关卡,标记符变量intbarrierkind=0;//定义障碍物选择变量structPlayerplayer={"xxx",0};//初始化此次玩家信息system("cls");//清屏speed=input(player.name,&barrierkind);//调用输入函数,返回速度值initalsnake(&player.grade,&head,&rear);//调用蛇初始化函数initalbarrier(barrierkind,&firstbar,&lastbar);//初始化障碍物srand((unsigned)time(NULL));/*利用time函数产生随机数*/while(1){if((food.x==head->x)&&(food.y==head->y))/*当蛇头吃到食物*/{if(food.c=="O")deletepoint(&head,&rear);else;addpoint(&head,&rear);foodreset(c,&food,head,firstbar);/*调用食物重置*/player.grade+=STAGE*10;} if(kbhit())/*用kbhit()函数判断是否有键盘输入*/{c=directioninput(c);/*调用方向输入函数*/}pt=rear;/*将pt指向蛇尾结点*/while(pt!=head)/*当pt不指向蛇头时,将蛇头后面的结点坐标分别等于前驱结点,相当于蛇向前移一格*/{pt->x=pt->pre->x;pt->y=pt->pre->y;pt=pt->pre;}snakeheadmove(c,&head);/*改变蛇头坐标*//*判断游戏过关或失败*/inttempSTAGE=STAGE;/如果升级,增加难度STAGE=player.grade/100+1;if(tempSTAGE-STAGE){speed=(speed-STAGE*10)>0?(speed-STAGE*10):0;delete[]firstbar;initalbarrier(STAGE,&firstbar,&lastbar);}else; if(gameover=Gameover(head,firstbar)){printf("gameover!n胜败乃兵家常事,大侠请从新来过n");/*当结束游戏时,退出本循环*/break;}screenshow(player.grade,STAGE,head,firstbar,&food);/*屏幕显示*/Sleep(speed);/*控制游戏速度*/}//内循环free(head);delete[]firstbar;scorecompare(topplayer,&player);file(topplayer);Sleep(999);//延时一秒system("cls");printf("高分排行榜n玩家姓名t游戏得分n");for(number=0;numbernext){if(i==pt->x&&j==pt->y){if(pt==head)printf("■");elseprintf("□");flag1=1;break;}}for(flag2=0,pt=firstbar;pt!=NULL;pt=pt->next){if(i==pt->x&&j==pt->y){ printf("※");flag2=1;break;}}if(flag1==0&&flag2==0){if(i==food->x&&j==food->y){putchar(food->c);putchar(food->c);continue;}printf("");}}//j的括弧printf("│");putchar("n");}//i的括弧printf("");for(i=1;ix=2;(*head)->y=2;(*head)->pre=NULL;(*head)->next=NULL;*rear=*head;}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;case"a":(*head)->y-=1;if((*head)->y<0)(*head)->y+=boundary;break;case"w":(*head)->x-=1;if((*head)->x<0)(*head)->x+=boundary;break;case"s":(*head)->x+=1;if((*head)->x>=boundary)(*head)->x-=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;}food.cpp#include"stdafx.h"#include"game.h"voidfoodreset(charc,Food*food,Node*head,Node*firstbar){intflag;intt;structNode*pt;food->x=rand()%(boundary-2)+1;food->y=rand()%(boundary-2)+1;food->c=65+rand()%26;for(t=0,flag=1;flag==1;t++)/*表示食物已经重置*/{if(t>5)break; flag=0;for(pt=head;pt!=NULL;pt=pt->next){if(food->x==pt->x&&food->y==pt->y){flag=1;food->x=rand()%(boundary-2)+1;food->y=rand()%(boundary-2)+1;break;}}for(pt=firstbar;pt!=NULL;pt=pt->next){if(food->x==pt->x&&food->y==pt->y){flag=1;food->x=rand()%(boundary-2)+1;food->y=rand()%(boundary-2)+1;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;case"a":food->x=head->x-1;food->y=head->y;if(food->x<0)food->x+=boundary;break;case"w":food->x=head->x;food->y=head->y+1;if(food->y>=boundary)food->y-=boundary;break;case"s":food->x=head->x;food->y=head->y-1;if(food->y<0)food->y+=boundary;break;}}}blockandbarrier.cpp#include"stdafx.h" #include"game.h"voidinitalbarrier(intbarrierkind,Node**firstbar,Node**lastbar){*firstbar=newNode[5];(*firstbar)->x=10;(*firstbar)->y=10;(*firstbar)->pre=NULL;(*firstbar)->next=NULL;*lastbar=*firstbar;barrierset(barrierkind,firstbar,lastbar);}intBlock(Node*head)//判断出界{if((head->x<0)||(head->x>boundary)||(head->y<1)||(head->y>boundary))return1;elsereturn0;}voidbarrierset(intbarrierkind,Node**firstbar,Node**lastbar){inti;structNode*pt,*p;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%3){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){structNode*pt;for(pt=head->next;pt!=NULL;pt=pt->next){if(head->x==pt->x&&head->y==pt->y){return1;} }for(pt=firstbar;pt!=NULL;pt=pt->next){if(head->x==pt->x&&head->y==pt->y){return1;}}if(Block(head)){return1;}return0;} grade.cpp#include"stdafx.h"#include"game.h"voidscorecompare(Player*top,Player*player){inti,mark=0;for(i=0;i<10;i++){if((top+i)->gradegrade){mark=i;break;}}for(i=9;i>mark;i--){top[i]=top[i-1];}top[mark]=*player;}voidfileinital(Player*topplayer){FILE*fp;if((fp=fopen("f1.txt","r"))==NULL){if((fp=fopen("f1.txt","w"))==NULL){printf("运行错误n");exit(0); }Playerinital[N];inti;for(i=0;i