基于51单片机的贪吃蛇小程序(8*8LED点阵实现)

发布者:备战最新更新时间:2020-03-24 来源: eefocus关键字:51单片机  贪吃蛇小程序  8*8  LED点阵 手机看文章 扫描二维码
随时随地手机看文章

一直很想写一个贪吃蛇的小程序,这两天终于抽空完成了,这里把我的思路分享给大家,仅供参考!


代码如下:

先放段主函数压压惊


void main()

{

x_s[0] = 2;    //初始化三个点

y_s[0] = 3;

x_s[1] = 3;

y_s[1] = 3;

x_s[2] = 4;

y_s[2] = 3;

Timer0Init();

suijishu();

while(1)

{

   appear();

   if(flag_a) //蛇身移动位

   {

   if(!flag_s)   //蛇身死亡位

    {

auto_move();

HC_595(0x00);     //消隐

P0 = 0xFF; //消隐

shensi();

chiguo();

delay(1000);

flag_a = 0;

}

}

}

}


/*

本程序核心程序:

appear函数,显示蛇身

auto_move函数,控制蛇身惯性移动 ,同时里面附了判断是否穿墙的一段代码

direction函数,控制蛇的移动方向

suijishu(随机数)函数,随机生成果子

chiguo(吃果)函数,判断是否吃到果子

shensi(身死)函数,碰到自己身体则死亡


*/


#include

#include

#include

#define M 12 //难度系数,12中等,越小越难

typedef unsigned char uchar;

typedef unsigned int uint;


sbit SRCLK = P3^6;   //595芯片

sbit RCLK = P3^5;

sbit SER = P3^4;


sbit LSA=P2^2; //138译码器

sbit LSB=P2^3;

sbit LSC=P2^4;


uchar code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值


//定义方向键

sbit K1 = P3^1; //上 

sbit K2 = P3^0; //下 

sbit K3 = P3^2; //左

sbit K4 = P3^3; //右 


uchar m; //储存果子的X坐标

uchar n; //储存果子的Y坐标


uchar snakelong = 3;    //初始化蛇长

char flag_x = 1;    //初始化运动方向

char flag_y = 0;    //初始化运动方向

uchar flag_gg = 0;    //生成果子的重复性标志

uchar flag_c = 0, sheshen = 0;   //吃果标志

uchar flag_a = 0; //移动标志

uchar flag_s = 0; //死亡标志

uchar x_s[32] = {0},y_s[32] = {0};    //定义蛇的最大长度

uchar code X_[8] = {0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE};  

uchar code Y_[8] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};    


/*  

y1 //定义x,y坐标

y2   //如,我想让(4,2)亮,只需要P0 = X_[4];HC_595 = Y_[2];

y3

y3

y5

y6

y7

y8

  x1    x2   x3   x4  x5   x6   7   x8

*/


一个小的延时函数



void suijishu();    //提前定义随机数生成函数

void delay(uint i)    //简单的delay函数,对于51单片机,delay(1)约等于9微秒

{

while(i--);

}


定时器初始化:



void Timer0Init()   //定时器初始化函数    模式1,16位定时器

{

TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。


TH0=0XFC; //给定时器赋初值,定时1ms

TL0=0X18;

ET0=1;//打开定时器0中断允许

EA=1;//打开总中断

TR0=1;//打开定时器

}


两个显示函数,分别控制点阵和数码管;


void HC_595(uchar date) //595例程,这里就不详细解释了

{

uchar a;

SRCLK = 0;

RCLK = 0;


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

{

SER = date>>7;

date<<=1;

SRCLK = 1;

_nop_();

_nop_();

SRCLK = 0;

}

RCLK = 1;

_nop_();

_nop_();

RCLK = 0;

}


void display() //数码管显示,用来显示蛇长

{

uchar i,b=2;

HC_595(0x00);     //消隐

_nop_();

P0=0x00;   //因为我用的板子上数码管和点阵共用的P0口,所以这里消隐的时候需要特别注意。

_nop_();

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

{

while(b) {    //这里循环两次是为了让数码管显示更清楚一点。

switch(i) //位选,选择点亮的数码管

{

case(0):

LSA=0;LSB=0;LSC=0; P0=smgduan[(snakelong%10)];delay(10);P0=0x00;break;

case(1):

LSA=1;LSB=0;LSC=0; P0=smgduan[(snakelong/10)];delay(10);P0=0x00;break;

}

_nop_();

b--;

}

}

LSA=1;LSB=1;LSC=1; P0=0xFF; //还是为了消隐。以一个数码管常亮为代价,以求不影响点阵和数码管显示蛇长      

}


显示蛇身,核心函数之一:


void appear() // viod 蛇身出现     

{

/* x_s[0] = 2; //初始化三个点

y_s[0] = 3;

x_s[1] = 3;

y_s[1] = 3;

x_s[2] = 4;

y_s[2] = 3; */

     

//uint t = 150; //t越小越难,越大越简单 //这里也可以控制难度,经测试也有效。

//while(t)

//{

uchar i;

for(i=0;i {

if((x_s[i]!=0)&&(y_s[i]!=0))

{

P0 = X_[x_s[i]-1];

HC_595(Y_[y_s[i]-1]);

delay(100);    //延时

P0 = 0xFF; //消隐

HC_595(0x00);     //消隐

}

}

// t--;

//}


}


自动惯性移位函数:


void auto_move() // viod 自动移动   核心程序之一

{

uchar i;

for(i=0;i<(snakelong-1);i++)

{

x_s[i] = x_s[i+1];

y_s[i] = y_s[i+1];

}

x_s[snakelong-1] += flag_x;

y_s[snakelong-1] += flag_y;


if(x_s[snakelong-1]>8) // void 穿墙判断  

x_s[snakelong-1] = 1;

else if(x_s[snakelong-1]<1)

x_s[snakelong-1] = 8;

if(y_s[snakelong-1]>8)

y_s[snakelong-1] = 1;

else if(y_s[snakelong-1]<1)

y_s[snakelong-1] = 8;

}


键盘扫描(独立键盘),控制蛇的移动方向:


void direction() // void 方向控制 

{

if(!K1) 

{

delay(1000);

if(!K1)

{

if(flag_y == 1)    //是否正在下降 ,若是,则点击上升无用。

{flag_y = 1;}

   else

    {

flag_x = 0;

flag_y = -1; //shang

}

}

}

else if(!K2) 

{

delay(1000);

if(!K2)

{

if(flag_y == -1)    //是否正在上升

{flag_y = -1;}

else

{

flag_x = 0;

flag_y = 1; //xia

}

}

}

else if(!K3) 

{

delay(1000);

if(!K3)

{

if(flag_x == 1)    //是否正在右移

{flag_x = 1;}

else

{

flag_x = -1; //zuo

flag_y = 0;

}

}

}

else if(!K4) 

{

delay(1000);

if(!K4)

{

if(flag_x == -1)    //是否正在左移

{flag_x = -1;}

else

{

flag_x = 1; //you

flag_y = 0;

}

}

}

}


吃果函数,吃到果子蛇头增长


void chiguo() // void 吃果判断

{

if(((x_s[snakelong-1]+flag_x)==m)&&((y_s[snakelong-1]+flag_y)==n)  )

{ flag_c = 1; }

else if(((x_s[snakelong-1]+flag_x)==m)&&((y_s[snakelong-1]+flag_y)==n)  ) //重复两次防止程序bug——穿过果子但不去吃     

{ flag_c = 1; }

else if(((x_s[snakelong-2]+flag_x)==m)&&((y_s[snakelong-2]+flag_y)==n)  ) //放宽吃果判定,以防止出现bug——穿过果子但不去吃               

{ flag_c = 1; sheshen = 1;    }

else if(((x_s[snakelong-3]+flag_x)==m)&&((y_s[snakelong-3]+flag_y)==n)  )

{ flag_c = 1; sheshen = 2;    }

   

if(flag_c)

{

flag_c = 0;

TR0 = 0;//关闭定时器

snakelong++;

if(sheshen == 1)

{

x_s[snakelong-1] = m+flag_x;

y_s[snakelong-1] = n+flag_y;

sheshen = 0;

}

else if(sheshen == 2)

{

x_s[snakelong-1] = m+2*flag_x;

y_s[snakelong-1] = n+2*flag_y;

sheshen = 0;

}

else

{ //这才是吃果的正常情况

    x_s[snakelong-1] = m;

y_s[snakelong-1] = n;

sheshen = 0;

}

        suijishu();   //再生成一个果子

P0 = 0xFF; //消隐

HC_595(0x00);     //消隐

appear();

appear();

P0 = 0xFF; //消隐

HC_595(0x00);     //消隐

TR0=1;//打开定时器

}

}


碰到自己身体死亡函数


void shensi() // void 身死    碰到自己身死

{

uchar b,x_1,y_1;

if(snakelong>4)

{

for(b=0;b   {

if(((x_s[snakelong-1])==x_s[b])&&((y_s[snakelong-1])==y_s[b])  )  

{

flag_s = 1; 

}

  }

if(flag_s == 1)

{

P0 = 0x00;HC_595(0xFF);delay(2000);    //闪烁两次

P0 = 0xFF;HC_595(0x00);delay(2000);

P0 = 0x00;HC_595(0xFF);delay(3000);

P0 = 0xFF;HC_595(0x00);delay(1000);

x_1 = x_s[snakelong-1] ;

y_1 = y_s[snakelong-1] ;      //卡在死亡状态的下一刻  

  snakelong++;

x_s[snakelong-1] = x_1 + flag_x;

y_s[snakelong-1] = y_1 + flag_y;

}


}

}


随机生成果子:



void suijishu() //随机数,生成果子

{

uchar b,m_1,n_1;

do{

flag_gg = 0;

m_1 = (rand()%8)+1;    

n_1 = (rand()%8)+1;

for(b=0;b   {

if((m_1==x_s[b])&&(n_1==y_s[b])) //如果果子和蛇身有重复,则flag_gg置1,再生成一次                    

flag_gg = 1;

  }

}while(flag_gg);

m = m_1;

n = n_1;

}


主函数:


void main()

{

x_s[0] = 2;    //初始化三个点

y_s[0] = 3;

x_s[1] = 3;

y_s[1] = 3;

x_s[2] = 4;

y_s[2] = 3;

Timer0Init();

suijishu();

while(1)

{

   appear();

   if(flag_a) //蛇身移动位

   {

   if(!flag_s)   //蛇身死亡位

    {

auto_move();

HC_595(0x00);     //消隐

P0 = 0xFF; //消隐

shensi();

chiguo();

delay(1000);

flag_a = 0;

}

}

}

}


/*

果子的函数放在了中断里,1ms一次进行显示,同时键盘也是1mS一次进行扫描

通过调节M的大小来实现蛇的延时移动。

*/


void guozi() interrupt 1 // void 果子出现

{

uint a;

uchar i=3;

a++;

direction();   //用中断去扫描键盘,1mS/次

P0 = 0xFF; //消隐

HC_595(0x00);     //消隐

while(i)   //重复以增加亮度

{

P0 = X_[m-1];

HC_595(Y_[n-1]);

i--;

}

delay(100);

P0 = 0xFF; //消隐 ,因为我用的板子上数码管和点阵共用的P0口,所以这里消隐的时候需要特别注意

HC_595(0x00);     //消隐


_nop_();

P0=0x00;  //数码管消隐

_nop_();

display();

delay(100);


HC_595(0x00);     //消隐

_nop_();

LSA=1;LSB=1;LSC=1; P0 = 0xFF;

if (a>M)   //蛇身移动控制位

{

a = 0;

flag_a = 1;

}


/*

编写过程中共累计进行了两次优化,第一次对1,随机生成果子,2,吃果判定的放宽,3,碰到蛇身死亡,以及4,正在上升/下降时,不能下降上升

正在左移/右移时,不能右移/左移 进行了加入以及优化

第二次对数码管显示问题,吃到果子延时增长问题进行了解决,同时对死亡时的效果进行了优化


调试经验:

建议初学者首先构思好程序框架,想清楚程序需要哪几个必要模块(因此建议程序书写模块化),然后

对几个必要模块进行相对独立的调试,进而进行整合,确保基础功能的实现。

在此之后,在对程序出现的问题进行解决和优化。


*/

关键字:51单片机  贪吃蛇小程序  8*8  LED点阵 引用地址:基于51单片机的贪吃蛇小程序(8*8LED点阵实现)

上一篇:基于51单片机的简单计算器
下一篇:51单片机的8x8点阵贪吃蛇

推荐阅读最新更新时间:2024-11-21 10:55

丰田RAV4已经进入中国8年了!丰田的汽车到底怎么样
    要说城市SUV应该是当下最火的车型,但本应死扛CR-V的丰田RAV4却一直表现的十分低调,销量不佳。然而坐不住的丰田也终于是在7月28日发布了中期改款车型RAV4荣放,那换了一张雷凌脸的它到底都进行了哪些升级呢?   2016款RAV4和老款一样全系搭载了两台2.0L和2.5L自然吸气发动机,全系总共包含了7款车型。分别是2.0L都市版、风尚版、舒适版、智尚版、四驱新锐版、2.5L四驱精英版和四驱尊贵版,价格也是从17.98万到26.98万不等。   1994年,RAV4一经上市便获得了不错的市场反响,其销量更是达到了丰田预期的两倍。   彼时,距离丰田在1989年东京车展推出RAV4概念车已经过去了5年。5年
[汽车电子]
折扣近一半!三星为Note 7老用户购买Note 8提供给优惠
三星在官方新闻稿中提到,所有曾经买过Note7的用户可以参与以旧换新计划,用现役的手机交易换购Note8,最高可享受425美元(约合2829元)的购机补偿,基本相当于优惠了快一半了。下面就随嵌入式小编一起来了解一下相关内容吧。 昨晚,三星年度旗舰Galaxy Note8正式发布。 虽然官方照例没有公布价格,但美版的预购已经开启,9月15日上市,基本在900美元左右(约合人民币6000元)。 促销方面,首批购买都有Gear 360、128GB MicroSD卡、无线快充等配件免费赠送,和往年十分类似。 不过,真正给力的还是下面这项。 三星在官方新闻稿中提到,所有曾经买过Note7的用户可以参与以旧换新计划,用现役的手机交易换购N
[嵌入式]
德州仪器推出业界首款具有双通道异步取样率转换器的 8 通道PWM 音频处理器
日前,德州仪器 (TI) 宣布推出业界首款在单芯片上集成双通道异步取样率转换器 (ASRC) 的 8 通道脉宽调制器 (PWM) 音频处理器。符合 HD 标准的 TAS5548 有助于家庭及专业音频设计人员无缝整合两个音频源,相比需要两个芯片的同类竞争解决方案,该方案可提高设计灵活性并降低成本。该器件不但 支持8 至 192 kHz 的取样速率,同时还可将其转换为 96 kHz 或 192 kHz 固定速率,无需创建、存储和修改系数。这可简化一体化蓝光家庭影院 (HTiB)、音视频接收器、迷你/微型组合设备以及条形音箱等数字多通道产品的设计。如欲了解更多详情或订购样片,敬请访问: www.ti.com.cn/tas5548-pr-
[嵌入式]
51单片机驱动12位AD转换TLC2543电路图+程序
下面是电路图和仿真图: TI公司的12位AD转换TLC2543芯片比ADC0832的8位AD转换芯片,精度要高很多,ADC0832的精度是255分之1,而TLC2543 由于二进制数的位数是12bit,所以精度要高出很多,它的精度为4096分之一。以下为89C51单片机控制C语言程序和电路连接图。完整的工程文件及hex文件下载:http://www.51hei.com/f/tlccadc.rar 是用stc89c51单片机制作的 成品正在使用中. #include reg51.h #define uint unsigned int #define uchar unsigned char sbit cs=P1^0;
[单片机]
<font color='red'>51单片机</font>驱动12位AD转换TLC2543电路图+程序
89C51单片机I/O口模拟串行通信实现方法
目前普遍采用的MCS51 和P IC 系列单片机通常只有一个(或没有)UART异步串行 通信 接口,在应用系统中若需要多个串行接口(例如在多机通信系统中,主机既要和从机通信又要和终端通信)的情况下,通常的方法是扩展一片8251 或 8250 通用同步/异步接收发送 芯片 (USART),需额外占用单片机I/O 资源。本文介绍一种用单片机普通I/O 口实现串行通信的方法,可在单片机的最小应用系统中实现与两个以上串行接口设备的多机通信。   1.串行接口的基本通信方式 串行接口的有异步和同步两种基本通信方式。异步通信采用用异步传送格式,如图1 所示。数据发送和接收均将起始位和停止位作为开始和结束的标志。在异步通信中,起始位占用
[单片机]
89C<font color='red'>51单片机</font>I/O口模拟串行通信实现方法
MCS51单片机的数据复制程序(ASM)
MCS51单片机的数据复制程序(ASM) ;内部RAM数据复制程序 ;入口 :R0,R7 ;占用资源:A ;堆栈需求:2字节 ;出口 :R1 IBMOV :MOV A,R0 ADD A,R7 MOV R0,A MOV A,R1 ADD A,R7 MOV R1,A IBM1 :DEC R0 DEC R1 MOV A,@R0 MOV @R1,A DJNZ R7,IBM1 RET ;外部RAM数据复制程序 ;入口 :ADDPH,ADDPL,R7 ;占用资源:ACC ;堆栈需求:2字节 ;出口 :R0
[单片机]
英国研发新技术 8M宽带能流畅看在线4K
    相对传统的1080P视频而言,4K超高清视频无疑是大家更为关注的,更高的分辨率带来了更清晰的画面回放效果。但是现在4K电视节目很少,不少用户的4K电视都只能观看1080P全高清节目。因此,有很多公司在研发通过网络传输4K视频的技术。最近,欧洲广播公司与英国广播公司Sky以及V-Nova公司正在共同研发新的编码技术,以适应未来4K视频可以更好的通过网络传输。 新的4K传输编码技术将大幅降低网络带宽的使用说明     在欧洲广播联盟进行的一项调查中显示,以英国为例,根据网络4K视频的测试结果显示,22Mpbs的带宽,可以流畅传输4K超高清视频。而目前能够达到这一带宽的用户数量并不多,因此,就需要新的技术和编码方式进
[家用电子]
51单片机驱动点阵16*16左移
这个点阵左移,曾经让我......如今在朋友指导下.........主要部分在红色部分,请大家理解那里就行了!会了也没有什么!硬件:行采用74HC154+S8550,列采用74HC595! #include reg52.h #define uchar unsigned char #define uint unsigned int #define LINE P0//定义行线IO口,即74HC154控制端 #define shudu 20//字移动的速度 sbit DATA=P1^4;//74HC595数据端 sbit CLK=P1^5;//74HC595移位脉冲端 sbit CLKR=P1^6;//74HC595数据锁存端 u
[单片机]
<font color='red'>51单片机</font>驱动点阵16*16左移
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved