⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snake.c

📁 51单片机上的贪吃蛇游戏
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <REG52.H>
sbit sound=P2^7; //这个是接峰鸣器
sbit rs = P2^0;   //H=data; L=command;
sbit rw = P2^1;   //H=read; L=write;
sbit  e = P2^2;   //input enable;
sbit busy=P0^7;   //lcd busy bit
/*---------这里是液晶的一些命令定的控制字-----------8*/
#define com_expand_command        0x40
#define base_command          0x34
#define oppsite_cursor_dec    0x10
#define open_display_oppsite  0x0D
#define clear_screen          0x01
 
/*------下面的这些反白指令没有什么用处!--------*/
#define oppsite_first_line    0x04
#define oppsite_second_line   0x05
#define oppsite_third_line    0x06
#define oppsite_forth_line    0x07
/*------上面的这些反白指令没有什么用处!--------*/
/*-------------这里是定义那个绘图时设置地址时用的------*/
#define X1_ADDRESS    0x80
#define X2_ADDRESS    0x88
#define Y_ADDRESS     0x80
/*******-----这里用来向LCD定入数据时区分命令和数据的-----*/
#define comm  0   //命令
#define dat   1   //数据!
 
#define uint  unsigned int
#define uchar unsigned char
#define uchar unsigned char
/*-----键盘扫描码定义------------------*/
#define DOWN_DOWN    0xe0  //第一键
#define UP_DOWN      0xd0  //第二键
#define RIGHT_DOWN   0xb0  //
#define LEFT_DOWN    0x70   //
/*------------屏上区域定义区---------------*/
#define RIGHT_MAX    31
#define DOWN_MAX     15
#define UP_MAX       0
#define LEFT_MAX     0
/*------------定义游戏状态--------------*/
#define GAME_OVER                0    //游戏结束了
#define GAME_RUNING              1    //游戏进行中
#define WAIT_FOR_USER_INPUT      3  //等待用户输入
#define GAME_WELCOME_SCREEN   4    //
#define SHOW_YOUR_RECORD   5//这个状态就是当游戏结束以后显示你的成绩
 

/*--------------方向定义----------------*/
#define RIGHT  0
#define LEFT   1
#define DOWN   2
#define UP     3

/*--------------定义屏幕序列号------------------*/
#define WELCOME_SCREEN  0 //第一个欢迎屏
#define WAITE_IN_PUT    1 //这是等待玩家选关的
#define YOUR_RECORD  2 //这个屏是当玩家OVER后显示他分数
#define CONGRATULATE    3 //这个是当玩家玩完一关后进入下一关时显示的
 

/*---------------------------*/
#define SNAKE_LONG   16  //定义蛇长
#define DEFAULT_SPEED 5//定义蛇的默认速度 
#define X_POT         0
#define Y_POT         1 //蛇身是一个2维数组0是放X1放Y
#define MAX_RECORD    15//这个是定义当多少分时就进入下一关
/*---------定义一种结构体---------*/
struct postion
{
  uchar x;
 uchar y ;
};//这个结构体是用来表示一些点的数据

//*-----这个结构休是用来保存一些蛇改变方向时的数据它是有蛇前进时要用来删除尾巴时要用到-----*/
 //这三点分别是头,尾,和食物
struct Snake
{
  uchar Snake_body[SNAKE_LONG][2]; //其0为头15为尾
  uchar direction;
  uchar Speed;///速度这是由用户设定的
  uchar Game_Mode;    //这个是游戏的状态如如进行中,结速了等
  struct postion Temp_Pot_Or_Last_Trail;//这里蛇在前进时用暂存数据的移过后这个里面就是上次蛇尾所在的点
  uchar soft_conter;//这个是软件计数器  用来计数T1的中断次数,到了一定数值时就让蛇前进一步
  uchar Current_screen_num;    //这个是用来保存当前所显示的屏
  uchar Currrent_Position;//保存光标所在的位置
  uchar Screen_data[2][4];//这个是更新屏上的数据时,重构数据所使用的缓存
  struct postion Food_Postion;//这个是食物的位置
  uchar Record;//游戏得分数
} ;
uchar code NO_Data[10]={"0123456789"};//{"0","1","2","3","4","5","6","7","8","9"};
/*----------------这个地方是输出到屏上面的数据--------------*/
uchar code screen_data[][64]={
                  {"    综合程序    "                  
       "开发:Crasyboye  "
       "  游戏--贪吃蛇  "
       "  按任意键继续  "
       },//第一屏
       {
       "                "
       "        第:  关"
       "    请您选关    "
       "增加/ 减少  确定"
       },
       ///////////////////////////
       {"您的得分为:    "
        "    继续努力    "
        "                "
        "  按任意键继续  "
       },
       {"                "
        "恭喜!您顺利过关"
        "  马上进下一关  "
        "  按任意键继续  "
       }
     
       };
       
 
 
/*-----变量定义--------*/
struct Snake   My_snake;
 
unsigned char KEY_WORD;
bit   KEY_DOWN;  //这个用来表示键位有按下了
 
 
/*----------函数声明-------------*/
 void inicial_timer () ; /*--------初始化两个定时器----------*/
 void voice_function() ;   /*------发音子程序-------*/
 /*---------确认某一点是否有有障碍物-----------*/
 bit  Sure_Postion_Have_pot(uchar row,uchar line);  //row是行line是列
 void Go_Ahead(); //这个函数用来使蛇向前前进一步
 bit Sure_Pot_Empty(uchar x,uchar y);   /*------------ 确认某一点是否是空点------------------*/
 void One_Step();///这个函数里蛇走一步的
 void wr_lcd (bit dat_comm,uchar content); /*-------------------写数据或指令到LCD-------------*/
 void init_lcd (void); //初始化定时器
 void chk_busy (void);  /*---------------检测忙信号----------------*/
 void Erasure();  //擦除屏幕函数 这是在绘图模式下
 void delay_ms(unsigned int ms);////延时毫秒级的
 void Erasure_Trail();  //擦尾
 void Draw_Head();//画头
 void Creat_Food();//产生一个食物并且检测食物是不是产生在蛇的身上如果是重新产生
 void Re_Build_Food_Buffer(uchar x,uchar y);//这个是用来重构缓存数据
 void Write_Food();//把食物画到屏上
 void Inicial_Game();////p初始化游戏
 void display_all_screen (uchar screen_num);//显示一整屏
 void Show_Your_Record();//显示你的成绩
 
/*------键盘扫描也是中T0中断函数--------*/
void inter_timer0() interrupt 1
{
   unsigned char b;
  TR0=0;
  P1=0xff;
  b=P1;
  b=b&0xf0;
  if(b!=0xf0)
     {   
  KEY_DOWN=1;
  KEY_WORD=b;
  voice_function();
  } 
 
 while(b!=0xf0)   //这个地方是用来消抖的
 {
     b=P1;
  b=b&0xf0;
 }
  TR0=1;

}
/*--------初始化定时器----------*/
 void inicial_timer ()
 {
  TMOD=0x11;
  EA=1;
  TR0=1;
 TR1=1;
  ET0=1;
  ET1=1;
 }
 /*=----------这是定时器1的中断用来做为游戏的系系时钟------*/
void inter_timer1() interrupt 3
{
       TR1=0;
    TR0=0;
  if(My_snake.soft_conter>=9-My_snake.Speed)
     {
  My_snake.soft_conter=0;
  if(My_snake.Game_Mode==GAME_RUNING)
      {
         
            One_Step();
            Erasure_Trail();
            Draw_Head();
    //  Write_Food();
      if(My_snake.Snake_body[0][Y_POT]==My_snake.Food_Postion.y&&My_snake.Snake_body[0][X_POT]==My_snake.Food_Postion.x)
         {
     Creat_Food();//产生一个食物并且检测食物是不是产生在蛇的身上如果是重新产生
     Write_Food();
    My_snake.Record++;
          
      }
          
       }
    else My_snake.soft_conter++;
  
  }
   else My_snake.soft_conter++;
  
  if(My_snake.Game_Mode==GAME_OVER)
   {
   Show_Your_Record();
   }
    TR1=1;
    TR0=1; 
}
 /*------发音子程序-------*/
 void voice_function()
{
  int c,e,d;
  for(d=0;d<1;d++)
  {
   
   for (c=0;c<50;c++)
   for(e=0;e<100;e++)
    sound=0;
   }
   sound=1;
}
 /*---------确认某一点是否有有障碍物-----------*/
 bit  Sure_Postion_Have_pot()  //row是行line是列
   {
     
   
   return 1;  
        
   }
/**-------------------这个是用来让蛇向前面一步-------------------**/
void Go_Ahead()
   {
     uchar i,temp_x,temp_y;
  switch (My_snake.direction)
         {
   case RIGHT:
        {
        for(i=0;i<SNAKE_LONG;i++)
     {
         if(i==0)
      {
        My_snake.Temp_Pot_Or_Last_Trail.x=My_snake.Snake_body[0][X_POT];
     My_snake.Temp_Pot_Or_Last_Trail.y=My_snake.Snake_body[0][Y_POT];
     My_snake.Snake_body[0][X_POT]++;
       } //如果是第一个点就X++
      else         
     {
       temp_x=My_snake.Snake_body[i][X_POT];
       temp_y=My_snake.Snake_body[i][Y_POT];
      My_snake.Snake_body[i][Y_POT]=My_snake.Temp_Pot_Or_Last_Trail.y;
      My_snake.Snake_body[i][X_POT]=My_snake.Temp_Pot_Or_Last_Trail.x;
      My_snake.Temp_Pot_Or_Last_Trail.x=temp_x;
      My_snake.Temp_Pot_Or_Last_Trail.y=temp_y;
      }
     
     
      }
      return;
      }
/*----------------------------------------------------------------------------*/
    case LEFT:
          {
      for(i=0;i<SNAKE_LONG;i++)
     {
         if(i==0)
      {
        My_snake.Temp_Pot_Or_Last_Trail.x=My_snake.Snake_body[0][X_POT];
     My_snake.Temp_Pot_Or_Last_Trail.y=My_snake.Snake_body[0][Y_POT];
     My_snake.Snake_body[0][X_POT]--;
       } //如果是第一个点就X++
      else         
     
     {
       temp_x=My_snake.Snake_body[i][X_POT];
       temp_y=My_snake.Snake_body[i][Y_POT];
     My_snake.Snake_body[i][X_POT]=My_snake.Temp_Pot_Or_Last_Trail.x;
      My_snake.Snake_body[i][Y_POT]=My_snake.Temp_Pot_Or_Last_Trail.y;
      My_snake.Temp_Pot_Or_Last_Trail.x=temp_x;
      My_snake.Temp_Pot_Or_Last_Trail.y=temp_y;
     }
     
     
      }
      return;
    }
/*-----------------------------------------------------------------------------*/
    case UP:
          {
      for(i=0;i<SNAKE_LONG;i++)
     {
         if(i==0)
      {
        My_snake.Temp_Pot_Or_Last_Trail.x=My_snake.Snake_body[0][X_POT];
     My_snake.Temp_Pot_Or_Last_Trail.y=My_snake.Snake_body[0][Y_POT];
     My_snake.Snake_body[0][Y_POT]--;
       } //如果是第一个点就X++
      else         
      {
      temp_x=My_snake.Snake_body[i][X_POT];
       temp_y=My_snake.Snake_body[i][Y_POT];
     My_snake.Snake_body[i][X_POT]=My_snake.Temp_Pot_Or_Last_Trail.x;
      My_snake.Snake_body[i][Y_POT]=My_snake.Temp_Pot_Or_Last_Trail.y;
      My_snake.Temp_Pot_Or_Last_Trail.x=temp_x;
      My_snake.Temp_Pot_Or_Last_Trail.y=temp_y;
      }
      }
      return;
    }
/*---------------------------------------------------------------------------*/
   case DOWN:
          {
      for(i=0;i<SNAKE_LONG;i++)
     {
         if(i==0)
      {
        My_snake.Temp_Pot_Or_Last_Trail.x=My_snake.Snake_body[0][X_POT];
     My_snake.Temp_Pot_Or_Last_Trail.y=My_snake.Snake_body[0][Y_POT];
     My_snake.Snake_body[0][Y_POT]++;
       } //如果是第一个点就X++
      else         
      {
      temp_x=My_snake.Snake_body[i][X_POT];
       temp_y=My_snake.Snake_body[i][Y_POT];
     My_snake.Snake_body[i][X_POT]=My_snake.Temp_Pot_Or_Last_Trail.x;
      My_snake.Snake_body[i][Y_POT]=My_snake.Temp_Pot_Or_Last_Trail.y;
      My_snake.Temp_Pot_Or_Last_Trail.x=temp_x;
      My_snake.Temp_Pot_Or_Last_Trail.y=temp_y;
      }
     
      }
      return ;
           }
     default:
        return;
   }
   return;
   
   }
/*------------ 确认某一点是否是空点------------------*/
bit Sure_Pot_Empty(uchar x,uchar y)   /*------------ 确认某一点是否是空点------------------*/
{
    uchar i;
   for(i=0;i<SNAKE_LONG;i++)
     {
     if(My_snake.Snake_body[i][X_POT]==x&&My_snake.Snake_body[i][Y_POT]==y)   //查遍蛇的全身看看蛇身是否在这点上
     return 0;
  }
   return 1;//如
}
/*--------------------这个函数是用来确认前面没有障碍物------------*/
bit Sure_No_Stock()
    {
   switch (My_snake.direction)
      {
   case RIGHT:  //如果向右
       {
          if((My_snake.Snake_body[0][X_POT])>=RIGHT_MAX)
                   return 0 ;
                 else  if(Sure_Pot_Empty(My_snake.Snake_body[0][X_POT]+1,My_snake.Snake_body[0][Y_POT]))
                    return 1;
               else return 0;
        }
     break;
   case LEFT:
       {
     if(My_snake.Snake_body[0][X_POT]==LEFT_MAX)
           return 0;
      else if(Sure_Pot_Empty(My_snake.Snake_body[0][X_POT]-1,My_snake.Snake_body[0][Y_POT]))
          return 1;
        else return 0;
    }
    break;
   case UP:
       {
      if(My_snake.Snake_body[0][Y_POT]==UP_MAX)
         return 0;
      else if(Sure_Pot_Empty(My_snake.Snake_body[0][X_POT],My_snake.Snake_body[0][Y_POT]-1))
           return 1;
        else return 0;
    }
    break;
   case DOWN:
       {
       if(My_snake.Snake_body[0][Y_POT]>=DOWN_MAX)
         return 0;
     else if(Sure_Pot_Empty(My_snake.Snake_body[0][X_POT],My_snake.Snake_body[0][Y_POT]+1))
          return 1;
       else return 0;
    }
    break;
     default:
       break;
   }
   return 0;
  
    }
/*-----------------------------键盘响应函数--------------*/
void Key_Respond()
{ 
   if (KEY_DOWN)
   {
     KEY_DOWN=0;
      switch(My_snake.Game_Mode)
    {
      case GAME_RUNING:
         switch (KEY_WORD)
               {
                  case DOWN_DOWN:
                      My_snake.direction=DOWN;
            break;
               case UP_DOWN:
                 My_snake.direction=UP;
            break;
              case RIGHT_DOWN:
                  My_snake.direction=RIGHT;
         break;
                 case LEFT_DOWN:
                  My_snake.direction=LEFT;
         break;
                default:
                break;
      
         }
      return;
     
    case GAME_OVER: 
             {
        display_all_screen (WAITE_IN_PUT);
        My_snake.Game_Mode=WAIT_FOR_USER_INPUT;
     wr_lcd (comm,0x34);
                  wr_lcd (comm,0x30);
                     wr_lcd (comm,0x8E);    //置AC为0
     wr_lcd(dat,NO_Data[9-My_snake.Speed]);
                
     
 
     }
     return;    //如果游戏结束了就什么也不做了

    case WAIT_FOR_USER_INPUT:
                switch (KEY_WORD)
               {
                  case DOWN_DOWN:
                      {
       if(My_snake.Speed<9)
          {
           My_snake.Speed++;
           wr_lcd (comm,0x34);
                             wr_lcd (comm,0x30);
                              wr_lcd (comm,0x8E);    //置AC为0
           wr_lcd(dat,NO_Data[9-My_snake.Speed]);
          }
       }
            break;
               case UP_DOWN:
         {
          if(My_snake.Speed>0)
                        {
         My_snake.Speed--;
            wr_lcd (comm,0x34);
                              wr_lcd (comm,0x30);
                               wr_lcd (comm,0x8E);    //置AC为0
            wr_lcd(dat,NO_Data[9-My_snake.Speed]);
         }
       }
            break;
              case RIGHT_DOWN:
                 
         break;
                 case LEFT_DOWN:
                  Inicial_Game();
         break;
                default:
                break;
         }
      return;
                          
                           break;//这里暂时还没有写好!
   case GAME_WELCOME_SCREEN:
                        {
         display_all_screen (WAITE_IN_PUT);
         My_snake.Game_Mode=WAIT_FOR_USER_INPUT;
          wr_lcd (comm,0x34);
                            wr_lcd (comm,0x30);
                             wr_lcd (comm,0x8E);    //置AC为0
            wr_lcd(dat,NO_Data[9-My_snake.Speed]);
 
         }
                                    
                            break;
         
    default:
         return;
     
   }
   }
  
    
}
/*----------------------------这个是用来确定不是按下了相反位-----------*/
bit Press_Oppsite_Direction() /* -------这个是用来确定不是按下了相反位-------*/
 {
 switch(My_snake.direction)
    {
 case RIGHT:
      if(My_snake.Snake_body[0][Y_POT]==My_snake.Snake_body[1][Y_POT]&&My_snake.Snake_body[0][X_POT]+1==My_snake.Snake_body[1][X_POT])
     return 1;
     break;
 case LEFT:
      if(My_snake.Snake_body[0][Y_POT]==My_snake.Snake_body[1][Y_POT]&&My_snake.Snake_body[0][X_POT]-1==My_snake.Snake_body[1][X_POT])
     return 1;
     break;
 case UP:
      if(My_snake.Snake_body[0][X_POT]==My_snake.Snake_body[1][X_POT]&&My_snake.Snake_body[0][Y_POT]-1==My_snake.Snake_body[1][Y_POT])
       return 1;
    break;
    case DOWN:
      if(My_snake.Snake_body[0][X_POT]==My_snake.Snake_body[1][X_POT]&&My_snake.Snake_body[0][Y_POT]+1==My_snake.Snake_body[1][Y_POT])
     return 1;
    break;
 default:
      return 0;
      break;
    }
 return 0;
 }
void One_Step()///这个函数里蛇走一步的
{
  if(My_snake.Game_Mode==GAME_RUNING)    //如果在游戏中的话!
    {
    switch (My_snake.direction)
    {
     case RIGHT:
       {
        if(Press_Oppsite_Direction())
         {
      My_snake.direction=LEFT;
         return ;      //如果是按了相反方向那么就返回并把方向转过来
      }
      else if(Sure_No_Stock()) //看看有障碍物 么
         {
       Go_Ahead();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -