欢迎光临
我们一直在努力

经典游戏:用Arduino玩贪吃蛇

1111_11

==概述==

还记得曾经的旧款手机上的贪吃蛇么?可能您的脑补画面是这样的上图↑↑↑↑↑↑↑没错,今天我们就来尝试一个经典的贪吃蛇游戏,运用于强大的Arduino。

贪吃蛇游戏是一款经典的益智游戏,有PC和手机等多平台版本。既简单又耐玩。该游戏通过控制蛇头方向吃蛋,从而使得蛇变得越来越长。

本次是以小实验的方式写的,对于模块不了解的,可以先看一下我们的模块教程,了解掌握模块使用方法后,再尝试本小实验。

(对于非本店模块不提供技术支持!如果无法做通,可能是不兼容导致,请自行尝试)。

先上成品图:

20171223151414_11

所需材料:

UNO 主控版一块:点我购买

大按键模块6个:点我购买

面包线若干:点我购买

大面包板二块(按需购买):点我购买

OLED显示屏一个:点我购买

==接线图==

tanchishe11_bb_99_88

==接线方式==

OLED显示屏                       Arduino

VCC                                       5V

GND                                     GND

SDA                                        A4

SCL                                         A5

———————————————-

按键                                   Arduino

上                                         D5

下                                         D4

左                                         D3

右                                         D2

A(开始/确定键)                 D8

B(暂无,可不接)               D9

==例子程序==

/*
  * 综合中文资料门户网站:arduino365.com
  * U8G的程序对于刚入门的话比较难懂,可以找些资料学一下函数。
  * 感谢您对我们技术的支持,祝您生活愉快!
  */
#include "U8glib.h"//引用U8G头文件
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);//设置设备名称:I2C-SSD1306-128*64(OLED)
/***********************************************/
#define UP 5//定义方向键上为Arduino上的D5号引脚
#define DOWN 4//定义方向键上为Arduino上的D4号引脚
#define LEFT 3//定义方向键上为Arduino上的D3号引脚
#define RIGHT 2//定义方向键上为Arduino上的D2号引脚
#define A 8//定义方向键上为Arduino上的D8号引脚
#define B 9//定义方向键上为Arduino上的D9号引脚(暂时不用)
/***********************************************/
int box_x = 0;//定义变量
int box_y = 0;//定义变量
//int box_width = 2;
int box_x_length = 98;//x方向32  0-31
int box_y_length = 62;//y方向20  0-19
int snake_max_length = 100; //蛇身体最大长度
int snake_x[100];//蛇身x坐标
int snake_y[100];//蛇身y坐标
int snake_body_width = 3; //蛇身方块宽度(正方形)
int food_x;//食物位置坐标x
int food_y;//食物位置坐标y
int snake_length = 3; //定义初始化蛇身长度
unsigned int game_speed;//设置游戏速度
/***********************************************/
void setup(void)
{
   pinMode(UP, INPUT_PULLUP);//定义方向UP引脚状态
   pinMode(DOWN, INPUT_PULLUP);//定义方向DOWN引脚状态
   pinMode(LEFT, INPUT_PULLUP);//定义方向LEFT引脚状态
   pinMode(RIGHT, INPUT_PULLUP);//定义方向RIGHT引脚状态
   pinMode(A, INPUT_PULLUP);//定义按键A引脚状态
   pinMode(B, INPUT_PULLUP);//定义按键B引脚状态
   welcome();//欢迎界面
   delay(2000);
   chose_game();//选择界面
}
/***********************************************/
void welcome()
{
   u8g.firstPage();//第一页显示
   do
   {
     u8g.setFont(u8g_font_gdr14r);//坐标函数
     u8g.setPrintPos(0, 20);
     u8g.print("Snake Game");
     u8g.setPrintPos(0, 35);
     u8g.print("             v2.0");
     u8g.setFont(u8g_font_9x18);
     u8g.setPrintPos(0, 55);
     u8g.print("arduino365.com");
   } while (u8g.nextPage());
}
/***********************************************/
int chose_game()//对选择界面进行定义
{
   int flag = 1;
   int temp = 1;
   while (flag)
   {
     int key = read_key();
     if (key == UP)
     {
       u8g.firstPage();
       do
       {
         u8g.setFont(u8g_font_9x18);
         u8g.setPrintPos(5, 20);
         u8g.print("Snake  <");
         u8g.setPrintPos(5, 40);
         u8g.print("Player");
       } while (u8g.nextPage());
       temp = 1;
     }
     if (key == DOWN)
     {
       u8g.firstPage();
       do
       {
         u8g.setFont(u8g_font_9x18);
         u8g.setPrintPos(5, 20);
         u8g.print("Snake");
         u8g.setPrintPos(5, 40);
         u8g.print("Player  <");
       } while (u8g.nextPage());
       temp = 2;
     }
     if (key == A)
     {
       return temp;
     }
   }
}
/***********************************************/
int read_key()//对按键进行定义
{
   int key_temp;
   if (digitalRead(UP) == LOW) {
     key_temp = UP;
     return key_temp;
   }
   if (digitalRead(DOWN) == LOW) {
     key_temp = DOWN;
     return key_temp;
   }
   if (digitalRead(LEFT) == LOW) {
     key_temp = LEFT;
     return key_temp;
   }
   if (digitalRead(RIGHT) == LOW) {
     key_temp = RIGHT;
     return key_temp;
   }
   if (digitalRead(A) == LOW) {
     key_temp = A;
     return key_temp;
   }
   if (digitalRead(B) == LOW) {
     key_temp = B;
     return key_temp;
   }
   return 0;
}
/***********************************************/
void game_over()//对游戏结束进行定义
{
   u8g.firstPage();
   do
   {
     u8g.setFont(u8g_font_gdr14r);
     u8g.setPrintPos(0, 40);
     u8g.print("GAME OVER!");
     }
     
   while (u8g.nextPage()); 
   snake_length=3;
   snake_x[0] = 15; snake_y[0] = 15;//snake起始坐标
   snake_x[1] = snake_x[0]  - 1; snake_y[1] = snake_y[0];//snake起始坐标
   snake_x[2] = snake_x[1]  - 1; snake_y[2] = snake_y[1];//snake起始坐标
}

void snake()//对贪吃蛇参数进行定义
{
   int flag = 1; //标志
   snake_x[0] = 15; snake_y[0] = 15;//snake起始坐标
   snake_x[1] = snake_x[0]  - 1; snake_y[1] = snake_y[0];//snake起始坐标
   snake_x[2] = snake_x[1]  - 1; snake_y[2] = snake_y[1];//snake起始坐标
   int snake_dir=RIGHT;//初始方向 right
   game_speed=30;
   int food_flag=1;
   Serial.println("snake!");
   food();
   while (flag)
   {
     snake_frame(game_speed);
     delay(game_speed);
     switch(read_key())
     {
       case UP:
         if(snake_dir!=DOWN)
         {
           snake_dir=UP;
           break;
         }
       case DOWN:
         if(snake_dir!=UP)
         {
           snake_dir=DOWN;
           break;
         }
         case LEFT:
         if(snake_dir!=RIGHT)
         {
           snake_dir=LEFT;
           break;
         }
         case RIGHT:
         if(snake_dir!=LEFT)
         {
           snake_dir=RIGHT;
           break;
         }
         default:break;
     }
     if(snake_eat_food(snake_dir)==1)
     {
       food();
       if(snake_length<10){game_speed=30;}
       if(snake_length<30&&snake_length>=10){game_speed=20;}
       if(snake_length<50&&snake_length>=30){game_speed=10;}
       if(snake_length>=50){game_speed=0;}
     }
     else
     {
       if(snake_knock_wall(snake_dir==1))
       {
         game_over();
         flag=0;
       }
       else
       {
         if(snake_eat_body(snake_dir)==1)
         {
           game_over();
           flag=0;
         }
         else
         {
           change_con(snake_dir);
         }
       }
     }
   }
}

void snake_frame(int s)
{
   u8g.firstPage();
   do
   {
     u8g.drawFrame(box_x, box_y, box_x_length, box_y_length);
     u8g.setFont(u8g_font_5x8);
     u8g.setPrintPos(box_x_length + 1, 12);
     u8g.print("Score");
     u8g.setPrintPos(box_x_length + 1, 22);
     u8g.print((snake_length - 3) * 5);
     u8g.setPrintPos(box_x_length + 1, 46);
     u8g.print("Speed");
     u8g.setPrintPos(box_x_length + 1, 56);
     u8g.print(30-s);
     u8g.drawFrame(food_x*snake_body_width+1, food_y*snake_body_width+1, snake_body_width, snake_body_width);//显示食物
     for (int i = 0; i < snake_length; i++)//显示snake
     {
       if(i==0)
       {
         u8g.drawBox(snake_x[i]*snake_body_width+1, snake_y[i]*snake_body_width+1, snake_body_width, snake_body_width);
       }
       else
       {
         u8g.drawFrame(snake_x[i]*snake_body_width+1, snake_y[i]*snake_body_width+1, snake_body_width, snake_body_width);
       }
     }
   } while (u8g.nextPage());
}

void food()//对实物进行定义
{
   int flag = 1;
   while (flag)
   {
     food_x = random(0,(box_x_length-2)/3);
     food_y = random(0,(box_y_length-2)/3);
     for (int i = 0; i < snake_length; i++)
     {
         if((food_x==snake_x[i])&&(food_y==snake_y[i]))
         {
           break;
         }
         flag=0;
     }
   }
//  Serial.print("food_x:");
//  Serial.print(food_x);
//  Serial.print(" food_y:");
//  Serial.println(food_y);m
}

void change_con(int DIR)//移动坐标函数
{
   int temp_x[snake_length+2];
   int temp_y[snake_length+2];
   for(int i=0;i<snake_length-1;i++)//将旧坐标数据存放到temp数组  最后一位数据无效
   {
     temp_x[i]=snake_x[i];
     temp_y[i]=snake_y[i];
   }
   switch(DIR)
   {
     case RIGHT: {snake_x[0]+=1;break;}
     case LEFT: {snake_x[0]-=1;break;}
     case UP: {snake_y[0]-=1;break;}
     case DOWN: {snake_y[0]+=1;break;}
   }
   for(int i=1;i<snake_length;i++)
   {
     snake_x[i]=temp_x[i-1];
     snake_y[i]=temp_y[i-1];
   }
}

void change_pos()//吃到东西后移动函数
{
   int temp_x[snake_length+2];
   int temp_y[snake_length+2];
   for(int i=0;i<snake_length-1;i++)//将旧坐标数据存放到temp数组  最后一位数据无效
   {
     temp_x[i]=snake_x[i];
     temp_y[i]=snake_y[i];
   }
   snake_x[0]=food_x;
   snake_y[0]=food_y;
   for(int i=1;i<snake_length;i++)
   {
     snake_x[i]=temp_x[i-1];
     snake_y[i]=temp_y[i-1];
   }
}
//判断是否吃到食物 0-没有吃到 1-吃到 2-无效
int snake_eat_food(int dir)
{
   int x_temp=snake_x[0];
   int y_temp=snake_y[0];
   switch(dir)
   {
     case UP :y_temp-=1;break;
     case DOWN :y_temp+=1;break;
     case LEFT :x_temp-=1;break;
     case RIGHT :x_temp+=1;break;
   }
   if((x_temp==food_x)&&(y_temp==food_y))
   {
       snake_length+=1;
       change_pos();
       return 1;
   }
   else
   {
     return 0;
   }
}
//判断是否撞墙 0-没有撞到 1-撞到 2-无效
int snake_knock_wall(int dir)
{
   int x_temp=snake_x[0];
   int y_temp=snake_y[0];
   switch(dir)
   {
     case UP :y_temp-=1;break;
     case DOWN :y_temp+=1;break;
     case LEFT :x_temp-=1;break;
     case RIGHT :x_temp+=1;break;
   }
   if(x_temp<0||x_temp>31||y_temp<0||y_temp>19)
   {
     return 1;
   }
   else
   {
     return 0;
   }
}
//判断是否吃到自己 0-没有吃到 1-吃到 2-无效
int snake_eat_body(int dir)
{
   int x_temp=snake_x[0];
   int y_temp=snake_y[0];
   switch(dir)
   {
     case UP :y_temp-=1;break;
     case DOWN :y_temp+=1;break;
     case LEFT :x_temp-=1;break;
     case RIGHT :x_temp+=1;break;
   }
   for(int i=1;i<snake_length;i++)
   {
     if((snake_x[0]==snake_x[i])&&(snake_y[0]==snake_y[i]))
     {
       return 1;
     }
   }
   return 0;
}
/***********************************************/
//使用说明(player)主函数
void tetrs()
{
   int flag = 1;
   while (flag)
   {
       u8g.firstPage();
       do
       {
            u8g.setFont(u8g_font_gdr14r);
            u8g.setPrintPos(0, 20);
            u8g.print("1.UP:chose1");
            u8g.setPrintPos(1, 40);
            u8g.print("2:start is:A"); 
       } while (u8g.nextPage());
       delay(1000);
       flag=0;
   }
}
/***********************************************/
void loop(void)//主循环函数
{
   while (1)
   {
     switch (chose_game())
     {
       case 1: snake(); break;
       case 2: tetrs(); break;
       default:break;
     }
   }
}

==操作说明==

模块上电后进入欢迎界面,按方向键上或下,可以选择snake或者player,按下A键,进入相应的界面。

snake:贪吃蛇游戏

player:按键信息(暂无,可开发)。

贪吃蛇:通过上下左右控制方向,吃食物。触壁会死!!!!

==实验效果==

==相关下载==

库文件:https://pan.baidu.com/s/1nvadkHb

未经允许不得转载:Arduino-Maker » 经典游戏:用Arduino玩贪吃蛇

支付宝扫码打赏 微信打赏

原创文章,若帮到您,欢迎打赏

分享到:更多 ()

评论 抢沙发

评论前必须登录!

 

线上商城

中贝斯特创客空间蘑菇云创客教育