计算机实习报告
姓名: 向睿
班级: 07班
学号: 10210197
小班序号:11
指导老师:方莉
题目:贪吃蛇
邮箱:hgjngh123@126.com
小游戏“贪吃蛇”实验报告
一.功能说明
1.1总体功能说明
贪吃蛇的小游戏,控制蛇来吃苹果;
随着吃掉的苹果个数的增加分数会增加,
但蛇身也会变长;
如果蛇撞到墙壁或者自己的话就会死掉结束游戏。
1.2用户界面
选择游戏等级,等级越高速度越快;
游戏界面;
死后选择是否继续游戏;
1.3使用方法
进入先选择游戏等级,1-9个等级对应的速度依次增大并且获得的分也依次增大。
通过上下左右控制蛇的运动方向,可选择1-9共9个等级,蛇会有不同的速度和分数递加。
死亡后按Y或N来继续或结束游戏
二.程序设计说明
2.1 总体设计框架
2.2 关键算法描述
1.蛇的运动算法:
将蛇的前一节坐标赋给后一节,最后一节消去前一节。
textout(handle,x[lenth-1],y[lenth-1],wColors,1," ");
for(int n=lenth-1;n>0;n--)
{
x[n]=x[n-1];
y[n]=y[n-1];
}
y[0]++;
textout(handle,x[1],y[1],wColors,1,"●");
textout(handle,x[0],y[0],wColors,1,"◆");
2.蛇的死亡算法:
即蛇头不与任何一个蛇身坐标相重合
int right=0;
for(int i=1;i<lenth;i++) //判断是否死掉
right=(right||(x[i]==x[0]&&y[i]==y[0])); //若蛇头与任意一节不重合则right值为0;
3.蛇头坐标不与边框重合即撞墙的判断。
4转弯算法:
Int ch;
ch=_getch();
switch(ch)
{
case 72:
case 80:
case 75:
case 77:
default:;
2.3 程序设计的难点和关键点
1.蛇的运动算法
2.蛇不能反向运动
3.音乐和音效的插入
2.4 调试的方法
1.采用坐标赋值运算,将前一个坐标的值赋给后一个,实现传递
textout(handle,x[lenth-1],y[lenth-1],wColors,1," ");
for(int n=lenth-1;n>0;n--)
{
x[n]=x[n-1];
y[n]=y[n-1];
}
y[0]++;
textout(handle,x[1],y[1],wColors,1,"●");
textout(handle,x[0],y[0],wColors,1,"◆");
2.加入俩次判断:每次用一个临时变量来记录之前的按键再用SWITCH语句来判断是否方向相反。
if(_kbhit()) //检测按键以控制蛇头
{
int ch;
ch=_getch();
switch(tempch) //记录上次按键并判断是否按相反方向运动
{ //如果方向相反则按原方向
case 72:
{if(ch==80)
ch=72;
break;}
case 80:
{if(ch==72)
ch=80;
break;}
case 75:
{if(ch==77)
ch=75;
break;}
case 77:
{if(ch==75)
ch=77;
break;}
default:;
}
switch(ch) //控制蛇头的方向
{
case 72: //蛇头向上
case 80: //蛇头向下运动
case 75: //蛇头向左运动
case 77: //蛇头向右运动
3.上网搜索相关方法,采用了多线程和PlaySound函数来播放
DWORD WINAPI Music1( LPVOID lpParam ) //多线程控制音乐
{
PlaySound( "E:\\C++保存目录\\summer\\summer\\Debug\\WA074.wav",0,NULL);
return 0;
}
HANDLE hThread;
hThread = CreateThread(NULL,0,Music1,NULL,0,NULL);
2.5 程序性能评价
优点:能够顺利地进行游戏,
设有最高分显示,
有背景音乐,关卡。
缺点:界面不够美观,
不能加入与鼠标有关的操作
三.心得体会
这次暑期实习我的贪吃蛇算是比较顺利的完成了,但期间不乏一些波折。
最开始遇到的问题便是采用一个什么模型来完成整条蛇的运动。最开始我使用类似于滚动字幕的方法先让蛇能直线运动了,但后来发现如此蛇无法转弯,于是放弃了这种模型。之后采用控制蛇头和蛇尾的左边,通过擦去蛇尾补至蛇尾来进行转弯;但是这种方法在多次转弯的时候依旧麻烦,假如说蛇身一共N节,我则需要使蛇尾的运动始终慢蛇头N步;于是我想到了将蛇头的坐标赋N次值后传递到蛇尾。后来就改进设出一跳蛇每一节的坐标,前一节的坐标赋给后一节,这与赋N次值得方法原理是相同的。如此便完成了蛇的基本运动。
接下来是解决蛇回头的问题,这个问题本来我看起来觉得比较简单,但做起来出现了不小的问题。首先我解决这问题的方法我想到的很快:设置一个临时变量来存储上一次的运动方向,与这一次检测到的按键方向进行运算,如果俩次运动方向相反则这次按键值等于原方向。但我忽略了一个问题,上下左右键是双值按键,我采用俩次按键值相加等于152来判定运动方向相反就出现了问题,而且这个问题存在了很长时间也没找到哪出了错。后来我新建了一个TEST的程序尝试测试这个方法,发现输出的值都是俩个,另一个都是224。于是我发现了问题所在。之后经过尝试我在循环之前加了一个SWITCH(TEMPCH)的判定才解决了这个蛇回头的问题。
然后来写出现苹果的程序。这个比较好解决,通过产生俩个随机数来作为苹果的坐标,但是这样苹果就有可能出现在蛇身上,这是游戏中不应该出现的情况。于是我进行了进一步的判断,如果苹果出现在蛇身上就立刻被蛇身覆盖,并立刻出现另一个苹果。这样就解决了这个问题,但是微有瑕疵的地方就是程序判断需要时间,如果苹果出现在蛇身上还是会在蛇身上看到苹果闪一下才消失。
既然有了苹果,蛇就应该在吃掉后变长。这个程序好设计。我设置了一个GETLONG()函数,将蛇的长度设为LENTH,然后每吃一个苹果LENTH就自加1,同时调用一对数组元素来记录尾巴的位置,并输出图形作为新的尾巴,于是我的贪吃蛇就能正常的长大了。
之后来写蛇死亡的判定:即蛇撞到自己或者撞到边框。撞到边框很好判定,即蛇头的横坐标或者纵坐标与边框相同。而在判定蛇撞到自己的时候出现了一个小BUG:我设置了一个名字叫DIE()的函数,里面做了判定的条件并返回蛇的生命LIFE的值,用来判定蛇是否死亡。但是发现这个函数根本不能正常判定。于是我在TEST程序里测试这个函数发现这函数没有任何问题,但是放在原程序中就是有错误。然后我尝试性的把这函数的类容粘贴到主函数的循环中去发现能正常运行,唯独不能把它作为一个函数来调用。所以我只好取消了这个函数,在主函数循环中写判定条件。但是介于这个函数写的必将场要加到每个循环中会显得比较臃肿,于是我换了一个较为简单的判定方法:将蛇头得坐标等于蛇身每一节的坐标进行或运算,如果得的值是1证明至少有一节与蛇头重合了,如此较为简洁的解决了这个问题。
到这里游戏的主要部分就已经基本完成了,一下都是增加游戏性添加的一些类容。
首先游戏结束后至少能让别人有个重新开始的机会,不然死一次都要重新点一次运行多麻烦啦。我在整个函数外面添加了一个WHILE(LIFE)循环,即当LIFE=1的时候继续游戏,而在死亡后LIFE=0,这是会出现一个选项让你是否重新开始游戏,如果选“是”的话便会重新将LIFE值赋为1则继续游戏,而选“否”由于LIFE=0则程序结束。
其次要能够让人保存最高分,这样有点挑战性会更有乐趣。这个我在课件上看到了相关的代码,于是加了进去就能够读取和存储最高分了。
接下来加入了9个关卡,从1到9关卡蛇的速度是不同的,当然每吃到一个苹果得到的分数也是不同的。当然选哪关属于个人喜好,比如第一关速度很慢,开始基本很难死,但要想得高分吃的苹果就会比其他等级多,这样到最后蛇会很长相反是最容易死掉的。而最后一关得分多但速度极快,一担苹果出现在边上要去吃的花就很容易死,也不容易玩出高分,而中间的等级才是比较耐玩的。
之后我加了点音乐,但是由于这方面知识课件上给的不够,导致很多音效和音乐不能够完美的嵌入。网上给的方法也比较麻烦,于是音乐只设计了简单的载入音乐和游戏音乐,算是整个程序里面最不理想的地方
最后加入了载入界面和简单的游戏说明。使得程序看起来更完整,但由于C++上能输出的东西有限,不可能做的太美观,于是只能稍微做了一点字幕效果凑合了。
这次暑期实习期间我学到了很多东西。比如设计一个小游戏的思路:便是从主体入手,编写出主要的操作,再进行包装与美化。又比如说并不是什么东西都需要原创,借鉴才是最快最有效的方法,像插入音乐保存游戏结果这类没有接触过的东西只要查到相关代码会用就行。另外也要相信自己的能力,在程序的主体和算法设计的时候没有可借鉴的,就只能自己想办法来实现这些运算,当方法行不通的时候不要气馁,要善于分析问题,不断地测试和调试,一般总能将这些问题一个个解决来完成整个程序。
总之要感谢这次暑期实习机会,让我明白真正的水平不仅仅只局限于书本,而最多取决于自主创新和收集信息的能力。相信通过这次实习,我的编程能力已经提升了不少。我也会在以后编程时获得一个大概的思路,让我能够更好地面对将来编程中出现的问题。
第二篇:贪吃蛇C++编程
1.//这个是背景的单元格数据结构
2.constlength=40;
3.constwidth=20;
4.structsquare{
5.boolblocked;//是否有障碍物
6.boolfood;//是否有食物
7.intx;//单元格在背景中的相对横坐标
8.inty;//单元格在背景中的相对纵坐标
9.}bg[length][width];//直接创建游戏背景
10.
11.//设置背景
12.voidsetBG(intlength,intwidth){
13.HANDLEhOut;
14.COORDOutChar;
15.OutChar.X=10;
16.OutChar.Y=10;
17.inti=0;
18.intj=0;
19.for(i=0;i<width;i++){
20.for(j=0;j<length;j++){
21.bg[i][j].x=i;
22.bg[i][j].y=j;
23.bg[i][j].blocked=false;
24.bg[i][j].food=false;
25.OutChar.X=j+10;
26.hOut=GetStdHandle(STD_OUTPUT_HANDLE);
27.SetConsoleCursorPosition(hOut,OutChar);
28.cout<<col(BG_WHITE,true)<<"";
29.}
30.cout<<endl;
31.OutChar.Y=i+10;
32.SetConsoleCursorPosition(hOut,OutChar);
33.}
34.}
35.//构造障碍物
36.voidcreateBlock(intx,inty,unsignedshortcolor){
37.HANDLEhOut;
38.COORDOutChar;
39.OutChar.X=x;
40.OutChar.Y=y;
41.hOut=GetStdHandle(STD_OUTPUT_HANDLE);
42.SetConsoleCursorPosition(hOut,OutChar);//定位光标输入
43.cout<<col(color,true)<<"";//一个颜色为color的空白
字符
44.}
45.
46.//生成单个障碍物
47.voidcreateWall(intx,inty){
48.createBlock(x+10,y+10,BG_GREEN);
49.bg[x][y].blocked=true;
50.}
51.
52.//判断所指坐标是否被占用
53.boolcheckExisted(intx,inty){
54.if(bg[x][y].blocked==true||bg[x][y].food==true){
55.returnfalse;
56.}
57.returntrue;
58.}
59.
60.//随机生成障碍物
61.voidrand_createWall(void){
62.srand((unsigned)time(NULL));
63.intn=rand()%70+10;
64.intpos_x=0;
65.intpos_y=0;
66.inti=0;
67.for(i=0;i<n;i++){
68.pos_x=rand()%length;
69.pos_y=rand()%(width-1);
70.if(checkExisted(pos_x,pos_y)==true){//防止障碍物重
叠
71.createWall(pos_x,pos_y);
72.}else{
73.n++;
74.}
75.//createWall(pos_x,pos_y);
76.}
77.}
78.//创建食物
79.voidcreateFood(intx,inty){
80.createBlock(x+10,y+10,BG_BLUE);
81.bg[x][y].food=true;
82.}
83.
84.//随机创建食物
85.voidrand_createFood(void){
86.srand((unsigned)time(NULL));
87.
88.
89.
90.
91.
92.
93.
94.intn=1;//rand()%20;intpos_x=0;intpos_y=0;inti=0;for(i=0;i<n;i++){pos_x=rand()%length;pos_y=rand()%(width-1);if(checkExisted(pos_x,pos_y)==true){
上生成食物
95.createFood(pos_x,pos_y);
96.}else{
97.n++;
98.}
99.}
100.}
101.//物体信息,这是蛇的单元模型
102.constobjLen=5;
103.structobj{
104.intx;
105.inty;
106.}snake[objLen];
107.
108.//创建蛇
109.LinList<structobj>newSnake;
110.voidcreateSnake(void){
111.inti=0;
112.for(i=0;i<objLen;i++){113.snake[i].x=i;
114.snake[i].y=0;
115.newSnake.Insert(snake[i],i);116.}
117.}
118.
119.//绘制蛇
120.voiddrawSnake(intlen){
121.inti=0;
122.structobjt;
123.for(i=0;i<len;i++){
124.t=newSnake.GetData(i);
125.createBlock(t.x,t.y,BG_RED);126.}
127.}
128.
129.//增长蛇的身体//防止在障碍物
130.131.132.133.134.135.136.137.138.139.140.141.142.143.144.145.146.147.148.149.150.151.152.153.154.155.156.157.158.159.160.161.162.163.164.165.166.167.168.169.170.171.172.
173.voidinsreaseSnake(intx,inty){structobjt;t.x=x;t.y=y;newSnake.Insert(t,0);createBlock(x,y,BG_RED);}//传递蛇的信息voidtransSnake(intx,inty,intlen){inti=0;structobjt1,t2;for(i=0;i<len-1;i++){t1=newSnake.GetData(i);t2=newSnake.GetData(i+1);newSnake.Delete(i);t1.x=t2.x;t1.y=t2.y;newSnake.Insert(t1,i);}newSnake.Delete(newSnake.Size()-1);t1.x=x;t1.y=y;newSnake.Insert(t1,newSnake.Size()-1);}//清除物体移动轨迹voidremoveTrack(intx,inty){HANDLEhOut;COORDOutChar;OutChar.X=x;OutChar.Y=y;hOut=GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleCursorPosition(hOut,OutChar);cout<<col(BG_WHITE,true)<<"";}//移动物体intx=10;inty=10;inttail_x=0;inttail_y=0;voidmoveBlock(chardirection){HANDLEhOut2;COORDOutChar2;
174.OutChar2.X=x;
175.OutChar2.Y=y;
176.structobjt;
177.t=newSnake.GetData(0);
178.tail_x=t.x;
179.tail_y=t.y;
180.hOut2=GetStdHandle(STD_OUTPUT_HANDLE);
181.removeTrack(t.x,t.y);
182.switch(direction){
183.case'w':{
184.OutChar2.Y--;
185.y--;
186.SetConsoleCursorPosition(hOut2,OutChar2);187.break;
188.}
189.case's':{
190.OutChar2.Y++;
191.y++;
192.SetConsoleCursorPosition(hOut2,OutChar2);193.break;
194.}
195.case'a':{
196.OutChar2.X--;
197.x--;
198.SetConsoleCursorPosition(hOut2,OutChar2);199.break;
200.}
201.case'd':{
202.OutChar2.X++;
203.x++;
204.SetConsoleCursorPosition(hOut2,OutChar2);205.break;
206.}
207.}
208.
209.transSnake(x,y,newSnake.Size());
210.drawSnake(newSnake.Size());
211.}
212.//判断是否碰到障碍物或边界
213.boolcheckView(chardirection){
214.if(direction=='w'&&y>=10){
215.if(y==10||bg[x-10][y-10-1].blocked==true){re
turnfalse;}
216.}
217.elseif(direction=='s'&&y<10+width){
218.if(y==10+width-2||bg[x-10][y-10+1].blocked==
true){returnfalse;}
219.}
220.elseif(direction=='a'&&x>=10){
221.if(x==10||bg[x-10-1][y-10].blocked==true){re
turnfalse;}
222.}
223.elseif(direction=='d'&&x<10+length){
224.if(x==10+length-1||bg[x-10+1][y-10].blocked==
true){returnfalse;}
225.}
226.returntrue;
227.}
228.
229.//判断是否吃到食物
230.boolcheckFood(intx,inty){
231.if(bg[x-10][y-10].food==true){returntrue;}232.returnfalse;
233.}
234.intmain()
235.{
236.HANDLEhOut;
237.COORDOutChar;
238.
239.OutChar.X=0;
240.OutChar.Y=0;
241.hOut=GetStdHandle(STD_OUTPUT_HANDLE);
242.SetConsoleCursorPosition(hOut,OutChar);
243.
244./*
245.structsquare**bgR=newsquare*[width];246.structsquare*bgC=newsquare[length];
247.for(inti=0;i<width;i++){
248.bgR[i]=bgC;
249.}
250.*/
251.//设置背景
252.setBG(length,width);
253.//设置障碍物
254.rand_createWall();
255.//设置食物
256.rand_createFood();
257.//创建蛇
258.259.260.261.262.263.264.265.266.
物267.268.269.270.
物271.272.273.274.275.276.277.278.279.
280.}createSnake();//移动物体chardirection;intscore=0;for(;;){direction=getch();if(checkView(direction)==true){//判断能否移动moveBlock(direction);if(checkFood(x,y)==true){//判断是否吃到食bg[x-10][y-10].food=false;score++;insreaseSnake(tail_x,tail_y);//增长身体rand_createFood();//吃完后随机在创建一个食}}OutChar.X=0;OutChar.Y=0;hOut=GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleCursorPosition(hOut,OutChar);cout<<col(BG_WHITE,true)<<"Scores:"<<score;}return0;