一种新的贪吃蛇C语言.docx

上传人:b****3 文档编号:4110588 上传时间:2023-05-06 格式:DOCX 页数:19 大小:20.15KB
下载 相关 举报
一种新的贪吃蛇C语言.docx_第1页
第1页 / 共19页
一种新的贪吃蛇C语言.docx_第2页
第2页 / 共19页
一种新的贪吃蛇C语言.docx_第3页
第3页 / 共19页
一种新的贪吃蛇C语言.docx_第4页
第4页 / 共19页
一种新的贪吃蛇C语言.docx_第5页
第5页 / 共19页
一种新的贪吃蛇C语言.docx_第6页
第6页 / 共19页
一种新的贪吃蛇C语言.docx_第7页
第7页 / 共19页
一种新的贪吃蛇C语言.docx_第8页
第8页 / 共19页
一种新的贪吃蛇C语言.docx_第9页
第9页 / 共19页
一种新的贪吃蛇C语言.docx_第10页
第10页 / 共19页
一种新的贪吃蛇C语言.docx_第11页
第11页 / 共19页
一种新的贪吃蛇C语言.docx_第12页
第12页 / 共19页
一种新的贪吃蛇C语言.docx_第13页
第13页 / 共19页
一种新的贪吃蛇C语言.docx_第14页
第14页 / 共19页
一种新的贪吃蛇C语言.docx_第15页
第15页 / 共19页
一种新的贪吃蛇C语言.docx_第16页
第16页 / 共19页
一种新的贪吃蛇C语言.docx_第17页
第17页 / 共19页
一种新的贪吃蛇C语言.docx_第18页
第18页 / 共19页
一种新的贪吃蛇C语言.docx_第19页
第19页 / 共19页
亲,该文档总共19页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

一种新的贪吃蛇C语言.docx

《一种新的贪吃蛇C语言.docx》由会员分享,可在线阅读,更多相关《一种新的贪吃蛇C语言.docx(19页珍藏版)》请在冰点文库上搜索。

一种新的贪吃蛇C语言.docx

一种新的贪吃蛇C语言

贪吃蛇C语言.txt这是一个禁忌相继崩溃的时代,没人拦得着你,只有你自己拦着自己,你的禁忌越多成就就越少。

自卑有多种档次,最高档次的自卑表现为吹嘘自己干什么都是天才。

//贪吃蛇游戏程序,屏左半部用于游戏活动,右半部为分数显示

//游戏屏为16*16游戏点阵,可容纳蛇身块数256。

每个游戏点阵又由4*4个LCD基本点阵组成

//蛇行标志在定时器上置位,这里为游戏的主体部分。

 

#defineucharunsignedchar

#defineuintunsignedint

#defineulongunsignedlong

#defineLCMDXBYTE[0xAfff]//液晶数据口

#defineLCMCXBYTE[0xAbff]//液晶命令口

#defineTIME_RUN10//定时器分品系数

#include"study.h"

#include"reg51.h"

#include"absacc.h"

#include"intrins.h"

//游戏部分

//x,y最大极限

#defineMAX_GAME_X15

#defineMAX_GAME_Y15

 

#definelcd_no_read1//编译选项,把这项屏蔽掉就采用LCD读出方式,否则采用显存形式

 

ucharsnake_flag,//蛇头标志76543210

//上下左右xgameoverfoodrun

snake_len,//蛇身长度

snake_food;//食物位置,高4位Y,低4位x

ucharxdatasnake_body[256];//蛇身每个部分的数据

//76543210

//高4位Y方向低4位X方向

#ifdeflcd_no_read

ucharxdatalcd_buf[8][64];//lcd缓冲,用于记录LCD内部的点阵,可以理解为显存

//当LCD无读出功能时,就要采用显示缓冲。

本LCD为可读,一般不用这个功能

//缓冲只记录蛇身活动的部分,即LCD左半屏

#endif

 

/******************************************************

*游戏LCD部分,根据游戏的特点把LCD分成16*16块

*用作游戏点阵,

*******************************************************/

//

//函数名:

clr_game_dot

//功能:

清一个游戏点

//输入参数:

游戏点的X,Y坐标

//注意事项:

这里的X,Y坐标和LCD底层的X,Y坐标不同,他最大只能是MAX_GAME_X,MAX_GAME_Y

//使用方式:

内部调用

voidclr_game_dot(ucharx,uchary)

