找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 14176|回复: 18
收起左侧

Arduino UNO U8glib贪吃蛇游戏设计与制作 附程序

  [复制链接]
ID:255921 发表于 2018-1-18 20:45 | 显示全部楼层 |阅读模式
本次是以小实验的方式写的,对于模块不了解的,可以先看一下我们的模块教程,了解掌握模块使用方法后,再尝试本小实验。该小实验仅供思维学习扩展
Open-Live-WriterArduino_81C420171223151414_11_thumb.jpg
所需材料:
UNO 主控版一块
按键模块6
0.96oled i2c ssd1306
==接线方式==
OLED显示屏                       Arduino
VCC                                       5V
GND                                     GND
SDA                                        A4
SCL                                         A5

———————————————-
按键                                   Arduino
上                                         D5
下                                         D4
左                                         D3
右                                         D2
A(开始/确定键)                 D8
B(暂无,可不接)               D9
==操作说明==
模块上电后进入欢迎界面,按方向键上或下,可以选择snake或者player,按下A键,进入相应的界面。
snake:贪吃蛇游戏
player:按键信息(暂无,可开发)。
贪吃蛇:通过上下左右控制方向,吃食物。触壁会死!!!!


Arduino源程序如下:
  1. #include "U8glib.h"//引用U8G头文件
  2. U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);//设置设备名称:I2C-SSD1306-128*64(OLED)
  3. /***********************************************/
  4. #define UP 5//定义方向键上为Arduino上的D5号引脚
  5. #define DOWN 4//定义方向键上为Arduino上的D4号引脚
  6. #define LEFT 3//定义方向键上为Arduino上的D3号引脚
  7. #define RIGHT 2//定义方向键上为Arduino上的D2号引脚
  8. #define A 8//定义方向键上为Arduino上的D8号引脚
  9. #define B 9//定义方向键上为Arduino上的D9号引脚(暂时不用)
  10. /***********************************************/
  11. int box_x = 0;//定义变量
  12. int box_y = 0;//定义变量
  13. //int box_width = 2;
  14. int box_x_length = 98;//x方向32  0-31
  15. int box_y_length = 62;//y方向20  0-19
  16. int snake_max_length = 100; //蛇身体最大长度
  17. int snake_x[100];//蛇身x坐标
  18. int snake_y[100];//蛇身y坐标
  19. int snake_body_width = 3; //蛇身方块宽度(正方形)
  20. int food_x;//食物位置坐标x
  21. int food_y;//食物位置坐标y
  22. int snake_length = 3; //定义初始化蛇身长度
  23. unsigned int game_speed;//设置游戏速度
  24. /***********************************************/
  25. void setup(void)
  26. {
  27.    pinMode(UP, INPUT_PULLUP);//定义方向UP引脚状态
  28.    pinMode(DOWN, INPUT_PULLUP);//定义方向DOWN引脚状态
  29.    pinMode(LEFT, INPUT_PULLUP);//定义方向LEFT引脚状态
  30.    pinMode(RIGHT, INPUT_PULLUP);//定义方向RIGHT引脚状态
  31.    pinMode(A, INPUT_PULLUP);//定义按键A引脚状态
  32.    pinMode(B, INPUT_PULLUP);//定义按键B引脚状态
  33.    welcome();//欢迎界面
  34.    delay(2500);
  35.    chose_game();//选择界面
  36. }
  37. /***********************************************/
  38. void welcome()
  39. {
  40.    u8g.firstPage();//第一页显示
  41.    do
  42.    {
  43.      u8g.setFont(u8g_font_gdr14r);//坐标函数
  44.      u8g.setPrintPos(0, 20);
  45.      u8g.print("Snake Game");
  46.      u8g.setPrintPos(0, 38);
  47.      u8g.print("             v2.0");
  48.      u8g.setFont(u8g_font_9x18);
  49.      u8g.setPrintPos(0, 55);
  50.      u8g.print("Formatmemory");
  51.    } while (u8g.nextPage());
  52. }
  53. /***********************************************/
  54. int chose_game()//对选择界面进行定义
  55. {
  56.    int flag = 1;
  57.    int temp = 1;
  58.    while (flag)
  59.    {
  60.      int key = read_key();
  61.      if (key == UP)
  62.      {
  63.        u8g.firstPage();
  64.        do
  65.        {
  66.          u8g.setFont(u8g_font_9x18);
  67.          u8g.setPrintPos(5, 20);
  68.          u8g.print("Snake  <");
  69.          u8g.setPrintPos(5, 40);
  70.          u8g.print("Player");
  71.        } while (u8g.nextPage());
  72.        temp = 1;
  73.      }
  74.      if (key == DOWN)
  75.      {
  76.        u8g.firstPage();
  77.        do
  78.        {
  79.          u8g.setFont(u8g_font_9x18);
  80.          u8g.setPrintPos(5, 20);
  81.          u8g.print("Snake");
  82.          u8g.setPrintPos(5, 40);
  83.          u8g.print("Player <");
  84.        } while (u8g.nextPage());
  85.        temp = 2;
  86.      }
  87.      if (key == A)
  88.      {
  89.        return temp;
  90.      }
  91.    }
  92. }
  93. /***********************************************/
  94. int read_key()//对按键进行定义
  95. {
  96.    int key_temp;
  97.    if (digitalRead(UP) == LOW) {
  98.      key_temp = UP;
  99.      return key_temp;
  100.    }
  101.    if (digitalRead(DOWN) == LOW) {
  102.      key_temp = DOWN;
  103.      return key_temp;
  104.    }
  105.    if (digitalRead(LEFT) == LOW) {
  106.      key_temp = LEFT;
  107.      return key_temp;
  108.    }
  109.    if (digitalRead(RIGHT) == LOW) {
  110.      key_temp = RIGHT;
  111.      return key_temp;
  112.    }
  113.    if (digitalRead(A) == LOW) {
  114.      key_temp = A;
  115.      return key_temp;
  116.    }
  117.    if (digitalRead(B) == LOW) {
  118.      key_temp = B;
  119.      return key_temp;
  120.    }
  121.    return 0;
  122. }
  123. /***********************************************/
  124. void game_over()//对游戏结束进行定义
  125. {
  126.    u8g.firstPage();
  127.    do
  128.    {
  129.      u8g.setFont(u8g_font_gdr14r);
  130.      u8g.setPrintPos(0, 40);
  131.      u8g.print(" GAME OVER!");
  132.      }
  133.       
  134.    while (u8g.nextPage());  
  135.    snake_length=3;
  136.    snake_x[0] = 15; snake_y[0] = 15;//snake起始坐标
  137.    snake_x[1] = snake_x[0]  - 1; snake_y[1] = snake_y[0];//snake起始坐标
  138.    snake_x[2] = snake_x[1]  - 1; snake_y[2] = snake_y[1];//snake起始坐标
  139. }

  140. void snake()//对贪吃蛇参数进行定义
  141. {
  142.    int flag = 1; //标志
  143.    snake_x[0] = 15; snake_y[0] = 15;//snake起始坐标
  144.    snake_x[1] = snake_x[0]  - 1; snake_y[1] = snake_y[0];//snake起始坐标
  145.    snake_x[2] = snake_x[1]  - 1; snake_y[2] = snake_y[1];//snake起始坐标
  146.    int snake_dir=RIGHT;//初始方向 right
  147.    game_speed=30;
  148.    int food_flag=1;
  149.    Serial.println("snake!");
  150.    food();
  151.    while (flag)
  152.    {
  153.      snake_frame(game_speed);
  154.      delay(game_speed);
  155.      switch(read_key())
  156.      {
  157.        case UP:
  158.          if(snake_dir!=DOWN)
  159.          {
  160.            snake_dir=UP;
  161.            break;
  162.          }
  163.        case DOWN:
  164.          if(snake_dir!=UP)
  165.          {
  166.            snake_dir=DOWN;
  167.            break;
  168.          }
  169.          case LEFT:
  170.          if(snake_dir!=RIGHT)
  171.          {
  172.            snake_dir=LEFT;
  173.            break;
  174.          }
  175.          case RIGHT:
  176.          if(snake_dir!=LEFT)
  177.          {
  178.            snake_dir=RIGHT;
  179.            break;
  180.          }
  181.          default:break;
  182.      }
  183.      if(snake_eat_food(snake_dir)==1)
  184.      {
  185.        food();
  186.        if(snake_length<10){game_speed=30;}
  187.        if(snake_length<30&&snake_length>=10){game_speed=20;}
  188.        if(snake_length<50&&snake_length>=30){game_speed=10;}
  189.        if(snake_length>=50){game_speed=0;}
  190.      }
  191.      else
  192.      {
  193.        if(snake_knock_wall(snake_dir==1))
  194.        {
  195.          game_over();
  196.          flag=0;
  197.        }
  198.        else
  199.        {
  200.          if(snake_eat_body(snake_dir)==1)
  201.          {
  202.            game_over();
  203.            flag=0;
  204.          }
  205.          else
  206.          {
  207.            change_con(snake_dir);
  208.          }
  209.        }
  210.      }
  211.    }
  212. }

  213. void snake_frame(int s)
  214. {
  215.    u8g.firstPage();
  216.    do
  217.    {
  218.      u8g.drawFrame(box_x, box_y, box_x_length, box_y_length);
  219.      u8g.setFont(u8g_font_5x8);
  220.      u8g.setPrintPos(box_x_length + 1, 12);
  221.      u8g.print("Score");
  222.      u8g.setPrintPos(box_x_length + 1, 22);
  223.      u8g.print((snake_length - 3) * 5);
  224.      u8g.setPrintPos(box_x_length + 1, 46);
  225.      u8g.print("Speed");
  226.      u8g.setPrintPos(box_x_length + 1, 56);
  227.      u8g.print(30-s);
  228.      u8g.drawFrame(food_x*snake_body_width+1, food_y*snake_body_width+1, snake_body_width, snake_body_width);//显示食物
  229.      for (int i = 0; i < snake_length; i++)//显示snake
  230.      {
  231.        if(i==0)
  232.        {
  233.          u8g.drawBox(snake_x[i]*snake_body_width+1, snake_y[i]*snake_body_width+1, snake_body_width, snake_body_width);
  234.        }
  235.        else
  236.        {
  237.          u8g.drawFrame(snake_x[i]*snake_body_width+1, snake_y[i]*snake_body_width+1, snake_body_width, snake_body_width);
  238.        }
  239.      }
  240.    } while (u8g.nextPage());
  241. }

  242. void food()//对实物进行定义
  243. {
  244.    int flag = 1;
  245.    while (flag)
  246.    {
  247.      food_x = random(0,(box_x_length-2)/3);
  248.      food_y = random(0,(box_y_length-2)/3);
  249.      for (int i = 0; i < snake_length; i++)
  250.      {
  251.          if((food_x==snake_x[i])&&(food_y==snake_y[i]))
  252.          {
  253.            break;
  254.          }
  255.          flag=0;
  256.      }
  257.    }
  258. //  Serial.print("food_x:");
  259. //  Serial.print(food_x);
  260. //  Serial.print(" food_y:");
  261. //  Serial.println(food_y);m
  262. }

  263. void change_con(int DIR)//移动坐标函数
  264. {
  265.    int temp_x[snake_length+2];
  266.    int temp_y[snake_length+2];
  267.    for(int i=0;i<snake_length-1;i++)//将旧坐标数据存放到temp数组  最后一位数据无效
  268.    {
  269.      temp_x[i]=snake_x[i];
  270.      temp_y[i]=snake_y[i];
  271.    }
  272.    switch(DIR)
  273.    {
  274.      case RIGHT: {snake_x[0]+=1;break;}
  275.      case LEFT: {snake_x[0]-=1;break;}
  276.      case UP: {snake_y[0]-=1;break;}
  277.      case DOWN: {snake_y[0]+=1;break;}
  278.    }
  279.    for(int i=1;i<snake_length;i++)
  280.    {
  281.      snake_x[i]=temp_x[i-1];
  282.      snake_y[i]=temp_y[i-1];
  283.    }
  284. }

  285. void change_pos()//吃到东西后移动函数
  286. {
  287.    int temp_x[snake_length+2];
  288.    int temp_y[snake_length+2];
  289.    for(int i=0;i<snake_length-1;i++)//将旧坐标数据存放到temp数组  最后一位数据无效
  290.    {
  291.      temp_x[i]=snake_x[i];
  292.      temp_y[i]=snake_y[i];
  293.    }
  294.    snake_x[0]=food_x;
  295.    snake_y[0]=food_y;
  296.    for(int i=1;i<snake_length;i++)
  297.    {
  298.      snake_x[i]=temp_x[i-1];
  299.      snake_y[i]=temp_y[i-1];
  300.    }
  301. }
  302. //判断是否吃到食物 0-没有吃到 1-吃到 2-无效
  303. int snake_eat_food(int dir)
  304. {
  305.    int x_temp=snake_x[0];
  306.    int y_temp=snake_y[0];
  307.    switch(dir)
  308.    {
  309.      case UP :y_temp-=1;break;
  310.      case DOWN :y_temp+=1;break;
  311.      case LEFT :x_temp-=1;break;
  312.      case RIGHT :x_temp+=1;break;
  313.    }
  314.    if((x_temp==food_x)&&(y_temp==food_y))
  315.    {
  316.        snake_length+=1;
  317.        change_pos();
  318.        return 1;
  319.    }
  320.    else
  321.    {
  322.      return 0;
  323.    }
  324. }
  325. //判断是否撞墙 0-没有撞到 1-撞到 2-无效
  326. int snake_knock_wall(int dir)
  327. {
  328. …………
  329. …………
  330. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
tanshishe.zip (2.59 KB, 下载次数: 124)

评分

参与人数 2黑币 +105 收起 理由
啦啦啦嘟嘟 + 5
admin + 100 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:295090 发表于 2018-3-27 10:41 | 显示全部楼层
兄弟,把你的代码粘贴到Arduino中调试出现这个问题,求解决
错误.png
回复

使用道具 举报

ID:255921 发表于 2018-3-29 20:20 | 显示全部楼层
ssss1234 发表于 2018-3-27 10:41
兄弟,把你的代码粘贴到Arduino中调试出现这个问题,求解决

你开发板型号啊 选nano
回复

使用道具 举报

ID:313997 发表于 2018-4-25 00:24 | 显示全部楼层
按键脚怎么接
回复

使用道具 举报

ID:319356 发表于 2018-4-30 14:18 | 显示全部楼层
支持一下!!
回复

使用道具 举报

ID:317322 发表于 2018-5-1 09:40 | 显示全部楼层
学习一下,字数补丁
回复

使用道具 举报

ID:322213 发表于 2018-5-4 16:45 | 显示全部楼层
谢谢楼主分享
回复

使用道具 举报

ID:330315 发表于 2018-5-15 13:22 | 显示全部楼层
好东东呀
回复

使用道具 举报

ID:349602 发表于 2018-6-20 15:14 | 显示全部楼层
henlihai henyoubangzhu
回复

使用道具 举报

ID:355570 发表于 2018-6-20 22:10 | 显示全部楼层
链接:https://pan.baidu.com/s/1shSINmNxyEVF92AIvrIKjQ 密码:qeyb
楼主分享的文件,后来人,没有黒币的,这个下载
回复

使用道具 举报

ID:356931 发表于 2018-8-19 18:00 | 显示全部楼层
请问整个线路怎么连啊?开关什么的
回复

使用道具 举报

ID:539976 发表于 2019-5-16 16:44 | 显示全部楼层
叶耀雷 发表于 2018-6-20 22:10
链接:https://pan.baidu.com/s/1shSINmNxyEVF92AIvrIKjQ 密码:qeyb
楼主分享的文件,后来人,没有黒币的 ...

兄弟打不开,能再发一下吗
回复

使用道具 举报

ID:603158 发表于 2019-8-27 11:44 | 显示全部楼层

谢谢楼主分享
回复

使用道具 举报

ID:411959 发表于 2019-9-23 20:37 | 显示全部楼层
我编译有问题,,,难受
回复

使用道具 举报

ID:618235 发表于 2019-9-30 08:57 | 显示全部楼层
感谢分享
回复

使用道具 举报

ID:671876 发表于 2019-12-23 22:46 来自手机 | 显示全部楼层
正好需要,谢谢楼主分享。
回复

使用道具 举报

ID:526888 发表于 2020-1-3 09:01 | 显示全部楼层
谢谢分享,不过型号要对应!!!!
回复

使用道具 举报

ID:742604 发表于 2020-5-2 00:59 | 显示全部楼层
请问proteus上要怎么接线呀
回复

使用道具 举报

ID:235954 发表于 2021-1-20 09:42 | 显示全部楼层
     //判断当前的位置跟食物的位置,扫描蛇身,有只相同会继续扫描。      for (int i = 0; i < snake_length; i++)      {           flag=0;          if((food_x==snake_x[i])&&(food_y==snake_y[i]))          {             flag=1;//相同继续循环          // break;          }               }          }
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表