51单片机 贪吃蛇 OLED显示屏

本人零基础在B站上学习完江科大的51单片机入门后做的一个实战项目

完整代码百度网盘链接:
链接:https://pan.baidu.com/s/1DZfGqGllyQu2fWCMP1eoIQ 
提取码:tc99

文末介绍了我所购OLED显示屏规格

ffac50d7110a46d68637f4494598b59e.png

main.c 


#include <REGX52.H>
#include "oled.h"
#include "snack.h"
#include "MatrixKey.h"
#include "Timer0.h"
//游戏延时
unsigned char time= 500;

static unsigned char T0Count;
 int main(void)
 {	
	 OLED_Init();
	 OLED_Clear(); 
	 Timer0_Init();
	 initSnake();
	 InitFood();
	 displaySnakeOnScreen();
	 while(1) 
	 {	//检测按键按下
		KeyDown();
        //随机生成食物,随机因子T0Count
		GenerateFood(T0Count);
        //判断是否吃到食物
		isGetFood();
        //检测蛇的生存状态
		CheckCollision();
        //检测游戏胜利	
		GameSucess();
	 }
}


void Timer0() interrupt 1
{	
	 TL0=0X18;
	 TH0=0XFC;
	 T0Count++;
	if(T0Count == time)
     {		
		T0Count=0;
	    moveSnake();
	 }
}

snake.c【各个函数的功能我已经在注释中写好了】

#include "oled.h"
#include "snack.h"
#include "Delay.h"
#include <REGX52.H>

#define OLED_WIDTH 16 //定义游戏画面宽度
#define OLED_HEIGHT 8 //定义游戏画面高度

//动画节点数据
unsigned char body[]={0xFF,0xFF,0xC3,0xC3,0xC3,0xC3,0xFF,0xFF};
//蛇身长度
unsigned char snake_length;
//控制上下左右的不同模式
unsigned char MODE;
//食物是否存在标志位
unsigned char flag=0;

//定义蛇的结构体
typedef struct {
	unsigned char x;// 蛇身节点横坐标
	unsigned char  y;// 蛇身节点纵坐标
}Snake;

Snake snake[20];

//定义食物的结构体
typedef struct {
	
    u8 x;//食物节点横坐标
    u8 y;//食物节点纵坐标
} Food;

Food food;

// 显示动画节点
void ShowNode(unsigned char x,unsigned char y)
{
	u8 t;
	OLED_Set_Pos(x*8,y);	
    for(t=0;t<8;t++)
		{
			OLED_WR_Byte(body[t],OLED_DATA);
     }		
}

//覆盖动画节点
void OverrideTail(unsigned char x, unsigned char y)
{
   u8 i;
   OLED_Set_Pos(x*8,y);
   for(i=0;i<8;i++)
   {
      OLED_WR_Byte(0x00,OLED_DATA);
   }
 
}

// 初始化蛇
void initSnake() {
	snake_length=3;
    snake[0].x = 6;
    snake[0].y = 3;	
	snake[1].x = 7;
    snake[1].y = 3;	
	snake[2].x = 8;
    snake[2].y = 3;
}


// 将蛇显示在屏幕上
void displaySnakeOnScreen() {
		unsigned char i;
			// 显示蛇身节点
		for(i=0;i<snake_length;i++){
			ShowNode(snake[i].x,snake[i].y);
		}

}

//检测按键按下
void KeyDown(){
	//定义局部静态变量KeyNum接受矩阵键盘的key值
	static unsigned char KeyNum;
	KeyNum = MatrixKey();
	switch(KeyNum){
		//上键3
		case 3:
			if(  MODE!=1 && MODE!=2){
				MODE=1;
			}
			break;
			//下键11
		case 11:
			if(  MODE!=1 && MODE!=2){
				MODE=2;
			}
			break;
            //左键6
		case 6:
			if(  MODE!=3 && MODE!=4){
				MODE=3;
			}
			break;
            //右键8
		case 8:
			if(  MODE!=3 && MODE!=4){
				MODE=4;
			}
			break;
	}
}

//显示游戏信息
void ShowMessage(u8 *message){	
	 OLED_Clear();
	 OLED_ShowString( 0,3, message,16);	
}

//检测蛇的生存状态
void CheckCollision() {
		u8 i;
		//检查蛇是否撞墙
    if (snake[0].x <= 0 || snake[0].x >= OLED_WIDTH || 
			snake[0].y <= 0 ||snake[0].y >= OLED_HEIGHT) {
            //关闭定时器
				TR0=0;
            //显示失败信息
                ShowMessage(" hit the wall!");
       
    }
    
    // 检查蛇是否撞到自身    
    for ( i = 1; i < snake_length; ++i) {
        if (snake[0].x == snake[i].x &&  
					snake[0].y == snake[i].y) {
                        //关闭定时器
						TR0=0;
                     //显示失败信息
               ShowMessage("Snake hit itself!");
           
        }
    }
    
   
}

//初始化食物
void InitFood(){
	food.x = 2;
	food.y = 4;
	ShowNode(food.x,food.y);
}

//食物被吃掉后,随机生成食物
void GenerateFood(unsigned char rand) {
		u8 i;
		if(flag==1){
			 do {
        food.x = rand % (OLED_WIDTH);
        food.y = rand % (OLED_HEIGHT);
        // 检查食物的位置是否和身体重叠
        for (i = 0; i < snake_length; i++) {
            if (food.x == snake[i].x && food.y == snake[i].y) {
                break;  // 位置重叠,需要重新生成食物
            }
        }
    } while (i != snake_length);  //只有在生成食物位置不和蛇身体重叠时才跳出循环
    snake_length++;
    ShowNode(food.x, food.y);
		}
   
	
}

//判断是否吃到食物
void isGetFood(){                                                                                                                                                                                                   
	if(snake[0].x == food.x&&snake[0].y==food.y){
		flag=1;
	}	else{
		flag=0;
	}
}

//控制蛇的移动
void moveSnake() {
	  u8 i;
    switch (MODE) {
        case 1:
                             if(flag==0)
							OverrideTail(snake[snake_length-1].x,snake[snake_length-1].y);
            //控制蛇往上走
							for ( i = snake_length - 1; i > 0; i--) {
									snake[i].x = snake[i - 1].x;
									snake[i].y = snake[i - 1].y;
							}
							snake[0].y -= 1;
							ShowNode(snake[0].x,snake[0].y);														
						
					 break;
														
        case 2:
            //控制蛇往下走
						if(flag==0)//没吃到食物时消除蛇尾
						OverrideTail(snake[snake_length-1].x,snake[snake_length-1].y);
							
						 for ( i = snake_length - 1; i > 0; i--) {
                snake[i].x = snake[i - 1].x;
                snake[i].y = snake[i - 1].y;
            }
          
            snake[0].y += 1;
						ShowNode(snake[0].x,snake[0].y);
		
            break;

        case 3:
            // 控制蛇往左走
						if(flag==0)
						OverrideTail(snake[snake_length-1].x,snake[snake_length-1].y);
            for ( i = snake_length - 1; i > 0; i--) {
                snake[i].x = snake[i - 1].x;
                snake[i].y = snake[i - 1].y;
            }
         
            snake[0].x -= 1;
						ShowNode(snake[0].x,snake[0].y);

						
            break;

        case 4:
            //控制蛇往右走
						if(flag==0)
						OverrideTail(snake[snake_length-1].x,snake[snake_length-1].y);
            for ( i = snake_length - 1; i > 0; i--) {
                snake[i].x = snake[i - 1].x;
                snake[i].y = snake[i - 1].y;
            }
            
            snake[0].x += 1;
						ShowNode(snake[0].x,snake[0].y);
            break;

        default:
            break;
    }
}
//游戏胜利
void GameSucess(){
	if(snake_length>=20){
		ShowMessage("GAME SUCESS!");
	}
}

为了游戏的操作方便,我采用了矩阵键盘作为操作键,但是由此带来的一些延迟也影响了按键的反映灵敏度,同时蛇吃到食物后的加长和食物的产生存在一些bug,希望后续改进

最后再介绍一下我的OLED显示屏规格,1.3寸,4针 已焊接,IIC通信,电源可接3.3v至5v

SCL线接的是P10引脚,SDA线 P11 引脚

希望能给到现在也在学习51单片机的伙伴们一些启发 

  • 14
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
贪吃蛇是一种经典的游戏,可以用51单片机OLED实现。以下是一份简单的贪吃蛇代码示例: ``` #include<reg52.h> #include"OLED.h" #include"snake.h" sbit button_up=P3^3; sbit button_down=P3^4; sbit button_left=P3^5; sbit button_right=P3^6; void delay(unsigned int i) { unsigned char j; while(i--) for(j=0;j<125;j++); } void main() { OLED_Init(); //初始化OLED屏幕 Snake_Init(); //初始化贪吃蛇游戏 while(1) { Snake_Control(); //控制贪吃蛇的移动方向 Snake_Move(); //移动贪吃蛇 Snake_Eat(); //判断贪吃蛇是否吃到了食物 OLED_Display(); //在OLED屏幕上显示贪吃蛇游戏画面 delay(500); //延时一段时间,控制贪吃蛇移动的速度 } } ``` 上面的代码中,我们首先初始化了OLED屏幕和贪吃蛇游戏。然后在主循环中,我们不断地控制贪吃蛇的移动、判断贪吃蛇是否吃到了食物,并在OLED屏幕上显示贪吃蛇游戏画面。最后,我们延时一段时间,以控制贪吃蛇移动的速度。 在代码中,我们还定义了四个按键,用于控制贪吃蛇的移动方向。在Snake_Control函数中,我们检测按键是否按下,并根据按键的不同来控制贪吃蛇的移动方向。在Snake_Move函数中,我们根据贪吃蛇的移动方向来移动贪吃蛇,并检测贪吃蛇是否碰到了边界或自身。在Snake_Eat函数中,我们检测贪吃蛇是否吃到了食物,并在贪吃蛇吃到食物的时候生成新的食物。 通过以上的代码实现,我们可以用51单片机OLED屏幕实现一个简单的贪吃蛇游戏。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值