[求助][贪吃蛇]源程序,请教其中一个问题。
<P>源程序如下: 我的问题是,调节游戏速度时,数字为什么越大时,有时候竟然越快?<BR><BR><BR>#define N 200<BR>#include <graphics.h><BR>#include <stdlib.h><BR>#include <dos.h><BR>#define LEFT 0x4b00 /* 将这些特殊字符的ACSII值(这里主要的是扩展的)定义宏,来方便使用 */<BR>#define RIGHT 0x4d00<BR>#define DOWN 0x5000<BR>#define UP 0x4800<BR>#define ESC 0x011b<BR>int i,key;<BR>int score=0;/*得分*/<BR>int gamespeed=60000;/*游戏速度自己调整 这个值应该是越小蛇运动的越快,但是我在Win-TC1.9.1运行时,当我把gamespeed增大时,在某些值下会反而会增快,不知道为什么*/<BR>struct Food<BR>{<BR> int x;/*食物的横坐标*/<BR> int y;/*食物的纵坐标*/<BR> int yes;/*判断是否要出现食物的变量*/<BR>}food;/*食物的结构体*/<BR>struct Snake<BR>{<BR> int x[N];<BR> int y[N];<BR> int node;/*蛇的节数*/<BR> int direction;/*蛇移动方向*/<BR> int life;/* 蛇的生命,0活着,1死亡*/<BR>}snake;<BR>void Init(void);/*图形驱动*/<BR>void Close(void);/*图形结束*/<BR>void DrawK(void);/*开始画面*/<BR>void GameOver(void);/*结束游戏*/<BR>void GamePlay(void);/*玩游戏具体过程*/<BR>void PrScore(void);/*输出成绩*/<BR>/*主函数*/<BR>void main(void)<BR>{<BR> Init();/*图形驱动*/<BR> DrawK();/*开始画面*/<BR> GamePlay();/*玩游戏具体过程*/<BR> Close();/*图形结束*/<BR>}<BR>/*图形驱动*/<BR>void Init(void)<BR>{<BR> int gd=DETECT,gm;<BR> initgraph(&gd,&gm,"d:\\tc\program"); /* 初始化图形系统, d:\\tc\program 为EGA VGA.bgi所在路径 */<BR> cleardevice(); /* 清除屏幕函数 */<BR>}<BR>/*开始画面,左上角坐标为(50,40),右下角坐标为(610,460)的围墙,不过画完后围墙的内圈是(60,50)(600,450)*/<BR>void DrawK(void)<BR>{<BR>/*setbkcolor(LIGHTGREEN);*/ /* 设置背景颜色,可以添加 */<BR> setcolor(11);/* 函数setcolor()设置当前绘图颜色(或称做前景色)。 */<BR> setlinestyle(SOLID_LINE,0,THICK_WIDTH);/*设置线型 为画线函数设置当前线型,包括线型、线图样和线宽。此处为实线加宽 */<BR> for(i=50;i<=600;i+=10)/*画围墙*/<BR> {<BR> rectangle(i,40,i+10,49); /*上边 画矩形函数用当前绘图色、线型及线宽,画一个给定左上角与右下角的矩形 */<BR> rectangle(i,451,i+10,460);/*下边 此函数调用方式为void rectangle(int left,int top,int right,int bottom); */<BR> }/* 以一个小格为一个单位来画围墙的上下两行 */<BR> for(i=40;i<=450;i+=10)<BR> {<BR> rectangle(50,i,59,i+10); /*左边*/<BR> rectangle(601,i,610,i+10);/*右边*/<BR> }/* 以一个小格为一个单位来画围墙的左右两行 */<BR>}<BR>/*玩游戏具体过程*/<BR>void GamePlay(void)<BR>{<BR> randomize();/*随机数发生器*/<BR> food.yes=1;/*1表示需要出现新食物,0表示已经存在食物*/<BR> snake.life=0;/*活着*/<BR> snake.direction=1;/*方向往右*/<BR> snake.x[0]=100;snake.y[0]=100;/*蛇头 初始化位置*/<BR> snake.x[1]=110;snake.y[1]=100;<BR> snake.node=2;/*节数*/<BR> PrScore();/*输出得分*/<BR> while(1)/*可以重复玩游戏,压ESC键结束*/<BR> {<BR> while(!kbhit())/*检查当前按下的键 在没有按键的情况下,蛇自己移动身体*/<BR> {/* 关于kbhit()的返回值,查找有些地方都说检查到按键返回1没有检查到返回0但本人在Win-TC1.9.1上测试为检查到返回-1没检查到返回0 */<BR> /* 所以kbhit()没检查到时返回0检查到返回非0相对准确些 */<BR> /* 再说一点,该函数只是检查当前是否有按键信息,却不捕获该信息。也就是说你按下一个'Q'它知道你有按下键,后面如果有捕获按键信息的函数,那么那个函数仍然可以捕获这个'Q'信息的 */<BR> if(food.yes==1) /*需要出现新食物*/<BR> {<BR> food.x=rand()%400+60;/* rand()产生随机数。rand()%400+60这个表达式说明产生的随机数范围是[60,460) */<BR> food.y=rand()%350+60;<BR> while(food.x%10!=0)/*食物随机出现后必须让食物能够在整格内,这样才可以让蛇吃到,因为作者把每个小格的大小定义为10*10,所以蛇头的位置必然在横(列)中是10的整数倍 */<BR> food.x++;<BR> while(food.y%10!=0)<BR> food.y++;<BR> food.yes=0;/*画面上有食物了*/<BR> }<BR> if(food.yes==0)/*画面上有食物了就要显示*/<BR> {<BR> setcolor(GREEN);<BR> rectangle(food.x,food.y,food.x+10,food.y-10);/* 根据刚才设置的食物的位置画出食物来 */<BR> }<BR> for(i=snake.node-1;i>0;i--)/*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/<BR> {<BR> snake.x[i]=snake.x[i-1];<BR> snake.y[i]=snake.y[i-1];<BR> }<BR> /*1,2,3,4表示右,左,上,下四个方向,通过这个判断来移动蛇头*/<BR> switch(snake.direction)<BR> {<BR> case 1:snake.x[0]+=10;break; /* 向右 */<BR> case 2: snake.x[0]-=10;break; /* 向左 */<BR> case 3: snake.y[0]-=10;break; /* 向上 */<BR> case 4: snake.y[0]+=10;break; /* 向下 */<BR> }<BR> for(i=3;i<snake.node;i++)/*从蛇的第四节开始判断是否撞到自己了,因为蛇头为两节,第三节不可能拐过来*/<BR> {<BR> if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0])<BR> {<BR> GameOver();/*显示失败*/<BR> snake.life=1;<BR> break;<BR> }<BR> }<BR> if(snake.x[0]<55||snake.x[0]>595||snake.y[0]<55||snake.y[0]>455)/*蛇是否撞到墙壁这里的数字都是内壁与外壁的中点,来判断蛇头是否超过了内壁*/<BR> {<BR> GameOver();/*本次游戏结束*/<BR> snake.life=1; /*蛇死*/<BR> }<BR> if(snake.life==1)/*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/<BR> break;<BR> if(snake.x[0]==food.x&&snake.y[0]==food.y)/*吃到食物以后*/<BR> {<BR> setcolor(0);/*把画面上的食物东西去掉*/<BR> rectangle(food.x,food.y,food.x+10,food.y-10);<BR> snake.x[snake.node]=-20;snake.y[snake.node]=-20;<BR> /*新的一节先放在看不见的位置,下次循环就取前一节的位置,此时虽然这节没有显示出来,不过蛇结构确实已经有了这节的数据*/<BR> snake.node++;/*蛇的身体长一节*/<BR> food.yes=1;/*画面上需要出现新的食物*/<BR> score+=10;<BR> PrScore();/*输出新得分*/<BR> }<BR> setcolor(4);/*画出蛇 这里4是红色 */<BR> for(i=0;i<snake.node;i++)<BR> rectangle(snake.x[i],snake.y[i],snake.x[i]+10,snake.y[i]-10);<BR> delay(gamespeed);/* 将程序的执行暂停一段时间(毫秒) void delay(unsigned milliseconds); 程序暂停就是蛇在停止 */<BR> setcolor(0);/*用黑色(作者说是黑色不过我测试的结果为setcolor(0)是设置成背景色,也就是说不管你的背景色设置成什么颜色,该函数都会使得绘图色于背景色一样,从而实现"不显色"蛇最后一节,但setbkcolor(0)确实将背景色设置为黑色)去除蛇的的最后一节*/<BR> rectangle(snake.x[snake.node-1],snake.y[snake.node-1],snake.x[snake.node-1]+10,snake.y[snake.node-1]-10); /* 当程序休息过,先去掉蛇的最后一节,因为在重新画蛇的时候(for语句)并没有去掉蛇尾巴的过程 */<BR> } /*end:while(!kbhit)*/<BR> if(snake.life==1)/*如果蛇死就跳出循环*/<BR> break;<BR> key=bioskey(0);/*接收按键函数bioskey()的原型为: int bioskey(int cmd); */<BR> /* 当cmd==0时,bioskey()返回按健的键值,该值是2 个字节的整型数。当按下时,若返回值的低8 位为非零,则表示为普通键,其值代表该键的ASCII 码。若返回值的低8 位为0,则高8 位表示为扩展的ASCII码,表示按下的是特殊功能键*/<BR> /* 由于while(!kbhit())的“再说一点”所以这里bioskey()函数仍然能捕获这个按键的信息。 */<BR> if(key==ESC)/*按ESC键退出*/<BR> break;<BR> else if(key==UP&&snake.direction!=4)<BR>/*判断是否往相反的方向移动,如果不是相反方向才确认新的方向*/<BR> snake.direction=3;<BR> else if(key==RIGHT&&snake.direction!=2)<BR> snake.direction=1;<BR> else if(key==LEFT&&snake.direction!=1)<BR> snake.direction=2;<BR> else if(key==DOWN&&snake.direction!=3)<BR> snake.direction=4;<BR> }/*end:while(1)*/<BR>}<BR>/*游戏结束*/<BR>void GameOver(void)<BR>{<BR> cleardevice(); /* 清除整个屏幕,并且将当前位置移到屏幕原点。该函数类似于文本模式下的函数clrscr(),但clrscr()函数不能在图形方式下工作;同样cleardevice()函数不能在文本模式下工作。 */<BR> PrScore();<BR> setcolor(15); /* 以下三个函数见PrScore()中说明 */<BR> settextstyle(0,0,4);<BR> outtextxy(200,200,"GAME OVER");<BR> getch();<BR>}<BR>/*输出成绩*/<BR>void PrScore(void)<BR>{ <BR> char str[10];<BR> setfillstyle(SOLID_FILL,14); /* 为各种图形函数设置填充图样和颜色 */<BR> bar(50,15,220,35); /* 用当前填充图样和填充色(注意不是给图色)画出一个指定上左上角与右下角的实心长条形(长方块或正方块),但没有四条边线 */<BR> /* bar()函数调用方式为void bar(int left,int top,int right,int bottom);调用此函数前,可用setfillstyle()或setfillpattern()设置当前填充图样和填充色。 */<BR> setcolor(6); /* 函数setcolor()设置当前绘图颜色(或称做前景色)。voids setcolor(int color);在低分辨率显示模式(320X200)下,选取的color是调色板颜色号,不是实际色彩值。 */<BR> settextstyle(0,0,2); /* 为图形输出设置当前的文本属性 void far settextstyle (int font, int direction, char size); 设置图形文本当前字体、文本显示方向(水平显示或垂直显示)以及字符大小。 */<BR> sprintf(str,"score:%d",score); /* score已经被定义成了全局变量,score内容格式化到str */<BR> outtextxy(55,20,str); /* 在(x,y)处显示字符串 */<BR>}<BR>/*图形结束*/<BR>void Close(void)<BR>{ <BR> getch();<BR> closegraph(); /* 关闭图形系统 */<BR>}</P>页:
[1]
