基于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-05 13:10

51单片机-按键的中断检测
接着昨天,继续说按键的事。昨天说的是扫描检测,今个说一下中断检测。先插播一个小故事~~ 当年我和凯凯学单片机的时候,我用扫描检测的方法做的项目,他用中断检测的方法做的项目。当我俩坐一起交流按键检测的方式时,他火了,直接跳起来跟我吼:你不用中断怎么检测? 当时我就意识到他可能陷入了只能用中断的误区,然后就乐呵呵的说:用扫描啊~ 他继续吼,我继续乐,我俩就这样陷入了死循环。终于都累了,然后把程序和原理给他看,了解~ 在STC89C52单片机上,具有外部中断功能的引脚有两个:P3.2 –INT0 和 P3.3-INT1。上电默认的情况下,他们是普通IO引脚;当配置好相关寄存器之后,他们就变成
[单片机]
学<font color='red'>51单片机</font>-按键的中断检测
C51单片机编程规范
1单片机C51编程规范- 前言   为了提高源程序的质量和可维护性,从而最终提高软件产品生产力,特编写此规范。 2 单片机C51编程规范-范围   本标准规定了程序设计人员进行程序设计时必须遵循的规范。本规范主要针对C51编程语言和keil编译器而言,包括排版、注释、命名、变量使用、代码可测性、程序效率、质量保证等内容。 3 单片机C51编程规范-总则 l 格式清晰 l 注释简明扼要 l 命名规范易懂 l 函数模块化 l 程序易读易维护 l 功能准确实现 l 代码空间效率和时间效率高 l 适度的可扩展性 4 单片机C51编程规范-数据类型定义 编程时统一采用下述新类型名的方式定义数据类型。 建立一个datatype.h文件
[单片机]
爆料大神再发疑似“iPhone 8”的真机模型
随着时间的推移,距离万众期待的“iPhone 8”的正式发布也越来越近了,按照过去几年的惯例,苹果将会在 9 月份发布新一代的旗舰。越来越多的曝光图开始出现在网络上,似乎我们距离这款设备的真机也越来越近。这不,爆料大神@OnLeaks 就继续向我们展示着疑似“iPhone 8”的真机模型。 从他今天发出的这些照片来看,这款“iPhone 8”基本上和此前的传闻一致。这款“iPhone 8”相比前代采用了全新的设计,屏占比增大了不少,这主要得益于新 iPhone 采用的全面屏设计,以及屏幕正面上方的“额头”新设计所得出的空间。其它外观方面,最明显的改动就是它采用了垂直双摄的布局,另外可以看到电源键有稍微加长了的感觉。另外据消息透露,
[手机便携]
5. 8GHz WiMAX宽带无线通信射频系统设计
  本设计主要是参照802. 16d 固定无线传输宽带技术标准,是针对WiMAX 宽带无线接入产品而设计的射频系统,它的作用是为基带信号处理单元提供零中频基带信号或基带I、Q 信号无线的收发通道。    0   引言   固定WiMAX 标准基于正交频分复用( OFDM) 技术,使用256 个副载波; 该标准支持1. 75~ 28 MHz范围内的多个信道带宽,同时支持多种不同的调制方案,包括BPSK、QPSK、16QAM 和64QAM。由于信号宽带及高调制方式等多项技术参数导致射频设计充满挑战性。    1   主要芯片完成功能   本设备采用超外差时分双工方式来完成设计,在符合WiMAX 标准的射频套片推出之前,
[网络通信]
51单片机RTL8019AS网卡驱动程序
SNMP网管板使用了RTL8019AS 10M ISA网卡芯片接入以太网。选它的好处是:NE2000兼容,软件移植性好;接口简单不用转换芯片如PCI-ISA桥;价格便宜2.1$/片(我的购入价为22元RMB/片);带宽充裕(针对51);较长一段时间内不会停产。8019有3种配置模式:跳线方式、即插即用P&P方式、串行Flash配置方式。为了节省成本,我去掉了9346而使用X5045作为闪盘存储MAC地址和其他可配置信息。P&P模式用在PC机中,这里用不上。只剩下跳线配置模式可用,它的电路设计参考REALTEK提供的DEMO板图纸。一天时间就可以完成,相对来说硬件设计比较简单。   与这部分硬件相对应的软件是网卡驱动。所谓驱动程序
[单片机]
<font color='red'>51单片机</font>RTL8019AS网卡驱动程序
51单片机DS18B20温度测量
大家好,通过以前的学习,我们已经对51单片机综合学习系统的使用方法及学习方式有所了解与熟悉,学会了步进电机控制的基本知识,体会到了综合学习系统的易用性与易学性,这一期我们将一起学习数字温度传感器DS18B20的基本原理与使用方法。 先看一下我们将要使用的51单片机综合学习系统能完成哪些实验与产品开发工作:分别有流水灯,数码管显示,液晶显示,按键开关,蜂鸣器奏乐,继电器控制,IIC总线,SPI总线,PS/2实验,AD模数转换,光耦实验,串口通信,红外线遥控,无线遥控,温度传感,步进电机控制等等。 单总线温度传感器DS18B20简介 DS18B20是DALLAS公司生产的单总线式数字温度传感器,它具有微型化、低功耗
[单片机]
《世上只有妈妈好》51单片机C语言程序
//《世上只有妈妈好》51单片机C语言程序 //2007-5-22 作者:徐学军 //注意有一个51单片机汇编语言程序与之对应 //此程序在硬件上调试通过 //本程序的单片机晶振采用11.0592MHZ #include reg51.h sbit speaker=P1^7; unsigned char timer0h,timer0l,time; //世上只有妈妈好数据表 code unsigned char sszymmh ={ 6,2,3,
[单片机]
HTC One M8高配版曝光:5.5寸屏2K屏幕
    5月7日上午消息,不光三星在准备Galaxy S5的高配版,现有消息表示,HTC也在准备推出M8的高级版。   据悉,HTC One M8 Prime版将会配备5.5寸屏,分辨率为1440×2560像素,同时搭载主频为2.3GHz的高通APQ8084处理器,内置基带为MDM9X35,支持LTE网络,内置RAM为3GB。依然是双摄像头的设计,不过主摄像头变成了1800万像素。   目前关于HTC M8 Prime的具体配置以及价格,上市时间等信息我们都尚未得知。(基德)
[手机便携]
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件
更多往期活动
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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