Arduino贪吃蛇

Arduino贪吃蛇


5921411BD19075EC2D954077B97FD3B8.png

2015-10-29 18:42 上传
(67.29 KB)





新特性:

  • 吃到食物蛇身变长。
  • 食物不会出现在蛇身上。
  • 蛇每吃5个食物,移动速度增加一次。
  • 场地无边界。
  • 修复所有漏洞。
  • 一键重置游戏。
  • 增加摇杆控制。
  • 增加手动加速功能。
  • 摇杆实时高精度识别,加入防误触机制。

    (源代码已开放,并且很耐心的为每一个句子写了详细注释)



    Demo如下:







    代码如下:



    ARDUINO 代码复制打印
    /**name: 贪吃蛇 version:3.6 <NO BUG Version>Author: Apple tec.<[email]godfights@163.com[/email]>Date: 2015-10-23Description:BiColor IIC点阵note: &#169;2015 Apple tec.All Rights      Designed by LJ//==================================================================================贪吃蛇=================================================================================================================/#include <Wire.h>                   // I2C链接库#include "Adafruit_LEDBackpack.h"             // 点阵驱动库#include "Adafruit_GFX.h"               // Arduino图形库 Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();     // 设置I2C点阵型号 static const uint8_t attribute ((progmem)) X [] = { B01000010, B01000010, B00100100, B00011000, B00011000, B00100100, B01000010, B01000010 }; // 字母 X 的logo代码,其实就是一个一个点的量灭组成的int speedS = 8;                   // 贪吃蛇的初始速度int socre;                    // 游戏得分int xValue;                     // JoyStick-Xint yValue;                     // JoyStick-Yint zPin = 4;                   // JoyStick-Zint Enabled;                    // 重启游戏使能int FX, FY;                     // 食物的坐标int SX, SY;                     // 蛇头的坐标int KEY, K;                     // 当前按键码和实际按键码char s[129] = {};                   // 蛇身体坐标集合,一共64个点,二维坐标128个元素 其中0没有用到 故为129个元素/***************************************************************************************************************************************************************************************************************/void setup() {/ pinMode(A2, OUTPUT);    // 让A2 A3输出A2高电平 A3 低电平来达到VCC GND的目的20ma的输出能力足够点阵使用了 pinMode(A3, OUTPUT);    // 在此模式下需将显示方向设置为 3 digitalWrite(A2, HIGH);  digitalWrite(A3, LOW); */pinMode(zPin, INPUT);RANDOM();         // 获取一个随机食物坐标K = 0;          // 初始化按键码,实际上就是行进方向 方向初始化为0 即在首次操作摇杆前 蛇不移动s[1] = 2;         // x3s[2] = 2;         // y3s[3] = 1;         // x2s[4] = 2;         // y2s[5] = 0;         // x1s[6] = 2;         // y1 初始化蛇的身体坐标   socre = 0;        // 游戏起始得分matrix.begin(0x70);     // 设定IIC屏幕地址matrix.clear();       // 屏幕清屏matrix.writeDisplay();    // 屏幕显示matrix.setRotation(1);    // 设置屏幕显示方向0向左显示 1向上显示 2向右显示 3向下显示 默认值为0 若输入错误值4 显示方向保持默认0matrix.clear(); Logo();         // 绘制开机Logomatrix.writeDisplay();delay(1000); matrix.setTextWrap(false);     // 设置字体平滑模式matrix.setTextSize(1);       // 设置字号matrix.setTextColor(LED_GREEN);    // 设定LED颜色,0表示熄灭~ for (int8_t x = 7; x >= -70; x--) {  // for (int8_t x = -75; x <= 7; x++) {} 向右滚屏  matrix.clear();  matrix.setCursor(x, 1);      // setCursor(int16_t x, int16_t y)  matrix.print( "READY!!! G0 " );  matrix.writeDisplay();  delay(70);}// 循环绘制文字,获得滚动效果 matrix.clear(); for(int i = 1; i <= 6; i += 2)        // 从蛇头开始绘制三个点 s[1], s[3], s[5]为x坐标 s[2], s[4], s[6]为y坐标 蛇身排序: {s[5],s[6]}{s[3],s[4]}{s[1],s[2]} (右侧为蛇头){  matrix.drawPixel(s[i], s[i + 1], LED_RED);  // drawPixel(int16_t x, int16_t y, uint16_t color)}matrix.writeDisplay();delay(400);}// 循环绘制蛇的身体,实际上就是3个点咯~ /***************************************************************************************************************************************************************************************************************/void RANDOM() {A: FX = random(0, 7); FY = random(0, 7);for(int i = 1; i <= 6 + 2 * socre; i+= 2)    // 防止食物出现在蛇身上{  if( FX == s[i] and FY == s[i + 1])  goto A;           }}// 随机食物获取函数 /***************************************************************************************************************************************************************************************************************/void myDelay( int Time) {         // 在蛇移动的延时期间 我们要做一些事情 比如食物的闪烁和摇杆方向的读取for(int t = 1; t <= Time; t++){   matrix.drawPixel(FX, FY, LED_GREEN);  matrix.writeDisplay();  delay(50);  matrix.drawPixel(FX, FY, 0);  matrix.writeDisplay();  delay(50);  joyStick();              // 读取摇杆方向  }}// 这个是演示函数,实际上通过不断闪现食物来完成延迟,这样既可以做到精确延时,也可以让食物不断闪动,来让大家不断的看到~ /***************************************************************************************************************************************************************************************************************/ void Endelay( unsigned long duration) {      // 字幕滚动的延时期间 我们也要做一些事情 比如判断中央键是否被按下 按下则重置游戏unsigned long Start = millis();while(millis() - Start <= duration) {  if(digitalRead(zPin) == LOW) {  delay(20);  if(digitalRead(zPin) == LOW) {  Enabled = 1;  }  }  }}// 重启游戏专用延时函数/***************************************************************************************************************************************************************************************************************/ void Logo() {matrix.drawPixel(6, 0, LED_YELLOW);    // X 右边笔画的动画matrix.writeDisplay();delay(35);for ( int x = 1; x <= 6; x++) {       matrix.drawPixel(7-x, x, LED_YELLOW);   matrix.writeDisplay();  delay(35);  }matrix.drawPixel(1, 7, LED_YELLOW); matrix.writeDisplay();delay(35);matrix.drawPixel(1, 0, LED_YELLOW);    // X 左边笔画的动画matrix.writeDisplay();delay(35);for ( int x = 1; x <= 6; x++) {      matrix.drawPixel(x, x, LED_YELLOW);   matrix.writeDisplay();  delay(35);  }matrix.drawPixel(6, 7, LED_YELLOW); matrix.writeDisplay();delay(35);for (int x = 1; x <= 45; x++) {         // logo闪烁  matrix.clear();   matrix.writeDisplay();  delay(x);   matrix.drawBitmap(0, 0, X, 8, 8, LED_YELLOW);   // drawBitmap(int16_t x, int16_t y, const uint8_t bitmap, int16_t w, int16_t h, uint16_t color)  matrix.writeDisplay();  delay(x);  }}// Logo绘制函数,看不懂可以跳过~~~不过还是蛮简单的,仔细看下就明白了~/***************************************************************************************************************************************************************************************************************/void joyStick() {xValue = analogRead(A0);         // JoyStick-X 最左值为0 最右值为1023 中间值为515yValue = analogRead(A1);         // JoyStick-Y 最下值为0 最上值为1023 中间值为510if(yValue == 1023 && KEY != 5) {  K = 8;  } else if(yValue == 0 && KEY != 8) {  K = 5;  }else if(xValue == 0 && KEY != 6 && K != 0) {   // 首次操作摇杆前 不能向左移动蛇  K = 4;  } else if(xValue == 1023 && KEY != 4) {  K = 6;  }if(digitalRead(zPin) == LOW)         // 当按下中央键后 速度变为 2松开后 速度恢复到当前值  speedS = 2;else  speedS = 8 - socre / 5; }// 这里是在比对按键方向是否和目前蛇的行进方向相反,如果相反就放弃按键/***************************************************************************************************************************************************************************************************************/ void gameover() {            // 一旦执行到Gameover 程序停止 需要按下中央键后以重启游戏Enabled = 0;while(Enabled == 0) {  for (int8_t x = 7; x >= -125 && Enabled == 0; x--) {  matrix.clear();  matrix.setCursor(x, 1);  matrix.print( "GAME OVER YOUR SOCRE:" );  matrix.writeDisplay();  Endelay(70);  }  for (int8_t x = 7; x >= -39 && Enabled == 0; x--) {  matrix.clear();  matrix.setCursor(x, 1);  matrix.print(socre);  matrix.writeDisplay();  Endelay(70);  }   }  // GameOver函数,显示游戏结束和得分   for(int i = 0; i < 129; i++) {  s[i] = 0;   }  K = 0;      // 重置摇杆方向  s[1] = 2;  s[2] = 2;  s[3] = 1;  s[4] = 2;  s[5] = 0;  s[6] = 2;     // 重置蛇的坐标  socre = 0;    // 重置游戏得分}/***************************************************************************************************************************************************************************************************************/void loop() { KEY = K;            // 蛇每移动一次 方向才能改变一次matrix.clear(); if(KEY == 8)            // 蛇向上运动{   for(int i = 6 + 2 * socre; i > 3; i= i - 2)  {  s[i] = s[i - 2];  s[i - 1] = s[i - 3];  }  s[2] = s[2] - 1;  if(s[2] < 0)          // 超出边框的从另一边继续出现  s[2] = 7;}else if(KEY == 5)         // 蛇向下运动{  for(int i = 6 + 2 * socre; i > 3; i= i - 2)  {  s[i] = s[i - 2];  s[i - 1] = s[i - 3];  }  s[2] = s[2] + 1;  if(s[2] > 7)          // 超出边框的从另一边继续出现  s[2] = 0;}else if(KEY == 4)         // 蛇向左运动{  for(int i = 6 + 2 * socre; i > 3; i= i - 2)  {  s[i] = s[i - 2];  s[i - 1] = s[i - 3];  }  s[1] = s[1] - 1;  if(s[1] < 0)          // 超出边框的从另一边继续出现  s[1] = 7;}else if(KEY == 6)         // 蛇向右运动{  for(int i = 6 + 2 * socre; i > 3; i= i - 2)  {  s[i] = s[i - 2];  s[i - 1] = s[i - 3];  }  s[1] = s[1] + 1;  if(s[1] > 7)          // 超出边框的从另一边继续出现  s[1] = 0;}// 根据按键来移动蛇的身体for(int i = 1; i <= 6 + 2 * socre; i+= 2) // 从蛇头开始绘制{  matrix.drawPixel(s[i], s[i + 1], LED_RED);}matrix.writeDisplay();myDelay(speedS);          //()内为延时次数 延时一次为100ms实测200ms速度很合适 故将加速时速度设置为 2SX = s[1];SY = s[2]; // 获取蛇头的坐标for(int i = 3; i <= 6 + 2 * socre; i+= 2){  if( SX == s[i] && SY == s[i + 1])  gameover();           }// 判断蛇头是否碰到自己的身体,碰到就跳转到GameOverif(SY == FY && SX == FX){  socre ++;  RANDOM();  if( !(socre % 5)) {       // 根据得分加快蛇的速度 每吃5个食物 速度快100ms  speedS --;   if(speedS < 2)        // 速度下限为200ms 如果速度小于200ms 速度值仍为200ms  speedS = 2;  }}// 判断是否吃到了食物~吃到了就会加分和重新随机生成食物~}
    /

    *name: 贪吃蛇

    *version:3.6 <NO BUG Version>

    *Author: Apple tec.<[email]godfights@163.com[/email]>

    *Date: 2015-10-23

    *Description:BiColor IIC点阵

    *note: &#169;2015 Apple tec.All Rights
  •  Designed by LJ<br />
    

/

/
==================================================================================贪吃蛇=================================================================================================================/

#include <Wire.h> // I2C链接库

#include "Adafruit_LEDBackpack.h" // 点阵驱动库

#include "Adafruit_GFX.h" // Arduino图形库



Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix(); // 设置I2C点阵型号



static const uint8_t attribute ((progmem)) X [] = { B01000010, B01000010, B00100100, B00011000, B00011000, B00100100, B01000010, B01000010 }; // 字母 X 的logo代码,其实就是一个一个点的量灭组成的



int speedS = 8; // 贪吃蛇的初始速度

int socre; // 游戏得分

int xValue; // JoyStick-X

int yValue; // JoyStick-Y

int zPin = 4; // JoyStick-Z

int Enabled; // 重启游戏使能

int FX, FY; // 食物的坐标

int SX, SY; // 蛇头的坐标

int KEY, K; // 当前按键码和实际按键码

char s[129] = {}; // 蛇身体坐标集合,一共64个点,二维坐标128个元素 其中0没有用到 故为129个元素

/***************************************************************************************************************************************************************************************************************/



void setup() {



/


pinMode(A2, OUTPUT); // 让A2 A3输出A2高电平 A3 低电平来达到VCC GND的目的20ma的输出能力足够点阵使用了

pinMode(A3, OUTPUT); // 在此模式下需将显示方向设置为 3

digitalWrite(A2, HIGH);

digitalWrite(A3, LOW);

*/



pinMode(zPin, INPUT);



RANDOM(); // 获取一个随机食物坐标

K = 0; // 初始化按键码,实际上就是行进方向 方向初始化为0 即在首次操作摇杆前 蛇不移动

s[1] = 2; // x3

s[2] = 2; // y3

s[3] = 1; // x2

s[4] = 2; // y2

s[5] = 0; // x1

s[6] = 2; // y1 初始化蛇的身体坐标

socre = 0; // 游戏起始得分



matrix.begin(0x70); // 设定IIC屏幕地址

matrix.clear(); // 屏幕清屏

matrix.writeDisplay(); // 屏幕显示

matrix.setRotation(1); // 设置屏幕显示方向0向左显示 1向上显示 2向右显示 3向下显示 默认值为0 若输入错误值4 显示方向保持默认0

matrix.clear();



Logo(); // 绘制开机Logo



matrix.writeDisplay();

delay(1000);



matrix.setTextWrap(false); // 设置字体平滑模式

matrix.setTextSize(1); // 设置字号

matrix.setTextColor(LED_GREEN); // 设定LED颜色,0表示熄灭~



for (int8_t x = 7; x >= -70; x--) { // for (int8_t x = -75; x <= 7; x++) {} 向右滚屏

matrix.clear();

matrix.setCursor(x, 1); // setCursor(int16_t x, int16_t y)

matrix.print( "READY!!! G0 " );

matrix.writeDisplay();

delay(70);

}

// 循环绘制文字,获得滚动效果



matrix.clear();

for(int i = 1; i <= 6; i += 2) // 从蛇头开始绘制三个点 s[1], s[3], s[5]为x坐标 s[2], s[4], s[6]为y坐标 蛇身排序: {s[5],s[6]}{s[3],s[4]}{s[1],s[2]} (右侧为蛇头)

{

matrix.drawPixel(s[i], s[i + 1], LED_RED); // drawPixel(int16_t x, int16_t y, uint16_t color)

}

matrix.writeDisplay();

delay(400);

}

// 循环绘制蛇的身体,实际上就是3个点咯~

/***************************************************************************************************************************************************************************************************************/



void RANDOM() {

A:

FX = random(0, 7);

FY = random(0, 7);



for(int i = 1; i <= 6 + 2 * socre; i+= 2) // 防止食物出现在蛇身上

{

if( FX == s[i] and FY == s[i + 1])

goto A;

}

}

// 随机食物获取函数

/***************************************************************************************************************************************************************************************************************/



void myDelay( int Time) { // 在蛇移动的延时期间 我们要做一些事情 比如食物的闪烁和摇杆方向的读取



for(int t = 1; t <= Time; t++)

{

matrix.drawPixel(FX, FY, LED_GREEN);

matrix.writeDisplay();

delay(50);

matrix.drawPixel(FX, FY, 0);

matrix.writeDisplay();

delay(50);

joyStick(); // 读取摇杆方向

}

}

// 这个是演示函数,实际上通过不断闪现食物来完成延迟,这样既可以做到精确延时,也可以让食物不断闪动,来让大家不断的看到~

/***************************************************************************************************************************************************************************************************************/



void Endelay( unsigned long duration) { // 字幕滚动的延时期间 我们也要做一些事情 比如判断中央键是否被按下 按下则重置游戏



unsigned long Start = millis();

while(millis() - Start <= duration) {

if(digitalRead(zPin) == LOW) {

delay(20);

if(digitalRead(zPin) == LOW) {

Enabled = 1;

}

}

}

}

// 重启游戏专用延时函数

/***************************************************************************************************************************************************************************************************************/



void Logo() {



matrix.drawPixel(6, 0, LED_YELLOW); // X 右边笔画的动画

matrix.writeDisplay();

delay(35);

for ( int x = 1; x <= 6; x++) {

matrix.drawPixel(7-x, x, LED_YELLOW);

matrix.writeDisplay();

delay(35);

}

matrix.drawPixel(1, 7, LED_YELLOW);

matrix.writeDisplay();

delay(35);



matrix.drawPixel(1, 0, LED_YELLOW); // X 左边笔画的动画

matrix.writeDisplay();

delay(35);

for ( int x = 1; x <= 6; x++) {

matrix.drawPixel(x, x, LED_YELLOW);

matrix.writeDisplay();

delay(35);

}

matrix.drawPixel(6, 7, LED_YELLOW);

matrix.writeDisplay();

delay(35);



for (int x = 1; x <= 45; x++) { // logo闪烁

matrix.clear();

matrix.writeDisplay();

delay(x);

matrix.drawBitmap(0, 0, X, 8, 8, LED_YELLOW); // drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color)

matrix.writeDisplay();

delay(x);

}

}

// Logo绘制函数,看不懂可以跳过~~~不过还是蛮简单的,仔细看下就明白了~

/***************************************************************************************************************************************************************************************************************/



void joyStick() {



xValue = analogRead(A0); // JoyStick-X 最左值为0 最右值为1023 中间值为515

yValue = analogRead(A1); // JoyStick-Y 最下值为0 最上值为1023 中间值为510



if(yValue == 1023 && KEY != 5) {

K = 8;

}

else if(yValue == 0 && KEY != 8) {

K = 5;

}

else if(xValue == 0 && KEY != 6 && K != 0) { // 首次操作摇杆前 不能向左移动蛇

K = 4;

}

else if(xValue == 1023 && KEY != 4) {

K = 6;

}



if(digitalRead(zPin) == LOW) // 当按下中央键后 速度变为 2松开后 速度恢复到当前值

speedS = 2;

else

speedS = 8 - socre / 5;

}

// 这里是在比对按键方向是否和目前蛇的行进方向相反,如果相反就放弃按键

/***************************************************************************************************************************************************************************************************************/



void gameover() { // 一旦执行到Gameover 程序停止 需要按下中央键后以重启游戏



Enabled = 0;

while(Enabled == 0) {



for (int8_t x = 7; x >= -125 && Enabled == 0; x--) {

matrix.clear();

matrix.setCursor(x, 1);

matrix.print( "GAME OVER YOUR SOCRE:" );

matrix.writeDisplay();

Endelay(70);

}



for (int8_t x = 7; x >= -39 && Enabled == 0; x--) {

matrix.clear();

matrix.setCursor(x, 1);

matrix.print(socre);

matrix.writeDisplay();

Endelay(70);

}

}

// GameOver函数,显示游戏结束和得分



for(int i = 0; i < 129; i++) {

s[i] = 0;

}



K = 0; // 重置摇杆方向

s[1] = 2;

s[2] = 2;

s[3] = 1;

s[4] = 2;

s[5] = 0;

s[6] = 2; // 重置蛇的坐标

socre = 0; // 重置游戏得分

}

/***************************************************************************************************************************************************************************************************************/



void loop() {



KEY = K; // 蛇每移动一次 方向才能改变一次

matrix.clear();



if(KEY == 8) // 蛇向上运动

{

for(int i = 6 + 2 * socre; i > 3; i= i - 2)

{

s[i] = s[i - 2];

s[i - 1] = s[i - 3];

}

s[2] = s[2] - 1;

if(s[2] < 0) // 超出边框的从另一边继续出现

s[2] = 7;

}

else if(KEY == 5) // 蛇向下运动

{

for(int i = 6 + 2 * socre; i > 3; i= i - 2)

{

s[i] = s[i - 2];

s[i - 1] = s[i - 3];

}

s[2] = s[2] + 1;

if(s[2] > 7) // 超出边框的从另一边继续出现

s[2] = 0;

}

else if(KEY == 4) // 蛇向左运动

{

for(int i = 6 + 2 * socre; i > 3; i= i - 2)

{

s[i] = s[i - 2];

s[i - 1] = s[i - 3];

}

s[1] = s[1] - 1;

if(s[1] < 0) // 超出边框的从另一边继续出现

s[1] = 7;

}

else if(KEY == 6) // 蛇向右运动

{

for(int i = 6 + 2 * socre; i > 3; i= i - 2)

{

s[i] = s[i - 2];

s[i - 1] = s[i - 3];

}

s[1] = s[1] + 1;

if(s[1] > 7) // 超出边框的从另一边继续出现

s[1] = 0;

}

// 根据按键来移动蛇的身体



for(int i = 1; i <= 6 + 2 * socre; i+= 2) // 从蛇头开始绘制

{

matrix.drawPixel(s[i], s[i + 1], LED_RED);

}

matrix.writeDisplay();



myDelay(speedS); //()内为延时次数 延时一次为100ms实测200ms速度很合适 故将加速时速度设置为 2



SX = s[1];

SY = s[2];

// 获取蛇头的坐标



for(int i = 3; i <= 6 + 2 * socre; i+= 2)

{

if( SX == s[i] && SY == s[i + 1])

gameover();

}

// 判断蛇头是否碰到自己的身体,碰到就跳转到GameOver



if(SY == FY && SX == FX)

{

socre ++;

RANDOM();

if( !(socre % 5)) { // 根据得分加快蛇的速度 每吃5个食物 速度快100ms

speedS --;

if(speedS < 2) // 速度下限为200ms 如果速度小于200ms 速度值仍为200ms

speedS = 2;

}

}

// 判断是否吃到了食物~吃到了就会加分和重新随机生成食物~

}



用到的库文件如下:

adafruit_gfx.zip

(7.92 KB, 下载次数: 57)

2015-10-29 18:44 上传
点击文件名下载附件


adafruit_ledbackpack.zip

(56.44 KB, 下载次数: 57)

2015-10-29 18:44 上传
点击文件名下载附件


via - 极客工坊

标签: Arduino教程