- /*==============================================================================================================
- * @function_name: 貪吃蛇
- * @描述: MAX7219 8*8 點陣LED
- * @作者: @逝水無痕@
- * @日期: 2018-01-02
- *----------------------------------------------------------------------------------------------------------------
- * @修改人:
- * @修改內容:
- ================================================================================================================*/
- #include "LedControl.h" //點陣控制庫
-
- int SpeedS = 8; // 貪吃蛇的初始速度
- int Socre; // 游戲得分
- int Left; //定義五個按鍵,上下左右
- int Right;
- int Up;
- int Down;
- int Res; //游戲中用來加速,游戲結束用來重新開始游戲
- int Enabled; // 重啟游戲使能
- int FX, FY; // 食物的坐標
- int SX, SY; // 蛇頭的坐標
- int KEY, K; // 當前按鍵碼和實際按鍵碼
- LedControl lc=LedControl(12,11,10,1); //初始化設備,引腳連接 (din,clk,cs,點陣個數)
- char s[129] = {}; // 蛇身體坐標集合,一共64個點,二維坐標128個元素 其中0沒有用到 故為129個元素
- //字符的模
- byte zero[8] = {0x18,0x24,0x42,0x42,0x42,0x42,0x24,0x18,}; //0
- byte one[8] = {0x10,0x18,0x14,0x10,0x10,0x10,0x10,0x38,}; //1
- byte two[8] = {0x18,0x24,0x20,0x20,0x10,0x08,0x04,0x3C,}; //2
- byte three[8]= {0x18,0x24,0x20,0x38,0x38,0x20,0x24,0x18,}; //3
- byte four[8] = {0x10,0x18,0x14,0x12,0x3E,0x10,0x10,0x10,}; //4
- byte five[8] = {0x3C,0x04,0x0C,0x10,0x20,0x20,0x24,0x18,}; //5
- byte six[8] = {0x1C,0x22,0x02,0x1E,0x22,0x22,0x22,0x1C,}; //6
- byte seven[8]= {0x7E,0x20,0x10,0x08,0x08,0x08,0x08,0x08,}; //7
- byte eight[8]= {0x18,0x24,0x24,0x24,0x18,0x24,0x24,0x18,}; //8
- byte nine[8] = {0x18,0x24,0x24,0x24,0x38,0x10,0x08,0x04,}; //9
- byte smile[8]= {0x3C,0x42,0xA5,0x81,0xA5,0x99,0x42,0x3C,}; //笑臉
- byte neutral[8]= {0x3C,0x42,0xA5,0x81,0xBD,0x81,0x42,0x3C,}; //標準臉
- /******************************************************************************************************************/
- void setup()
- {
- //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; // 游戲起始得分
- //MAX7219的初始設置
- lc.shutdown(0,false); //設置節電模式,設備號從0開始,false 不節電
- lc.setIntensity(0,2); //設置亮度
- lc.clearDisplay(0); //清屏
- printByte(smile); //顯示笑臉
- delay(2000);
-
- /*循環繪制蛇的身體,實際上就是3個點 */
- 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]} (右側為蛇頭)
- {
- lc.setLed(0,s[i],s[i + 1],1); //(設備號 行 列 亮)
- }
- }
- /*****************************************************隨機食物獲取函數 ***********************************************************************/
- 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++)
- {
- lc.setLed(0,FX,FY,1); //設備號 行 列 亮
- delay(50);
- lc.setLed(0,FX,FY,0); //設備號 行 列 亮
- delay(50);
- Button(); // 讀取搖桿方向
- }
- }
- // /***************************************************************************************************************************************************************************************************************/
- void Button()
- {
- Up = digitalRead(2); //讀取按鍵的值
- Down = digitalRead(3);
- Left = digitalRead(4);
- Right= digitalRead(5);
- Res = digitalRead(6);
-
- if(Up == 0 && KEY != 5) // 這里是在比對按鍵方向是否和目前蛇的行進方向相反,如果相反就放棄按鍵
- {
- K = 8;
- }
- else if(Down == 0 && KEY != 8)
- {
- K = 5;
- }
- else if(Left == 0 && KEY != 6 && K != 0)
- { // 首次操作按鍵前 不能向左移動蛇
- K = 4;
- }
- else if(Right == 0 && KEY != 4)
- {
- K = 6;
- }
- if(Res == LOW) // 當按下中央鍵后 速度變為 2 松開后 速度恢復到當前值
- SpeedS = 2;
- else
- SpeedS = 8 - Socre / 5;
- }
- /************************************GameOver函數,顯示游戲結束和得分 ******************************************************************************/
- void gameover() // 一旦執行到Gameover 程序停止 需要按下重啟鍵后以重啟游戲
- {
- Enabled = 0;
- while(Enabled == 0)
- {
- lc.clearDisplay(0); //清屏
- printByte(neutral); //顯示標準臉
- delay(1000);
-
- lc.clearDisplay(0); //清屏
- printfSocre(Socre); //顯示分數
- delay(1000);
-
- Res = digitalRead(6); //如果重啟鍵按下,跳出循環,重啟游戲
- if(Res == 0)
- {
- Enabled=1;
- }
- }
- lc.clearDisplay(0); //清屏
- 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; // 蛇每移動一次 方向才能改變一次
- lc.clearDisplay(0);
-
- 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) // 從蛇頭開始繪制
- {
- lc.setLed(0,s[i],s[i + 1],1); //設備號 行 列 亮
- }
- 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;
- }
- } // 判斷是否吃到了食物~吃到了就會加分和重新隨機生成食物~
- }
- //點陣顯示函數
- void printByte(byte character [])
- {
- int i = 0;
- for(i=0;i<8;i++)
- {
- lc.setRow(0,i,character[i]);
- }
- }
- /************************************顯示分數子函數******************************************************/
- void printfSocre(int socre)
- {
- int tens_place = socre/10;
- int ones_place = socre%10;
- switch(tens_place)
- {
- //case 0:printByte(zero);delay(1000); break; //十位不顯示0
- case 1:printByte(one); delay(1000); break;
- case 2:printByte(two); delay(1000); break;
- case 3:printByte(three);delay(1000); break;
- case 4:printByte(four); delay(1000); break;
- case 5:printByte(five); delay(1000); break;
- case 6:printByte(six); delay(1000); break;
- case 7:printByte(seven);delay(1000); break;
- case 8:printByte(eight);delay(1000); break;
- case 9:printByte(nine); delay(1000); break;
- default:break;
- }
-
- switch(ones_place)
- {
- case 0:printByte(zero); delay(1000); break;
- case 1:printByte(one); delay(1000); break;
- case 2:printByte(two); delay(1000); break;
- case 3:printByte(three);delay(1000); break;
- case 4:printByte(four); delay(1000); break;
- case 5:printByte(five); delay(1000); break;
- case 6:printByte(six); delay(1000); break;
- case 7:printByte(seven);delay(1000); break;
- case 8:printByte(eight);delay(1000); break;
- case 9:printByte(nine); delay(1000); break;
- default:break;
- }
-
- }
復制代碼 |