【STM32单片机】贪吃蛇游戏设计

2023-12-13 14:36:58


一、功能简介

本项目使用STM32F103C8T6单片机控制器,使用IIC OLED模块、按键等。

主要功能:
系统运行后,OLED显示游戏界面,可通过K1-K4键控制蛇的方向,当蛇吃到食物,得分加1;K1左,K2右,K3上,K4下。


二、软件设计

/*
作者:嗨小易(QQ:3443792007)

*/



void GUI_Init()//界面初始化
{
	OLED_Clear();
	Snake_Init();
	Food();
	OLED_Refresh();	
}

void GUI_Refresh(int map[32][12])//界面刷新
{
	int i,j,temp;
	for(i=0;i<32;i++)
	{
		for(j=0;j<12;j++)
		{
		   temp=map[i][j];
		   if(temp==2)
		   {
		       Paint_Body(i,j);  
		   }
		   else if(temp==-2)
		   {
		       Paint_Map(i,j);  
		   }
		   else if(temp==-1)
		   {
		       Paint_Food(i,j);  
		   }
	       else if(temp==0)
		   {
		      Paint_Clean(i,j);  
		   } 		  
		}
	}
	OLED_Refresh();
	
}

void Creat_map(int map[32][12])//创建地图
{
	int i,j;
	for(i=0;i<12;i++)
	{
		for(j=0;j<32;j++)
		{
  		 if(i==0||i==11)
		 {
		   map[j][i]=-2;
		 }
		 if(j==0||j==31)
		 {
		   map[j][i]=-2;
		 }
		}
	
	}
}
void Paint_Map(int x,int y)//绘制地图
{
	int i,j;
	for(i=4*y;i<4*y+4;i++)     
	{
	  for(j=4*x;j<4*x+4;j++)
	  {
		    OLED_DrawPoint(j,i+16); 
	  }
	
	}

}

void Paint_Head(int x,int y )//绘制蛇头
{
	int i,j;
	for(i=4*y;i<4*y+4;i++)     
	{
	  for(j=4*x;j<4*x+4;j++)
	  {
		    OLED_DrawPoint(j,i+16); 
	  }
	
	}
}

void Paint_Food(int x,int y )//绘制食物
{
	int i,j;
	for(i=4*y;i<4*y+4;i++)     
	{
	  for(j=4*x;j<4*x+4;j++)
	  {
		
	   if(i==4*y+1||i==4*y+2)
		{
			
			 OLED_DrawPoint(j,i+16);  
			
		}
	   if(j==4*x+1||j==4*x+2)
		{
			
			 OLED_DrawPoint(j,i+16);  
		
		} 
	  }
	
	}

}
void Paint_Tail(int x,int y )//绘制尾巴
{
	int i,j;
	for(i=4*y;i<4*y+4;i++)     
	{
	  for(j=4*x;j<4*x+4;j++)
	  {
		
	   if(i==4*y+1||i==4*y+2)
		{
			
			 OLED_DrawPoint(j,i+16);  
			
		}
	   if(j==4*x+1||j==4*x+2||j==4*x+3)
		{
			
			 OLED_DrawPoint(j,i+16);  
		
		} 
	  }
	
	}

}
void Paint_Body(int x,int y )//绘制身体
{
	int i,j;
	for(i=4*y;i<4*y+4;i++)     
	{
	  for(j=4*x;j<4*x+4;j++)
	  {
		if(i==4*y||i==4*y+3)
		{
			
			 OLED_DrawPoint(j,i+16);  
			
		}
		if(j==4*x||j==4*x+3)
		{
			
			 OLED_DrawPoint(j,i+16);  
		
		}
	  }
    }
}
void Paint_Clean(int x,int y )//清除点
{
	int i,j;
	for(i=4*y;i<4*y+4;i++)     
	{
	  for(j=4*x;j<4*x+4;j++)
	  {
		OLED_ClearPoint(j,i+16);  
	  }
	
	}
}

void Snake_Init()//蛇及食物初始化
{  int i;
   length=5;
   score=0;
   snake_Grid[0][0]=7;//x坐标,蛇头坐标
   snake_Grid[0][1]=5;//y坐标
   for(i=1;i<5;i++)
    {
        snake_Grid[i][0]=snake_Grid[0][0]-i;
        snake_Grid[i][1]=snake_Grid[0][1];  //给刚开始的蛇身几个初始坐标
    }
  	direction=RIGHT;
    Creat_map(map);
}

void Move()//移动
{
	
    int i;
	map[snake_Grid[length-1][0]][snake_Grid[length-1][1]]=0;//清除尾巴
	if(eated)               //如果吃到了食物
    {
        length++;
        eated=false;        //设置为false,不然无限变长
    }
    for(i=length-1;i>0;i--)    //从尾巴开始,每一个点的位置等于它前面一个点的位置
    {
        snake_Grid[i][0]=snake_Grid[i-1][0];
        snake_Grid[i][1]=snake_Grid[i-1][1];
    }
    switch(direction)
    {
    case UP:
        snake_Grid[0][1]--;
        break;
    case DOWN:
        snake_Grid[0][1]++;
        break;
    case LEFT:
        snake_Grid[0][0]--;
        break;
    case RIGHT:
        snake_Grid[0][0]++;
        break;
    }
	Grid_Bound();//坐标限定
	
}
void drawSnake()            //画蛇
{
    int i,x,y;
    for(i=0;i<length;i++)
    {
		x=snake_Grid[i][0];
		y=snake_Grid[i][1];
        map[x][y]=2;       
    }
}
void Get_Command()//获取键盘值
{
	int key=0;
	key=KEY_Scan(0);
	if(key)
	{
		switch(key)
		{
			case 1:if(direction!=RIGHT)         //上
                   direction=LEFT;
                   break;
			case 2:if(direction!=LEFT)           //下
                   direction=RIGHT;
                   break;
			case 3:if(direction!=DOWN)        //左
                   direction=UP;
                   break;
			case 4:if(direction!=UP)         //右
                   direction=DOWN;
                   break;
		
		}
    }
}

void  Grid_Bound()//坐标限定
{
  if(snake_Grid[0][0]==31)
		snake_Grid[0][0]=1;
  else if(snake_Grid[0][0]==0)
		snake_Grid[0][0]=30;
  else if(snake_Grid[0][1]==11)
		snake_Grid[0][1]=1;
  else if(snake_Grid[0][1]==0)
		snake_Grid[0][1]=10;  

}

bool GameOver()//游戏结束
{
	bool isGameOver=false;
	int sx=snake_Grid[0][0],sy=snake_Grid[0][1],i;//蛇头坐标
	for(i=1; i<length; i++)    //判断有没有吃到自己
    {
        if(snake_Grid[i][0]==sx&&snake_Grid[i][1]==sy)
            isGameOver=true;
    }
    return isGameOver;
}

int Chek(int i,int j)//检查地图空位
{
	if(map[i][j]!=0)
	{
		return 0;
	}
	return 1;   //是空位就返回1
}

void Food()//生成食物
{
	int i,j;
	do
	{
		i=rand()%30;                 //生成0~H-1之间的一个数
        j=rand()%10;
	
	}
	while(Chek(i,j)==0);
	map[i][j]=-1;//画出食物
}

void Eat_Food()//吃食物
{
	if(map[snake_Grid[0][0]][snake_Grid[0][1]]==-1) //如果蛇头碰到食物,就重新投放食物,并且把食物点重置为0
        {
            eated=true;            //标记已经吃到食物
			score+=1;
            Food();
            map[snake_Grid[0][0]][snake_Grid[0][1]]=0;  //去掉食物
        }
}

void Show_Score()//显示分数
{
	OLED_ShowString(30,0,"Score:",16);
	OLED_ShowNum(80,0,score,2,16);

}



三、实验现象

B站演示视频:https://space.bilibili.com/444388619
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


联系作者

专注于51单片机、STM32、国产32、DSP、Proteus、ardunio、ESP32、物联网软件开发,PCB设计,视频分享,技术交流。

文章来源:https://blog.csdn.net/Hello_Muyi/article/details/134970120
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。