{

ucharlcd_x,i,tmp;

while(x>MAX_GAME_X)x-=(MAX_GAME_X+1);//这个是写程序习惯的保护措施,预防输入范围过大

while(y>MAX_GAME_Y)y-=(MAX_GAME_Y+1);

lcd_x=x<<2;

LCMC=lcd_x&0x0f;//设置x位置

LCMC=(lcd_x>>4)|0x10;

LCMC=0xb0+y/2;//设置Y位置

LCMC=0xe0;

if(y%2)//行的下半部

{

for(i=0;i<4;i++)

{

#ifdeflcd_no_read//以下是显存法的清点程序,其他例如亮点的部分和这个原理一样

tmp=lcd_buf[y>>1][(x<<2)+i];//先从缓冲读出要修改的LCD片的数据

tmp&=0x0f;//清对应的游戏点

LCMD=tmp;

_nop_();

lcd_buf[y>>1][(x<<2)+i]=tmp;//把新数据写回缓冲

#else

tmp=LCMD;tmp=LCMD;//读LCD的方法,要求连读2次

LCMD=tmp&0x0f;

#endif

}

}

else//行的上半部,下同

{

for(i=0;i<4;i++)

{

#ifdeflcd_no_read

tmp=lcd_buf[y>>1][(x<<2)+i];

tmp&=0xf0;

LCMD=tmp;

_nop_();

lcd_buf[y>>1][(x<<2)+i]=tmp;

#else

tmp=LCMD;tmp=LCMD;

LCMD=tmp&0xf0;

#endif

}

}

LCMC=0xee;

}

//函数名:

fill_game_dot

//功能:

亮一个游戏点

//输入参数:

游戏坐标的X,Y坐标

//注意事项:

这里的X,Y坐标和LCD底层的X,Y坐标不同,他最大只能是MAX_GAME_X,MAX_GAME_Y

//这个函数和上面的clr_game_dot基本相同,只是在写LCD数据的时候是全1而不是0

//使用方式:

内部调用

voidfill_game_dot(ucharx,uchary)

{

ucharlcd_x,i,tmp;

while(x>MAX_GAME_X)x-=(MAX_GAME_X+1);

while(y>MAX_GAME_Y)y-=(MAX_GAME_Y+1);

lcd_x=x<<2;

LCMC=lcd_x&0x0f;//设置x位置

LCMC=(lcd_x>>4)|0x10;

LCMC=0xb0+y/2;//设置Y位置

LCMC=0xe0;

if(y%2)//行的下半部

{

for(i=0;i<4;i++)

{

#ifdeflcd_no_read

tmp=lcd_buf[y>>1][(x<<2)+i];

tmp|=0xf0;

LCMD=tmp;

_nop_();

lcd_buf[y>>1][(x<<2)+i]=tmp;

#else

tmp=LCMD;tmp=LCMD;

LCMD=tmp|0xf0;

#endif

}

}

else

{

for(i=0;i<4;i++)

{

#ifdeflcd_no_read

tmp=lcd_buf[y>>1][(x<<2)+i];

tmp|=0x0f;

LCMD=tmp;

_nop_();

lcd_buf[y>>1][(x<<2)+i]=tmp;

#else

tmp=LCMD;tmp=LCMD;

LCMD=tmp|0x0f;

#endif

}

}

LCMC=0xee;

}

//函数名:

fill_game_dot2

//功能:

亮一个游戏点(另一种方式,这里用来显示食物用)

//输入参数:

X,Y

//注意事项:

X,Y为游戏的点阵,非LCD点阵...还有LCD填充数据是0x05或0x50

//使用方式:

内部调用,显示蛇的食物的时候用这个函数,区分开蛇身和食物.

voidfill_game_dot2(ucharx,uchary)

{

ucharlcd_x,i,tmp;

while(x>MAX_GAME_X)x-=(MAX_GAME_X+1);

while(y>MAX_GAME_Y)y-=(MAX_GAME_Y+1);

lcd_x=x<<2;

LCMC=lcd_x&0x0f;//设置x位置

LCMC=(lcd_x>>4)|0x10;

LCMC=0xb0+y/2;//设置Y位置

LCMC=0xe0;

if(y%2)

{

for(i=0;i<4;i++)

{

#ifdeflcd_no_read

tmp=lcd_buf[y>>1][(x<<2)+i];

tmp|=0x50;

LCMD=tmp;

_nop_();

lcd_buf[y>>1][(x<<2)+i]=tmp;

#else

tmp=LCMD;tmp=LCMD;

LCMD=tmp|0x50;

#endif

}

}

else

{

for(i=0;i<4;i++)

{

#ifdeflcd_no_read

tmp=lcd_buf[y>>1][(x<<2)+i];

tmp|=0x05;

LCMD=tmp;

_nop_();

lcd_buf[y>>1][(x<<2)+i]=tmp;

#else

tmp=LCMD;tmp=LCMD;

LCMD=tmp|0x05;

#endif

}

}

LCMC=0xee;

}

 

