#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define OLED_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// 定義按鍵引腳
#define LEFT_BUTTON_PIN 2
#define RIGHT_BUTTON_PIN 3
#define UP_BUTTON_PIN 4
#define DOWN_BUTTON_PIN 5
const int mazeWidth = 16;
const int mazeHeight = 8;
int maze[mazeWidth][mazeHeight];
int playerX = 1;
int playerY = 1;
int exitX, exitY;
void setup() {
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
display.display();
// 設置隨機種子
randomSeed(analogRead(0));
generateMaze();
placeExit();
drawMaze();
// 設置按鍵引腳為輸入
pinMode(LEFT_BUTTON_PIN, INPUT_PULLUP);
pinMode(RIGHT_BUTTON_PIN, INPUT_PULLUP);
pinMode(UP_BUTTON_PIN, INPUT_PULLUP);
pinMode(DOWN_BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
bool moved = false;
// 偵測按鍵按下,控制角色移動
if (digitalRead(LEFT_BUTTON_PIN) == LOW && maze[playerX - 1][playerY] != 1) {
playerX--;
moved = true;
} else if (digitalRead(RIGHT_BUTTON_PIN) == LOW && maze[playerX + 1][playerY] != 1) {
playerX++;
moved = true;
} else if (digitalRead(UP_BUTTON_PIN) == LOW && maze[playerX][playerY - 1] != 1) {
playerY--;
moved = true;
} else if (digitalRead(DOWN_BUTTON_PIN) == LOW && maze[playerX][playerY + 1] != 1) {
playerY++;
moved = true;
}
// 檢查勝利條件
if (playerX == exitX && playerY == exitY) {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print(F("You Win!"));
display.display();
while (1); // 停止遊戲
}
if (moved) {
drawMaze();
delay(100); // 減少延遲
}
}
void generateMaze() {
// 初始化迷宮
for (int x = 0; x < mazeWidth; x++) {
for (int y = 0; y < mazeHeight; y++) {
maze[x][y] = 1; // 填充所有牆壁
}
}
// 設置起點
playerX = 1;
playerY = 1;
maze[playerX][playerY] = 0; // 起點
// 開始深度優先搜索生成迷宮
carvePassagesFrom(1, 1);
}
void carvePassagesFrom(int x, int y) {
int directions[] = {0, 1, 2, 3};
// 打亂方向
for (int i = 0; i < 4; i++) {
int r = random(4);
int temp = directions[i];
directions[i] = directions[r];
directions[r] = temp;
}
for (int i = 0; i < 4; i++) {
int nx = x, ny = y;
switch (directions[i]) {
case 0: nx = x + 2; break; // 右
case 1: ny = y + 2; break; // 下
case 2: nx = x - 2; break; // 左
case 3: ny = y - 2; break; // 上
}
if (nx > 0 && nx < mazeWidth - 1 && ny > 0 && ny < mazeHeight - 1 && maze[nx][ny] == 1) {
maze[nx][ny] = 0;
maze[nx - (nx - x) / 2][ny - (ny - y) / 2] = 0;
carvePassagesFrom(nx, ny);
}
}
}
void placeExit() {
while (true) {
exitX = random(1, mazeWidth - 1);
exitY = random(1, mazeHeight - 1);
if (maze[exitX][exitY] == 0) {
maze[exitX][exitY] = 3;
break;
}
}
}
void drawMaze() {
display.clearDisplay();
for (int y = 0; y < mazeHeight; y++) {
for (int x = 0; x < mazeWidth; x++) {
if (maze[x][y] == 1) {
display.drawRect(x * 8, y * 8, 8, 8, SSD1306_WHITE); // 畫牆壁
} else if (x == exitX && y == exitY) {
display.fillRect(x * 8, y * 8, 8, 8, SSD1306_WHITE); // 畫出出口
} else if (x == playerX && y == playerY) {
display.fillRect(x * 8, y * 8, 8, 8, SSD1306_WHITE); // 畫出角色
}
}
}
display.display();
}