冰楓論壇

 找回密碼
 立即註冊
ads_sugarbook
搜索
查看: 484|回覆: 0
打印 上一主題 下一主題

[討論] ATmega8L 貪食蛇遊戲

[複製鏈接]

2609

主題

0

好友

948

積分

高級會員

Rank: 4

UID
373967
帖子
7535
主題
2609
精華
0
積分
948
楓幣
1650
威望
927
存款
26000
贊助金額
0
推廣
0
GP
1205
閱讀權限
50
在線時間
411 小時
註冊時間
2023-1-12
最後登入
2024-5-16

2023端午節紀念勳章 2023中秋節紀念勳章 2023聖誕節紀念勳章

跳轉到指定樓層
1
發表於 2023-4-6 05:33:31 |只看該作者 |倒序瀏覽
ATmega8L 貪食蛇遊戲程式碼。


#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>

// 定義顯示器引腳
#define DISPLAY_PORT PORTB
#define DISPLAY_DDR  DDRB

// 定義按鈕引腳
#define BUTTON_PIN   PINC
#define BUTTON_DDR   DDRC
#define BUTTON_LEFT  PC0
#define BUTTON_RIGHT PC1
#define BUTTON_UP    PC2
#define BUTTON_DOWN  PC3

// 定義蛇和食物
#define MAX_SNAKE_LENGTH 16
struct snake_t {
    uint8_t x[MAX_SNAKE_LENGTH];
    uint8_t y[MAX_SNAKE_LENGTH];
    uint8_t length;
    uint8_t direction;
};
struct food_t {
    uint8_t x;
    uint8_t y;
};

// 定義遊戲狀態
#define GAME_STATE_PLAYING 0
#define GAME_STATE_GAMEOVER 1
uint8_t game_state = GAME_STATE_PLAYING;

// 定義計時器
volatile uint32_t timer = 0;

// 7段顯示器字型
uint8_t font[] = {
    0b00111111, // 0
    0b00000110, // 1
    0b01011011, // 2
    0b01001111, // 3
    0b01100110, // 4
    0b01101101, // 5
    0b01111101, // 6
    0b00000111, // 7
    0b01111111, // 8
    0b01101111, // 9
};

// 初始化顯示器
void setup_display()
{
    // 設置顯示器引腳為輸出
    DISPLAY_DDR = 0xFF;
}

// 顯示一個數字
void display_number(uint8_t number)
{
    // 設置顯示器引腳狀態
    DISPLAY_PORT = font[number % 10];

    // 等待一段時間,以避免閃爍
    _delay_ms(2);

    // 關閉顯示器
    DISPLAY_PORT = 0x00;
}

// 初始化按鈕
void setup_buttons()
{
    // 設置按鈕引腳為輸入,啟用內部上拉電阻
    BUTTON_DDR &= ~(1 << BUTTON_LEFT) & ~(1 << BUTTON_RIGHT) & ~(1

<< BUTTON_UP) & ~(1 << BUTTON_DOWN);
BUTTON_PIN |= (1 << BUTTON_LEFT) | (1 << BUTTON_RIGHT) | (1 << BUTTON_UP) | (1 << BUTTON_DOWN);
}

// 檢查按鈕狀態
uint8_t check_button(uint8_t button)
{
return !(BUTTON_PIN & (1 << button));
}

// 初始化計時器
void setup_timer()
{
// 設置計時器0為CTC模式,64分頻
TCCR0 |= (1 << WGM01) | (1 << CS01) | (1 << CS00);

// 設置計時器比較值
OCR0 = 250;

// 啟用計時器比較中斷
TIMSK |= (1 << OCIE0);
}

// 計時器中斷處理
ISR(TIMER0_COMP_vect)
{
// 每4ms增加計時器
timer += 4;
}

// 初始化蛇
void init_snake(struct snake_t* snake)
{
// 蛇的初始長度為3,初始位置為(4, 4)
snake->length = 3;
snake->direction = 0;
snake->x[0] = 4;
snake->y[0] = 4;
snake->x[1] = 3;
snake->y[1] = 4;
snake->x[2] = 2;
snake->y[2] = 4;
}

// 顯示蛇
void display_snake(struct snake_t* snake)
{
for (uint8_t i = 0; i < snake->length; i++) {
// 計算在顯示器上的位置
uint8_t x = snake->x[i] + 1;
uint8_t y = snake->y[i] + 1;

    // 設置顯示器引腳狀態
    DISPLAY_PORT = 1 << x;
    _delay_ms(2);
    DISPLAY_PORT = 1 << y;
    _delay_ms(2);
}
}