/************************************************************

*

*游戏算法部分(4*4LCD)

*

**************************************************************/

//函数名game_init()

//功能:

游戏开始的时候初始化画面的,这里只是简单地把132*64LCD用一条中间线划分开来

//注意事项:

暂时在中间画条线用来划分游戏空间

//使用方式:

内部调用,

voidgame_init()

{

uchari;

ucharxdata*da;

for(da=0;da<0x8000;da++)//清空xDATA,

*da=0x0;

cls(9);//丁丁的清屏函数

initlcd();

for(i=0;i<8;i++)

{

LCMC=64&0x0f;

LCMC=(64>>4)|0x10;//线在x=64,

LCMC=0xb0+i;//y=(0-15)的地方

LCMC=0xe0;//把LCD划分,左边用来游戏

LCMD=0xff;

}

LCMC=0xee;

}

 

//函数名:

snake_init

//功能:

蛇初始化

//注意事项:

初始化只有3节蛇身,向右跑

//使用情况:

内部调用

voidsnake_init()

{

fill_game_dot(0,0);//显示射身

fill_game_dot(1,0);

fill_game_dot(2,0);

snake_len=2;

snake_flag=0x10;//蛇的初始化,3个身.向右跑

snake_body[0]=0x02;//装入射身数据

snake_body[1]=0x01;

snake_body[2]=0x00;

//一开始游戏时的文字部分

setcursor(8,0);

lcdstring("分数为:

\r\n");

setcursor(8,2);

lcddigit(snake_len-2);

}

//函数名:

show_mark

//功能:

显示当前分数,暂时以蛇身个数为分数

//参数说明:

0,和非0,0代表游戏中的显示,!

0代表挂了的显示

//注意事项:

调用到LCD.c显示函数,并需要汉字库的支持.

//返回值在GAMEOVER时候有效,返回0退出游戏,1从新游戏

//使用情况:

snake_run()在蛇吃到食物的时候调用,在GAMEOVER后调用

ucharshow_mark(ucharmode)

{

ucharch;

setcursor(8,0);

lcdstring("分数为:

\r\n");

setcursor(8,2);

lcddigit(snake_len-2);

if(mode)//gameover中显示

{

setcursor(8,0);

lcddigit(snake_len-2);

lcdstring("分.");

setcursor(8,2);

lcdstring("C退出");

setcursor(8,4);

lcdstring("回车继续");

doch=getkey(1000);

while((ch!

='C')&&(ch!

='Y'));//游戏结束了会在这里死等,直到用户按键

if(ch=='Y')

return

(1);

else

return(0);

}

return(0);

}

//函数名:

snake_run

//功能:

蛇运行函数

//输入参数:

一个全局变量flag_snake,蛇根据这个变量判断运动方向

//注意事项:

蛇跑动函数,用于判断路径,食物,长大,死亡

//使用情况:

内部调用

voidsnake_run()

{

uchartmp_head_x,tmp_head_y;

uchari;

switch(snake_flag&0xf0)//取蛇头方向

{

case0x80:

//向上走y--

tmp_head_x=snake_body[0]&0x0f;

tmp_head_y=(snake_body[0]>>4);

if(tmp_head_y==0)snake_flag|=0x04;//这个代表撞墙了,就置GAMEOVER标志,下同

elsetmp_head_y--;

break;

case0x40:

//向下走y++

tmp_head_x=snake_body[0]&0x0f;

tmp_head_y=(snake_body[0]>>4);

if(tmp_head_y==MAX_GAME_Y)snake_flag|=0x04;

elsetmp_head_y++;

break;

case0x20:

//向左走x--

tmp_head_y=snake_body[0]>>4;

tmp_head_x=snake_body[0]&0x0f;

if(tmp_head_x==0)snake_flag|=0x04;

elsetmp_head_x--;

break;

case0x10:

//向右走x++

tmp_head_y=snake_body[0]>>4;

tmp_head_x=snake_body[0]&0x0f;

if(tmp_head_x==MAX_GAME_X)snake_flag|=0x04;

elsetmp_head_x++;

break;

default:

break;

}

if(!

(snake_flag&0x04))//如果在之前没有撞墙,就可以进行下一步判断

{

//以下是得到食物的判断。

if(snake_food!

=((tmp_head_y<<4)+tmp_head_x))//蛇头和食物坐标没重叠就代表没有吃到食物

{//得不到食物的处理

clr_game_dot(snake_body[snake_len]&0x0f,snake_body[snake_len]>>4);//灭蛇尾巴

for(i=snake_len;i>0;i--)//柔体传动

snake_body[i]=snake_body[i-1];

snake_body[0]=(tmp_head_y<<4)+tmp_head_x;

}

else

{//得到食物的处理

snake_body[snake_len+1]=snake_body[snake_len];//保留蛇尾巴(这是增长型柔体传动)

for(i=snake_len;i>0;i--)

snake_body[i]=snake_body[i-1];

snake_body[0]=(tmp_head_y<<4)+tmp_head_x;//新蛇头

snake_len++;//长度增加1

snake_flag&=~0x02;//清食物标志

show_mark(0);//显示分数

}

fill_game_dot(tmp_head_x,tmp_head_y);//显示新蛇头

}

for(i=1;i

{

if(snake_body[0]==snake_body[i])

{

snake_flag|=0x04;//撞中了就置GAMEOVER标志

break;

}

}

}

 

//函数名:

set_food

//功能:

放食物

//注意事项:

这个函数在被调用前会先判断是否需要放食物,

//这里用自己编写的随机数来产生食物,随机数和蛇身位置,定时器有关

//每次放食物的时候必须先判断是否和蛇身重叠了,重叠了要重新放

//这里设定了如果蛇长度达到某值了就不再放食物.

//影响变量:

snake_food

//使用情况:

内部调用

voidset_food()

{

ucharseed0,seed1,i=0;

seed0=snake_body[snake_len-2];

if(snake_len==250)

{

return;//蛇都快满屏了,就不放食物了,事实上我还没玩过超过100的呢:

}

seed0=((seed1>>3)*4+seed0+TL0);//随机数的生成,其实乱做就可以了:

seed1=(snake_body[0]>>4)+seed0;

snake_food=(seed1+seed0*3);

food:

for(i=0;i

{

if(snake_body[i]==snake_food)

{

snake_food=(snake_food+0x01);//如果重叠了,位置就+1,然后

gotofood;//重新比较,这里可以换成i=255,效果一样

}

}

fill_game_dot2(snake_food&0x0f,snake_food>>4);//放食物

snake_flag|=0x02;//置有食物标志

}

//函数名:

定时器1初始化程序

//晶振22.1184,定时时间35MS

voidtimer0_init(void)

{

TMOD=0x1;

TH0=0x0;

TL0=0x0;

}

 

//函数名:

snake_game

//功能:

整个游戏的主要函数

//注意事项:

游戏利用了定时器产生蛇的运行速速度

//调用前应该先初始化定时器

//使用情况:

外部调用

//

externuchartime_service;//这个东东是使定时器公用的。

voidsnake_game()

{

uchartmp_snake_flag,ch;

cls(8);

time_service=1;

lcdstring("贪吃蛇游戏\r\nC退出,任意键进入\r\n游戏说明:

\r\n2:

上5:

下4:

左6:

右");

while((ch=getkey(1000))==0);

if(ch=='C')return;

ch=0;

begin_game:

game_init();//一堆初始化

snake_init();

timer0_init();

TR0=1;

ET0=1;

EA=1;

tmp_snake_flag=snake_flag;

while

(1)

{

ch=getkey(1000);

switch(ch)

{

case'2':

//按了上按键

if((snake_flag&0x40)||(snake_flag&0x80))break;//向上走的时候,上下键盘都无效,下同

tmp_snake_flag&=0x0f;tmp_snake_flag|=0x80;

break;

case'5':

//按了下按键

if((snake_flag&0x80)||(snake_flag&0x40))break;

tmp_snake_flag&=0x0f;tmp_snake_flag|=0x40;

break;

case'4':

//按了左按键

if((snake_flag&0x10||(snake_flag&0x20)))break;

tmp_snake_flag&=0x0f;tmp_snake_flag|=0x20;

break;

case'6':

//按了右按键

if((snake_flag&0x20||(snake_flag&0x10)))break;

tmp_snake_flag&=0x0f;tmp_snake_flag|=0x10;

break;

case'C':

//任何时候,按C就结束游戏

return;

default:

break;

}

if(!

(snake_flag&0x02))//如果图上已经没食物了,就

set_food();//放食物

if((snake_flag&0x01))//判断是否够时间跑一步

{

snake_flag=(snake_flag&0x0e)|tmp_snake_flag;//取消跑动标志,置新方向

snake_run();

tmp_snake_flag=snake_flag;

}

if((snake_flag&0x04))//判断游戏结束标志

{

if(show_mark

(1))

{

snake_flag&=~0x04;

gotobegin_game;

}

else

return;//游戏结束

}

}

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 其它

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2