# FSM 有限狀態機參考程式碼
## C++
:::spoiler **提示**
```cpp=
#include <iostream>
using namespace std;
int main()
{
string name;
cout << "FSM Example"<< endl << endl;
int state = 0; //起始狀態
int input; //輸入
while(1)
{
switch(state)
{
case 0://狀態 0:閒晃
cout << "Current State : Wander"<< endl;
cout << "Input Option : 0.Player Nearby" << endl;
cout << "Input : ";
cin >> input; //讀取輸入
if(input == 0)
{
state = 10; //狀態變換
}
break;
case 10://狀態 10:攻擊
cout << "Current State : Attack"<< endl;
cout << "Input Option : 0.Player Out Of Sight 1.Player Fight Back" << endl;
cout << "Input : ";
cin >> input;
if(input == 0)
{
state = 0;
}
else if(input == 1)
{
state = 20;
}
break;
case 20://狀態 20:撤退
cout << "Current State : Evade"<< endl;
cout << "Input Option : 0.Health are Low 1.Player is Idle" << endl;
cout << "Input : ";
cin >> input;
//TO_DO
break;
case 30://狀態 30:尋找補品
cout << "Current State : Find Aid"<< endl;
cout << "Input Option : 0.Get Aid" << endl;
cout << "Input : ";
cin >> input;
if(input == 0)
{
state = //TO_DO
}
break;
}
cout << endl;
}
}
```
:::
:::spoiler **參考答案**
```cpp=
#include <iostream>
using namespace std;
int main()
{
string name;
cout << "FSM Example"<< endl << endl;
int state = 0; //起始狀態
int input; //輸入
while(1)
{
switch(state)
{
case 0://狀態 0:閒晃
cout << "Current State : Wander"<< endl;
cout << "Input Option : 0.Player Nearby" << endl;
cout << "Input : ";
cin >> input; //讀取輸入
if(input == 0)
{
state = 10; //狀態變換
}
break;
case 10://狀態 10:攻擊
cout << "Current State : Attack"<< endl;
cout << "Input Option : 0.Player Out Of Sight 1.Player Fight Back" << endl;
cout << "Input : ";
cin >> input;
if(input == 0)
{
state = 0;
}
else if(input == 1)
{
state = 20;
}
break;
case 20://狀態 20:撤退
cout << "Current State : Evade"<< endl;
cout << "Input Option : 0.Health are Low 1.Player is Idle" << endl;
cout << "Input : ";
cin >> input;
if(input == 0)
{
state = 30;
}
else if(input == 1)
{
state = 10;
}
break;
case 30://狀態 30:尋找補品
cout << "Current State : Find Aid"<< endl;
cout << "Input Option : 0.Get Aid" << endl;
cout << "Input : ";
cin >> input;
if(input == 0)
{
state = 0;
}
break;
}
cout << endl;
}
}
```
:::
## Arduino
### **燈泡&按鈕 1**
:::spoiler **提示**
```cpp=
#include <LedControl.h>
#define CIN 6
#define CS 7
#define CLK 8
#define Button 2
#define Width 8
#define Height 8
LedControl LC = LedControl(CIN,CLK,CS,1);
void Update(int Map[Height][Width]) // LED 更新函式
{
for(int i=0;i<Height;i++)
{
for(int j=0;j<Width;j++)
{
bool temp;
if(Map[i][j]==0)
{
temp=false;
}
else
{
temp=true;
}
LC.setLed(0,j,i,Map[7-i][j]);
}
}
}
int On[8][8]={{0,0,0,0,0,0,0,0},
{0,0,0,0,1,0,0,0},
{0,0,1,0,1,0,1,0},
{0,0,0,1,1,1,0,0},
{0,1,1,1,0,1,1,1},
{0,0,0,1,1,1,0,0},
{0,0,1,0,1,0,1,0},
{0,0,0,0,1,0,0,0}};
int state = 0;
void setup()
{
pinMode(CIN,OUTPUT);
pinMode(CS,OUTPUT);
pinMode(CLK,OUTPUT);
pinMode(Button,INPUT);
LC.shutdown(0,false);
LC.setIntensity(0,15);//(0~15)
LC.clearDisplay(0);
Serial.begin(9600);
}
void loop()
{
Serial.println(state);
switch (state)
{
case 0://燈泡暗
LC.clearDisplay(0);
//TO_DO
break;
case 1://燈泡亮
Update(On);
//TO_DO
break;
}
}
```
:::
:::spoiler **參考答案**
```cpp=
#include <LedControl.h>
#define CIN 6
#define CS 7
#define CLK 8
#define Button 2
#define Width 8
#define Height 8
LedControl LC = LedControl(CIN,CLK,CS,1);
void Update(int Map[Height][Width])
{
for(int i=0;i<Height;i++)
{
for(int j=0;j<Width;j++)
{
bool temp;
if(Map[i][j]==0)
{
temp=false;
}
else
{
temp=true;
}
LC.setLed(0,j,i,Map[7-i][j]);
}
}
}
int On[8][8]={{0,0,0,0,0,0,0,0},
{0,0,0,0,1,0,0,0},
{0,0,1,0,1,0,1,0},
{0,0,0,1,1,1,0,0},
{0,1,1,1,0,1,1,1},
{0,0,0,1,1,1,0,0},
{0,0,1,0,1,0,1,0},
{0,0,0,0,1,0,0,0}};
int state = 0;
void setup()
{
pinMode(CIN,OUTPUT);
pinMode(CS,OUTPUT);
pinMode(CLK,OUTPUT);
pinMode(Button,INPUT);
LC.shutdown(0,false);
LC.setIntensity(0,15);//(0~15)
LC.clearDisplay(0);
Serial.begin(9600);
}
void loop()
{
Serial.println(state);
switch (state)
{
case 0://燈泡暗
LC.clearDisplay(0);
if(digitalRead(Button) == HIGH)
{
state = 1;
}
break;
case 1://燈泡亮
Update(On);
if(digitalRead(Button) == LOW)
{
state = 0;
}
break;
}
}
```
:::
### **燈泡&按鈕 2**
:::spoiler **提示**
```cpp=
#include <LedControl.h>
#define CIN 6
#define CS 7
#define CLK 8
#define Button 2
#define Width 8
#define Height 8
LedControl LC = LedControl(CIN,CLK,CS,1);
void Update(int Map[Height][Width])
{
for(int i=0;i<Height;i++)
{
for(int j=0;j<Width;j++)
{
bool temp;
if(Map[i][j]==0)
{
temp=false;
}
else
{
temp=true;
}
LC.setLed(0,j,i,Map[7-i][j]);
}
}
}
int On[8][8]={{0,0,0,0,0,0,0,0},
{0,0,0,0,1,0,0,0},
{0,0,1,0,1,0,1,0},
{0,0,0,1,1,1,0,0},
{0,1,1,1,0,1,1,1},
{0,0,0,1,1,1,0,0},
{0,0,1,0,1,0,1,0},
{0,0,0,0,1,0,0,0}};
int state = 0;
void setup()
{
pinMode(CIN,OUTPUT);
pinMode(CS,OUTPUT);
pinMode(CLK,OUTPUT);
pinMode(Button,INPUT);
LC.shutdown(0,false);
LC.setIntensity(0,10);//(0~15)
LC.clearDisplay(0);
//Update(On);
Serial.begin(9600);
}
void loop()
{
Serial.println(state);
switch (state)
{
case 0: //燈暗 按鈕放
LC.clearDisplay(0);
if(digitalRead(Button) == //TO_DO)
{
state = //TO_DO;
}
break;
case 1: //燈暗 按鈕押
if(digitalRead(Button) == //TO_DO)
{
state = //TO_DO;
}
break;
case 2: //燈亮 按鈕放
Update(On);
if(digitalRead(Button) == //TO_DO)
{
state = //TO_DO;
}
break;
case 3: //燈亮 按鈕押
if(digitalRead(Button) == //TO_DO)
{
state = //TO_DO;
}
break;
}
}
```
:::
:::spoiler **參考答案**
```cpp=
#include <LedControl.h>
#define CIN 6
#define CS 7
#define CLK 8
#define Button 2
#define Width 8
#define Height 8
LedControl LC = LedControl(CIN,CLK,CS,1);
void Update(int Map[Height][Width])
{
for(int i=0;i<Height;i++)
{
for(int j=0;j<Width;j++)
{
bool temp;
if(Map[i][j]==0)
{
temp=false;
}
else
{
temp=true;
}
LC.setLed(0,j,i,Map[7-i][j]);
}
}
}
int On[8][8]={{0,0,0,0,0,0,0,0},
{0,0,0,0,1,0,0,0},
{0,0,1,0,1,0,1,0},
{0,0,0,1,1,1,0,0},
{0,1,1,1,0,1,1,1},
{0,0,0,1,1,1,0,0},
{0,0,1,0,1,0,1,0},
{0,0,0,0,1,0,0,0}};
int state = 0;
void setup()
{
pinMode(CIN,OUTPUT);
pinMode(CS,OUTPUT);
pinMode(CLK,OUTPUT);
pinMode(Button,INPUT);
LC.shutdown(0,false);
LC.setIntensity(0,10);//(0~15)
LC.clearDisplay(0);
//Update(On);
Serial.begin(9600);
}
void loop()
{
Serial.println(state);
switch (state)
{
case 0: //燈暗 按鈕放
LC.clearDisplay(0);
if(digitalRead(Button) == HIGH)
{
state = 1;
}
break;
case 1: //燈暗 按鈕押
if(digitalRead(Button) == LOW)
{
state = 2;
}
break;
case 2: //燈亮 按鈕放
Update(On);
if(digitalRead(Button) == HIGH)
{
state = 3;
}
break;
case 3: //燈亮 按鈕押
if(digitalRead(Button) == LOW)
{
state = 0;
}
break;
}
}
```
:::
### **燈泡閃爍-delay**
:::spoiler **參考答案**
```cpp=
#include <LedControl.h>
#define CIN 6
#define CS 7
#define CLK 8
#define Button 2
#define Width 8
#define Height 8
LedControl LC = LedControl(CIN,CLK,CS,1);
void Update(int Map[Height][Width])
{
for(int i=0;i<Height;i++)
{
for(int j=0;j<Width;j++)
{
bool temp;
if(Map[i][j]==0)
{
temp=false;
}
else
{
temp=true;
}
LC.setLed(0,j,i,Map[7-i][j]);
}
}
}
int On[8][8]={{0,0,0,0,0,0,0,0},
{0,0,0,0,1,0,0,0},
{0,0,1,0,1,0,1,0},
{0,0,0,1,1,1,0,0},
{0,1,1,1,0,1,1,1},
{0,0,0,1,1,1,0,0},
{0,0,1,0,1,0,1,0},
{0,0,0,0,1,0,0,0}};
int state = 0;
void setup()
{
pinMode(CIN,OUTPUT);
pinMode(CS,OUTPUT);
pinMode(CLK,OUTPUT);
pinMode(Button,INPUT);
LC.shutdown(0,false);
LC.setIntensity(0,10);//(0~15)
LC.clearDisplay(0);
//Update(On);
Serial.begin(9600);
}
void loop()
{
Serial.println(state);
switch (state)
{
case 0:
LC.clearDisplay(0);
if(digitalRead(Button) == HIGH)
{
state = 1;
}
break;
case 1:
if(digitalRead(Button) == LOW)
{
state = 2;
}
break;
case 2:
Update(On);
if(digitalRead(Button) == HIGH)
{
state = 3;
}
break;
case 3:
if(digitalRead(Button) == LOW)
{
state = 4;
}
break;
case 4:
Update(On);
delay(500);
LC.clearDisplay(0);
delay(500);
if(digitalRead(Button) == HIGH)
{
state = 5;
}
break;
case 5:
if(digitalRead(Button) == LOW)
{
state = 0;
}
break;
}
}
```
:::
### **自定義物件 Timer**
:::spoiler **程式碼**
```cpp=
class Timer
{
private:
long Time;
public:
void TimerShutdown()
{
Time = -1;
}
void TimerSet()
{
Time = millis();
}
bool TimerTimeout(long Millis)
{
long C_Time = millis();
if ((C_Time - Time) < Millis || Time == -1)
{
return false;
}
else
{
return true;
}
}
};
```
:::
### **燈泡閃爍 - Timer**
:::spoiler **參考答案**
```cpp=
#include <LedControl.h>
#define CIN 6
#define CS 7
#define CLK 8
#define Button 2
#define Width 8
#define Height 8
class Timer
{
private:
long Time;
public:
void TimerShutdown()
{
Time = -1;
}
void TimerSet()
{
Time = millis();
}
bool TimerTimeout(long Millis)
{
long C_Time = millis();
if ((C_Time - Time) < Millis || Time == -1)
{
return false;
}
else
{
return true;
}
}
};
LedControl LC = LedControl(CIN,CLK,CS,1);
Timer Timer1;//宣告物件
void Update(int Map[Height][Width])
{
for(int i=0;i<Height;i++)
{
for(int j=0;j<Width;j++)
{
bool temp;
if(Map[i][j]==0)
{
temp=false;
}
else
{
temp=true;
}
LC.setLed(0,j,i,Map[7-i][j]);
}
}
}
int On[8][8]={{0,0,0,0,0,0,0,0},
{0,0,0,0,1,0,0,0},
{0,0,1,0,1,0,1,0},
{0,0,0,1,1,1,0,0},
{0,1,1,1,0,1,1,1},
{0,0,0,1,1,1,0,0},
{0,0,1,0,1,0,1,0},
{0,0,0,0,1,0,0,0}};
int Flag = 0;
int state = 0;
void setup()
{
pinMode(CIN,OUTPUT);
pinMode(CS,OUTPUT);
pinMode(CLK,OUTPUT);
pinMode(Button,INPUT);
LC.shutdown(0,false);
LC.setIntensity(0,10);//(0~15)
LC.clearDisplay(0);
Timer1.TimerShutdown();
Serial.begin(9600);
}
void loop()
{
Serial.println(state);
switch (state)
{
case 0:
LC.clearDisplay(0);
if(digitalRead(Button) == HIGH)
{
state = 1;
}
break;
case 1:
if(digitalRead(Button) == LOW)
{
state = 2;
}
break;
case 2:
Update(On);
if(digitalRead(Button) == HIGH)
{
state = 3;
}
break;
case 3:
if(digitalRead(Button) == LOW)
{
state = 4;
Timer1.TimerSet();//開始計時
}
break;
case 4:
if(Flag == 0 && Timer1.TimerTimeout(500))//
{
LC.clearDisplay(0);
Timer1.TimerSet();
Flag =1;
}
else if(Flag == 1 && Timer1.TimerTimeout(500))
{
Update(On);
Timer1.TimerSet();
Flag =0;
}
if(digitalRead(Button) == HIGH)
{
state = 5;
}
break;
case 5:
if(digitalRead(Button) == LOW)
{
state = 0;
}
break;
}
}
```
:::
### **簡易飲水機**
:::spoiler **提示**
```cpp=
#include <LedControl.h>
#define Cold 2
#define Warm 3
#define Cont 4
#define DIN 6
#define CS 7
#define CLK 8
int state = 0;
int flag = 0;
class Timer
{
private:
long Time;
public:
void TimerShutdown()
{
Time = -1;
}
void TimerSet()
{
Time = millis();
}
bool TimerTimeout(long Millis)
{
long C_Time = millis();
if ((C_Time - Time) < Millis || Time == -1)
{
return false;
}
else
{
return true;
}
}
};
int C[8][8] =
{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 1, 0, 0},
{0, 1, 1, 0, 0, 1, 1, 0},
{0, 1, 1, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 0, 1, 1, 0},
{0, 0, 1, 1, 1, 1, 0, 0}
};
int W[8][8] =
{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 0, 0, 1, 1},
{0, 1, 1, 0, 0, 0, 1, 1},
{0, 1, 1, 0, 0, 0, 1, 1},
{0, 1, 1, 0, 1, 0, 1, 1},
{0, 1, 1, 1, 1, 1, 1, 1},
{0, 1, 1, 1, 0, 1, 1, 1},
{0, 1, 1, 0, 0, 0, 1, 1}
};
int cont[8][8] =
{
{0, 0, 1, 1, 1, 1, 0, 0},
{0, 1, 1, 1, 1, 1, 1, 0},
{1, 1, 1, 0, 0, 1, 1, 1},
{1, 1, 0, 0, 0, 0, 1, 1},
{1, 1, 0, 0, 0, 0, 1, 1},
{1, 1, 1, 0, 0, 1, 1, 1},
{0, 1, 1, 1, 1, 1, 1, 0},
{0, 0, 1, 1, 1, 1, 0, 0}
};
LedControl LC = LedControl(DIN, CLK, CS, 1);
Timer Timer1;
void Update(int Map[8][8])
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
bool temp;
if (Map[i][j] == 0)
{
temp = false;
}
else
{
temp = true;
}
LC.setLed(0, j, 7 - i, temp);
//Serial.print(Map[i][j]);
}
//Serial.println();
}
}
void setup()
{
pinMode(DIN, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(Cold, INPUT);
pinMode(Warm, INPUT);
pinMode(Cont, INPUT);
LC.shutdown(0, false);
LC.setIntensity(0, 1); //(0~15)
Serial.begin(9600);
}
void loop()
{
Serial.println(state);
switch (state)
{
//TO_DO
}
}
```
:::
:::spoiler **參考答案**
```cpp=
#include <LedControl.h>
#define Cold 2
#define Warm 3
#define Cont 4
#define DIN 6
#define CS 7
#define CLK 8
int state = 0;
int flag = 0;
class Timer
{
private:
long Time;
public:
void TimerShutdown()
{
Time = -1;
}
void TimerSet()
{
Time = millis();
}
bool TimerTimeout(long Millis)
{
long C_Time = millis();
if ((C_Time - Time) < Millis || Time == -1)
{
return false;
}
else
{
return true;
}
}
};
int C[8][8] =
{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 1, 0, 0},
{0, 1, 1, 0, 0, 1, 1, 0},
{0, 1, 1, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 0, 1, 1, 0},
{0, 0, 1, 1, 1, 1, 0, 0}
};
int W[8][8] =
{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 0, 0, 1, 1},
{0, 1, 1, 0, 0, 0, 1, 1},
{0, 1, 1, 0, 0, 0, 1, 1},
{0, 1, 1, 0, 1, 0, 1, 1},
{0, 1, 1, 1, 1, 1, 1, 1},
{0, 1, 1, 1, 0, 1, 1, 1},
{0, 1, 1, 0, 0, 0, 1, 1}
};
int cont[8][8] =
{
{0, 0, 1, 1, 1, 1, 0, 0},
{0, 1, 1, 1, 1, 1, 1, 0},
{1, 1, 1, 0, 0, 1, 1, 1},
{1, 1, 0, 0, 0, 0, 1, 1},
{1, 1, 0, 0, 0, 0, 1, 1},
{1, 1, 1, 0, 0, 1, 1, 1},
{0, 1, 1, 1, 1, 1, 1, 0},
{0, 0, 1, 1, 1, 1, 0, 0}
};
LedControl LC = LedControl(DIN, CLK, CS, 1);
Timer Timer1;
void Update(int Map[8][8])
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
bool temp;
if (Map[i][j] == 0)
{
temp = false;
}
else
{
temp = true;
}
LC.setLed(0, j, 7 - i, temp);
//Serial.print(Map[i][j]);
}
//Serial.println();
}
}
void setup()
{
pinMode(DIN, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(Cold, INPUT);
pinMode(Warm, INPUT);
pinMode(Cont, INPUT);
LC.shutdown(0, false);
LC.setIntensity(0, 1); //(0~15)
Serial.begin(9600);
}
void loop()
{
Serial.println(state);
switch (state)
{
case 0:
LC.clearDisplay(0);
if (digitalRead(Cold) == HIGH)
{
state = 10;
}
else if (digitalRead(Warm) == HIGH)
{
state = 20;
}
else if (digitalRead(Cont) == HIGH)
{
state = 30;
Timer1.TimerSet();
}
break;
case 10: //冷水暫時出水
Update(C);
if (digitalRead(Cold) == LOW)
{
state = 0;
}
break;
case 20://Warm Water Temporary
Update(W);
if (digitalRead(Warm) == LOW)
{
state = 0;
}
break;
case 30:
if (digitalRead(Cont) == LOW)
{
state = 31;
}
break;
case 31:
if (Timer1.TimerTimeout(250))
{
if (flag == 1)
{
flag = 0;
Update(cont);
}
else
{
LC.clearDisplay(0);
flag = 1;
}
Timer1.TimerSet();
}
if (digitalRead(Cont) == HIGH)
{
state = 32;
}
else if (digitalRead(Cold) == HIGH)
{
state = 40;
}
else if (digitalRead(Warm) == HIGH)
{
state = 50;
}
break;
case 32:
if (digitalRead(Cont) == LOW)
{
state = 0;
}
break;
case 40:
if (digitalRead(Cold) == LOW)
{
state = 41;
}
break;
case 41:
Update(C);
if (digitalRead(Cold) == HIGH)
{
state = 42;
}
else if(digitalRead(Cont) == HIGH)
{
state = 32;
}
break;
case 42:
if (digitalRead(Cold) == LOW)
{
state = 0;
}
break;
case 50:
if (digitalRead(Warm) == LOW)
{
state = 51;
}
break;
case 51:
Update(W);
if (digitalRead(Warm) == HIGH)
{
state = 52;
}
else if(digitalRead(Cont) == HIGH)
{
state = 32;
}
break;
case 52:
if (digitalRead(Warm) == LOW)
{
state = 0;
}
break;
}
}
```
:::
## 俄羅斯方塊遊戲機
:::spoiler **程式碼**
```cpp=
#include <LedControl.h>
#define INI_speed 500 //初始速度 單位ms
//腳位定義
#define Rotate 2
#define Right 3
#define Left 4
#define Down 5
#define CIN 6
#define CS 7
#define CLK 8
//長寬
#define Width 8
#define Height 10
class Timer
{
private:
long Time;
public:
void TimerShutdown()
{
Time = -1;
}
void TimerSet()
{
Time = millis();
}
bool TimerTimeout(long Millis)
{
long C_Time = millis();
if ((C_Time - Time) < Millis || Time == -1)
{
return false;
}
else
{
return true;
}
}
};
/*方塊種類定義
| |
0 | 1 | 2
___|___|___
| |
3 |4&9| 5
___|___|___
| |
6 | 7 | 8
| |
*/
//Blocktype[方塊種類][選轉次數][補正碼]
int Blocktype[7][4][4] = {
{{3, 4, 5, 4}, {1, 4, 7, 4}, {3, 4, 5, 4}, {1, 4, 7, 4}}, //0 I
{{0, 1, 3, 4}, {0, 1, 3, 4}, {0, 1, 3, 4}, {0, 1, 3, 4}}, //1 O
{{1, 3, 4, 5}, {1, 4, 5, 7}, {3, 4, 5, 7}, {1, 3, 4, 7}}, //2 T
{{1, 2, 3, 4}, {1, 4, 5, 8}, {4, 5, 6, 7}, {0, 3, 4, 7}}, //3 S
{{0, 1, 4, 5}, {2, 4, 5, 7}, {3, 4, 7, 8}, {1, 3, 4, 6}}, //4 Z
{{0, 3, 4, 5}, {1, 2, 4, 7}, {3, 4, 5, 8}, {1, 4, 6, 7}}, //5 J
{{2, 3, 4, 5}, {1, 4, 7, 8}, {3, 4, 5, 6}, {0, 1, 4, 7}} //6 L
};
/*
補正碼
以4為中心x、y的相對位置
*/
int x_c[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1};
int y_c[9] = { -1, -1, -1, 0, 0, 0, 1, 1, 1};
int gravity = INI_speed; //重力(掉落速度)
int state = -1; //狀態
int T_map[Height][Width]; //地圖矩陣
int C_block = -1; //目前方塊種類
int C_rotate = 0; //目前旋轉狀態
int C_pos[2]; //目前方塊4號位置 0->y , 1->x;
int score = 0; //分數
bool legit = true; //檢測動作是否合法
Timer Timer1[10];
LedControl LC = LedControl(CIN, CLK, CS, 1); //LED矩陣物件
/*
左上角為原點
向右為+
向下為+
*/
void Update(int Map[Height][Width])
{
for (int i = 2; i < Height; i++)
{
for (int j = 0; j < Width; j++)
{
bool temp;
if (Map[i][j] == 0)
{
temp = false;
}
else
{
temp = true;
}
LC.setLed(0, j, 9 - i, temp);
//Serial.print(Map[i][j]);
}
//Serial.println();
}
}
void C_Rotate(int nextstate)
{
legit = true;
int New_rotate = (C_rotate + 1) % 4;
for (int i = 0; i < 4; i++)
{
int n = Blocktype[C_block][New_rotate][i];
int new_x = C_pos[1] + x_c[n];
int new_y = C_pos[0] + y_c[n];
if ( T_map[new_y][new_x] == 1 || new_x > 7 || new_x < 0 || new_y >= Height )
{
legit = false;
break;
}
}
if (legit)
{
for ( int i = 0 ; i < 4 ; i++ )
{
int n = Blocktype[C_block][C_rotate][i];
T_map[C_pos[0] + y_c[n]][C_pos[1] + x_c[n]] = 0;
}
C_rotate = New_rotate;
for (int i = 0; i < 4; i++)
{
int n = Blocktype[C_block][C_rotate][i];
int new_x = C_pos[1] + x_c[n];
int new_y = C_pos[0] + y_c[n];
T_map[new_y][new_x] = 2;
}
}
state = nextstate;
Update(T_map);
}
void C_Right(int nextstate)
{
legit = true;
for (int i = 0; i < 4; i++)
{
int n = Blocktype[C_block][C_rotate][i];
int new_x = C_pos[1] + x_c[n] + 1;
int new_y = C_pos[0] + y_c[n];
if ( T_map[new_y][new_x] == 1 || new_x > 7 )
{
legit = false;
break;
}
}
if (legit)
{
for (int i = 0; i < 4; i++)
{
int n = Blocktype[C_block][C_rotate][i];
int old_x = C_pos[1] + x_c[n];
int old_y = C_pos[0] + y_c[n];
T_map[old_y][old_x] = 0;
}
C_pos[1] += 1;
for (int i = 0; i < 4; i++)
{
int n = Blocktype[C_block][C_rotate][i];
int new_x = C_pos[1] + x_c[n];
int new_y = C_pos[0] + y_c[n];
T_map[new_y][new_x] = 2;
}
}
state = nextstate;
Update(T_map);
}
void C_Left(int nextstate)
{
legit = true;
for (int i = 0; i < 4; i++)
{
int n = Blocktype[C_block][C_rotate][i];
int new_x = C_pos[1] + x_c[n] - 1;
int new_y = C_pos[0] + y_c[n];
if (T_map[new_y][new_x] == 1 || new_x < 0)
{
legit = false;
break;
}
}
if (legit)
{
for (int i = 0; i < 4; i++)
{
int n = Blocktype[C_block][C_rotate][i];
int old_x = C_pos[1] + x_c[n];
int old_y = C_pos[0] + y_c[n];
T_map[old_y][old_x] = 0;
}
C_pos[1] -= 1;
for (int i = 0; i < 4; i++)
{
int n = Blocktype[C_block][C_rotate][i];
int new_x = C_pos[1] + x_c[n];
int new_y = C_pos[0] + y_c[n];
T_map[new_y][new_x] = 2;
}
}
state = nextstate;
Update(T_map);
}
void C_Down(int nextstate)
{
legit = true;
for (int i = 0; i < 4; i++)
{
int n = Blocktype[C_block][C_rotate][i];
int new_x = C_pos[1] + x_c[n];
int new_y = C_pos[0] + y_c[n] + 1;
if (T_map[new_y][new_x] == 1 || new_y >= Height)
{
legit = false;
break;
}
}
for (int i = 0; i < 4; i++)
{
int n = Blocktype[C_block][C_rotate][i];
int old_x = C_pos[1] + x_c[n];
int old_y = C_pos[0] + y_c[n];
if (legit)
{
T_map[old_y][old_x] = 0;
}
else
{
T_map[old_y][old_x] = 1;
}
}
if (legit)
{
C_pos[0] += 1;
for (int i = 0; i < 4; i++)
{
int n = Blocktype[C_block][C_rotate][i];
int new_x = C_pos[1] + x_c[n];
int new_y = C_pos[0] + y_c[n];
T_map[new_y][new_x] = 2;
}
state = nextstate;
}
else
{
for (int i = 0; i < Height ; i++)
{
bool check = true;
for (int j = 0; j < Width; j++)
{
if (T_map[i][j] != 1)
{
check = false;
break;
}
}
if (check == false)
{
continue;
}
else
{
score += 10;
gravity = INI_speed - score;
Update(T_map);
delay(10);
for (int j = i ; j >= 1 ; j--)
{
for (int k = 0 ; k < Width ; k++)
{
T_map[j][k] = T_map[j - 1][k];
}
}
for (int k = 0 ; k < Width ; k++)
{
T_map[0][k] = 0;
}
Update(T_map);
}
}
bool over = false;
for (int i = 0; i < Width ; i++)
{
if (T_map[1][i] == 1)
{
over = true;
break;
}
}
if (over)
{
for (int i = Height - 1; i >= 1; i--)
{
for (int j = 0; j < 8; j++)
{
T_map[i][j] = 0;
LC.setLed(0, i - 1, j, false);
Update(T_map);
}
}
state = -1;
}
else
{
state = 15;
}
}
Timer1[0].TimerSet();
Update(T_map);
}
void setup()
{
Serial.begin(9600);
//定義接角模式
pinMode(Rotate, INPUT);
pinMode(Right, INPUT);
pinMode(Left, INPUT);
pinMode(Down, INPUT);
pinMode(CIN, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(A0, INPUT);
randomSeed(analogRead(A0)); //產生隨機種子碼,A0空接會取得空氣中電壓,可視為亂碼
C_block = random(7);
//LED矩陣開啟
LC.shutdown(0, false);
//LED矩陣挑整亮度(0~15)
LC.setIntensity(0, 5);
for (int i = 0 ; i < 10; i++) //重設所有計時器
{
Timer1[i].TimerShutdown();
}
//清空地圖
for (int i = 0; i < Height; i++)
{
for (int j = 0; j < Width; j++)
{
T_map[i][j] = 0;
}
}
}
void loop()
{
Serial.println(state);
switch (state)
{
case -1://數值初始化
score = 0;
gravity = INI_speed;
for (int i = 0 ; i < 10; i++) //重設所有計時器
{
Timer1[i].TimerShutdown();
}
for (int i = 0; i <= 8; i++)
{
for (int j = 0; j < 8; j++)
{
T_map[i][j] = 0;
}
}
state = 0;
break;
case 0:
if (digitalRead(Rotate) == HIGH)
{
state = 10;
}
break;
case 10:
if (digitalRead(Rotate) == LOW)
{
state = 14;
}
break;
case 14:
for (int i = 0; i < Height; i++)
{
for (int j = 0; j < 8; j++)
{
T_map[i][j] = 0;
}
state = 15;
}
break;
case 15: //產生隨機方塊
C_block = random(7);
C_pos[0] = 1; //y
C_pos[1] = 4; //x
C_rotate = 0;
state = 20;
break;
case 20:
Timer1[0].TimerSet();
state = 25;
break;
case 25://偵測按鈕
if (digitalRead(Rotate) == HIGH)
{
Serial.println("rotate");
Timer1[1].TimerSet();
state = 30;
}
else if (digitalRead(Right) == HIGH)
{
Serial.println("right");
Timer1[1].TimerSet();
state = 35;
}
else if (digitalRead(Left) == HIGH)
{
Serial.println("left");
Timer1[1].TimerSet();
state = 40;
}
else if (digitalRead(Down) == HIGH)
{
Serial.println("down");
Timer1[1].TimerSet();
state = 45;
}
break;
case 30://旋轉
if (digitalRead(Rotate) == LOW)
{
C_Rotate(25);
}
else if (Timer1[1].TimerTimeout(500))
{
Timer1[2].TimerSet();
state = 31;
}
break;
case 31:
if (digitalRead(Rotate) == LOW)
{
C_Rotate(25);
}
else if (Timer1[2].TimerTimeout(100))
{
Timer1[2].TimerSet();
C_Rotate(state);
}
break;
case 35://右移
if (digitalRead(Right) == LOW)
{
C_Right(25);
}
else if (Timer1[1].TimerTimeout(500))
{
Timer1[2].TimerSet();
state = 36;
}
break;
case 36:
if (digitalRead(Right) == LOW)
{
C_Right(25);
}
else if (Timer1[2].TimerTimeout(100))
{
Timer1[2].TimerSet();
C_Right(state);
}
break;
case 40://左移
if (digitalRead(Left) == LOW)
{
C_Left(25);
}
else if (Timer1[1].TimerTimeout(500))
{
Timer1[2].TimerSet();
state = 41;
}
break;
case 41:
if (digitalRead(Left) == LOW)
{
C_Left(25);
}
else if (Timer1[2].TimerTimeout(100))
{
Timer1[2].TimerSet();
C_Left(state);
}
break;
case 45://下移
if (digitalRead(Down) == LOW)
{
C_Down(25);
}
else if (Timer1[1].TimerTimeout(500))
{
Timer1[2].TimerSet();
state = 46;
}
break;
case 46:
if (digitalRead(Down) == LOW)
{
C_Down(25);
}
else if (Timer1[2].TimerTimeout(100))
{
Timer1[2].TimerSet();
C_Down(state);
}
break;
}
//Fall down
if (Timer1[0].TimerTimeout(gravity))
{
C_Down(state);
}
}
```
:::