// 移動蛇
void move_snake(struct snake_t* snake, struct food_t* food)
{
// 計算新的頭部位置
uint8_t new_x = snake->x[0];
uint8_t new_y = snake->y[0];
switch (snake->direction) {
case 0: // 向右移動
new_x++;
break;
case 1: // 向上移動
new_y--;
break;
case 2: // 向左移動
new_x--;
break;
case 3: // 向下移動
new_y++;
break;
}

// 檢查是否吃到食物
if (new_x == food->x && new_y == food->y) {
    // 食物位置改變
    food->x = rand() % 6 + 1;
    food->y = rand() % 6 + 1;

    // 蛇長度增加
    snake->length++;

    // 檢查是否達到最大長度
    if (snake->length > MAX_SNAKE_LENGTH

        // 遊戲結束
        game_over();
        return;
    }
}

// 移動蛇的身體
for (uint8_t i = snake->length - 1; i > 0; i--) {
    snake->x[i] = snake->x[i - 1];
    snake->y[i] = snake->y[i - 1];
}

// 移動蛇的頭部
snake->x[0] = new_x;
snake->y[0] = new_y;

// 檢查是否碰到自己
for (uint8_t i = 1; i < snake->length; i++) {
    if (snake->x[0] == snake->x[i] && snake->y[0] == snake->y[i]) {
        // 遊戲結束
        game_over();
        return;
    }
}
}

// 初始化食物
void init_food(struct food_t* food)
{
// 隨機選擇食物位置
food->x = rand() % 6 + 1;
food->y = rand() % 6 + 1;
}

// 顯示食物
void display_food(struct food_t* food)
{
// 計算在顯示器上的位置
uint8_t x = food->x + 1;
uint8_t y = food->y + 1;

// 設置顯示器引腳狀態
DISPLAY_PORT = 1 << x;
_delay_ms(2);
DISPLAY_PORT = 1 << y;
_delay_ms(2);
}

// 初始化遊戲
void init_game()
{
// 初始化隨機數生成器
srand(timer);

// 初始化按鈕和顯示器
setup_io();

// 初始化計時器
setup_timer();

// 初始化蛇和食物
init_snake(&snake);
init_food(&food);
}

// 遊戲主循環
void game_loop()
{
while (1) {
// 檢查按鈕狀態,改變蛇的方向
if (check_button(BUTTON_LEFT)) {
snake.direction = 2;
} else if (check_button(BUTTON_RIGHT)) {
snake.direction = 0;
} else if (check_button(BUTTON_UP)) {
snake.direction = 1;
} else if (check_button(BUTTON_DOWN)) {
snake.direction = 3;
}

    // 移動蛇和顯示
    move_snake(&snake, &food);
    display_snake(&snake);
    display_food(&food);

    // 等待一段時間
    _delay_ms(250);
}
}

int main(void)
{
// 初始化遊戲
init_game();

kotlin
Copy code
// 遊戲主循環
game_loop();

return 0;
}




其中,這個程式碼的核心是 move_snake 函數,它接收蛇和食物的指針,檢查蛇是否碰到邊界或食物,更新蛇的位置,並檢查蛇是否碰到自己。其他函數,如 init_snake、init_food、display_snake 和 display_food,用於初始化蛇和食物,以及在顯示器上顯示它們。
[發帖際遇]: 洪嵐峰 為了證實「蜂蜜檸檬」的功效,因此購買一瓶「蜂蜜檸檬」搭配「鳳梨酥」,花費 1 楓幣 幸運榜 / 衰神榜
收藏收藏0 推0 噓0


把本文推薦給朋友或其他網站上,每次被點擊增加您在本站積分: 1骰子
複製連結並發給好友,以賺取推廣點數
簡單兩步驟,註冊、分享網址,即可獲得獎勵! 一起推廣文章換商品、賺$$
高級模式
B Color Image Link Quote Code Smilies |上傳

廣告刊登意見回饋關於我們管群招募本站規範DMCA隱私權政策

Copyright © 2011-2024 冰楓論壇, All rights reserved

免責聲明:本網站是以即時上載留言的方式運作,本站對所有留言的真實性、完整性及立場等,不負任何法律責任。

而一切留言之言論只代表留言者個人意見,並非本網站之立場,用戶不應信賴內容,並應自行判斷內容之真實性。

小黑屋|手機版|冰楓論壇

GMT+8, 2024-5-16 07:35

回頂部