贪吃蛇---STC89C52(已修复BUG版)

这篇博客介绍了使用STC89C52单片机编写贪吃蛇游戏的过程,重点在于通过结构体管理坐标,并利用人眼延时性实现点阵显示。游戏规则包括不能穿墙以及撞到自己后需重新开始,蛇头只能向三个方向移动。作者邀请读者指出可能存在的不足。

SNACK STC89C52  (已修复BUG版)

思路:
通过结构体设置x,y坐标,对点阵进行定点处理。只需对每个点进行扫描,利用人眼的延时性即可显示snack;
还有比较关键的就是模仿,只控制第一个点,随后几个分别模仿前一个点的运动轨迹即可实现连贯跟随。:)

自定义游戏规则:
不能穿墙(考虑到界面比较小,颜色比较单一,穿墙后容易分辨不了蛇的头和尾)。    撞到自己后重新开局,头只能向三个方向移动。以snake的长度定胜负。

这里写图片描述

这里写图片描述

这里写图片描述

撞到自己重新开局

这里写图片描述
这里写图片描述

花了一个下午搞的,有不足之处请直接评论 : )

/*************************
April 10  stc89c52 snake
made by Rays
*************************/
#include<reg51.h>
#include<stdlib.h>
#include<intrins.h>
typedef unsigned int uint;
typedef unsigned char uchar;
sbit SRCLK=P3^6;
sbit RCLK=P3^5;
sbit SER=P3^4;
sbit k1=P3^1; //up
sbit k2=P3^0; //down
sbit k3=P3^2; //left
sbit k4=P3^3; //right

uchar xz[]={0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xff};
uchar yz[]={0x00,0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,0xff};
uchar len,flag,x0,y0,r,p,f;
void send(uchar dat);
void keyboard();
struct point
{
    uchar x,y;
}s[40];
void int0()
{
    len=3;
    s[0].x=3,s[0].y=1;
    s[1].x=2,s[1].y=1;
    s[2].x=1,s[2].y=1;
    flag=0;//模仿标志

    p=1;  //随机数产生标志
    f=1; 

    r=0; //结果标志
}
void delay(uint c)   //c=1,1ms
{
    uint a,b,t;
    for(t=0;t<c;t++)
    for(b=102;b>0;b--)
        for(a=3;a>0;a--);
}

void show(uchar x,uchar y)
{
    send(xz[x]);
    P0=yz[y];
}
void main()
{       
    uchar i,tmpx,tmpy,x1,y1;
    int0();
    while(1){
          tmpx=s[0].x;
          tmpy=s[0].y;
            keyboard();
            if(s[0].x==s[1].x&&s[0].y==s[1].y)
            {
                s[0].x=tmpx;
                s[0].y=tmpy;
                flag=0;
            }
            if(s[0].x==x0 && s[0].y==y0)
            {
                if(len<40) len++;
                if(s[len-2].x==s[len-3].x)
                {
                    if(s[len-2].x<s[0].x) s[len-1].x=s[len-2].x-1;
                    else s[len-1].x=s[len-2].x+1;
                    s[len-1].y=s[len-2].y;
        }
                if(s[len-2].y==s[len-3].y)
                {
                    if(s[len-2].y<s[0].y) s[len-1].y=s[len-2].y-1;
                    else s[len-1].y=s[len-2].y+1;
                    s[len-1].x=s[len-2].y;
        }
                p=1;
      }
            x1=x0,y1=y0;

    while(p){               //产生随机数     
     f=1;
        x0=rand()%9;
      y0=rand()%9;
        for(i=0;i<len;i++) 
        if(s[i].x==x0 && s[i].y==y0) f=0;
        if(f &&(x0>=1&&x0<=8)&&(y0>=1&&y0<=8))
          if(x1!=x0||y1!=y0) p=0;
   }
            if(flag){
      for(i=len-1;i>=2;i--)  //模仿
       {
          s[i].x=s[i-1].x;
                s[i].y=s[i-1].y;
       }
                s[1].x=tmpx;
                s[1].y=tmpy;
             flag=0;
         }  
          s[len].x=x0,s[len].y=y0;
            for(i=0;i<len;i++) show(s[i].y,s[i].x);
          show(0,9);             //除阴影点                
          show(s[len].y,s[len].x);  
          show(0,9);

         r=0;  //初始化结果       
         for(i=1;i<len;i++)     //判断是否撞到自己
        if(s[0].x==s[i].x &&s[0].y==s[i].y) r=1;
        if(r)
            {
                show(9,0);
                delay(500);
                int0();          //撞到自己重新开局     
             }
    }
}
void send(uchar dat)
{
    uchar a;
    SRCLK=0;
    RCLK=0;
    for(a=0;a<8;a++)
    {
        SER=dat>>7;
        dat<<=1;

        SRCLK=1;
        _nop_();
        _nop_();
        SRCLK=0;    
    }

    RCLK=1;
    _nop_();
    _nop_();
    RCLK=0;
}
void keyboard()
{
    if(k1==0)      //up
  {
     delay(2);
     if(k1==0)
     { 
         if(s[0].y<8) {s[0].y++;
               //else s[0].y=1;
         flag=1;}
      }         
      while(!k1);                  
   }     
   if(k2==0)      //down
   {
      delay(2);
      if(k2==0)
      { 
          if(s[0].y>1) {s[0].y--;
                  //else s[0].y=8;
          flag=1;}
      }                 
      while(!k2);                  
    }     
    if(k3==0)      //left
    {
       delay(2);
       if(k3==0)
       { 
           if(s[0].x>1) {s[0].x--; 
                   //else s[0].x=8;
           flag=1;}
       }         
       while(!k3);                  
      }     
      if(k4==0)      //right
      {
        delay(2);
        if(k4==0)
      { 
         if(s[0].x<8) {s[0].x++;
                 //else s[0].x=1;
         flag=1;}
      }     
       while(!k4);                  
      } 
}
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值