1
0
Fork
You've already forked MineSweeper
0
Mine Sweeper
  • C 100%
2026年01月13日 14:32:57 +08:00
assets o_o ! 2026年01月12日 23:25:20 +08:00
include o_O!! 2026年01月13日 14:32:57 +08:00
lili o_O!! 2026年01月13日 14:32:57 +08:00
.gitignore o_o ! 2026年01月12日 23:25:20 +08:00
mineSw1.c o_o ! 2026年01月12日 23:25:20 +08:00
Minesweeper.png o_O!! 2026年01月13日 14:32:57 +08:00
README.md o_o ! 2026年01月12日 23:25:20 +08:00

MineSweeper Game (mineSw1.c)

這是一個使用 Raylib 圖形庫開發的經典踩地雷(Minesweeper)遊戲程式。程式以 C 語言撰寫,支援不同的難度等級,並包含音效、圖片資源和自訂字體。

專案概述

這個程式實現了完整的踩地雷遊戲邏輯,包括:

  • 三種難度:簡單 (9x9, 10 地雷)、中等 (16x16, 40 地雷)、困難 (30x16, 99 地雷)
  • 左鍵揭開格子,右鍵標記旗子或問號
  • 第一次點擊保證安全(不會踩到地雷)
  • 勝利條件:揭開所有非地雷格子
  • 失敗條件:揭開地雷
  • 計時器和地雷計數器
  • 音效和視覺效果

依賴項

  • Raylib: 圖形、音訊和輸入處理庫
  • 自訂庫: lili/myfont.c (自訂字體), lili/util.h (工具函式)
  • 資源檔案:
    • assets/brick.png: 磚塊圖片 (用於格子)
    • assets/num.png: 數字圖片 (0-9 和紅色方塊)
    • assets/flag.wav: 插旗音效
    • assets/boom.wav: 爆炸音效
    • assets/win.wav: 勝利音效
    • assets/question.wav: 問號音效

編譯和運行

Windows (使用 MinGW 或 MSVC)

gcc mineSw1.c -o mineSw1.exe -lraylib -lwinmm -lgdi32 -lopengl32
./mineSw1.exe

Linux

gcc mineSw1.c -o mineSw1 -lraylib -lGL -lm -lpthread -ldl -lrt -lX11
./mineSw1

macOS

gcc mineSw1.c -o mineSw1 -lraylib -framework CoreVideo -framework IOKit -framework Cocoa -framework GLUT -framework OpenGL
./mineSw1

程式流程

  1. 初始化階段 (main()):

    • 初始化隨機種子
    • 設定視窗 (800x600, "Raylib Minesweeper")
    • 啟動音訊裝置
    • 設定目標 FPS 為 60
    • 載入自訂字體
    • 初始化遊戲結構 (GameInit())
  2. 主要遊戲循環:

    • 更新階段 (Update()):
      • 根據遊戲狀態處理輸入
      • 在 MENU 狀態下,按 1/2/3 選擇難度並重設遊戲
      • 在 PLAYING 狀態下,處理滑鼠輸入 (左鍵揭開,右鍵標記)
      • 檢查勝利或失敗條件
    • 繪製階段 (Draw()):
      • 清除背景
      • 根據狀態繪製菜單或遊戲畫面
      • 顯示地雷數量、時間、網格等
  3. 清理階段:

    • 釋放資源 (GameFini())
    • 關閉音訊裝置和視窗

遊戲狀態

  • MENU: 顯示難度選擇菜單
  • PLAYING: 遊戲進行中
  • WON: 勝利狀態
  • LOST: 失敗狀態

關鍵函式說明

初始化與清理

  • GameInit(Game* game):

    • 初始化遊戲狀態為 MENU
    • 載入磚塊紋理 (brick.png) 和數字紋理 (num.png)
    • 定義紋理切片矩形
    • 載入音效檔案
    • 如果資源載入失敗,使用生成的備用圖片
  • GameFini(Game* game):

    • 釋放所有載入的紋理和音效資源

遊戲邏輯

  • ResetGame(Game* game, Difficulty diff):

    • 根據選擇的難度設定遊戲參數 (行列數、地雷數、格子大小)
    • 重設計時器和狀態
    • 清空格子網格
    • 調整視窗大小以適應網格
  • GenMines(Game* game, Cell* cell):

    • 在第一次點擊後生成地雷
    • 確保點擊格子和其周圍 3x3 區域沒有地雷
    • 計算每個格子的地雷鄰居數量
    • 設定每個格子的鄰居指標陣列
  • RevealCell(Game* game, Cell* cell):

    • 遞歸揭開格子
    • 如果是地雷,設定為 LOST 狀態並播放爆炸音效
    • 如果地雷計數為 0,自動揭開所有鄰居格子
    • 第一次點擊時觸發地雷生成
  • CheckWin(Game* game):

    • 檢查所有非地雷格子是否已被揭開
    • 如果是,設定為勝利狀態並播放勝利音效
  • ToggleMark(Game* game, int r, int c):

    • 切換格子標記狀態:無標記 → 旗子 → 問號 → 無標記
    • 更新剩餘地雷計數
    • 播放相應音效
  • RevealAllMines(Game* game):

    • 在失敗時一次性揭開所有地雷格子
    • 防止重複執行

繪製函式

  • DrawCustomDigit(Game* game, int digit, float x, float y, float scale):

    • 使用數字紋理繪製單個數字 (0-10,10 為紅色方塊)
  • DrawCustomNumber(Game* game, int number, float x, float y, float scale):

    • 將數字轉換為三個數字字串,使用 DrawCustomDigit 繪製

主循環函式

  • Update(Game* game):

    • 處理鍵盤和滑鼠輸入
    • 更新遊戲狀態和邏輯
  • Draw(Game* game):

    • 根據當前狀態繪製適當的畫面
    • 顯示地雷數量和經過時間
    • 繪製網格,根據格子狀態使用不同紋理和文字

資料結構

DifficultySettings

  • rows: 行數
  • cols: 列數
  • mines: 地雷數
  • cellSize: 格子像素大小

Cell

  • isMine: 是否為地雷
  • isRevealed: 是否已被揭開
  • isFlagged: 是否標記旗子
  • isQuestion: 是否標記問號
  • mineCount: 周圍地雷數量 (0-8)
  • neighborsCount: 有效鄰居數量 (3-8)
  • neighbors[8]: 指向鄰居格子的指標

Game

  • grid[MAX_ROWS][MAX_COLS]: 二維格子陣列
  • currentState: 當前遊戲狀態
  • currentDifficulty: 當前難度
  • minesLeft: 剩餘地雷數量
  • startTime / endTime: 開始和結束時間 (用於計時)
  • curC / curR: 當前滑鼠所在的列/行
  • brickTexture / numberTexture: 載入的紋理
  • brickRecs[6] / numberRecs[11]: 紋理切片矩形
  • firstClick: 是否為第一次點擊 (用於安全機制)
  • gameOverRevealed: 失敗時是否已顯示地雷
  • 多個音效物件

操作說明

  • 菜單:

    • 按 1: 簡單難度
    • 按 2: 中等難度
    • 按 3: 困難難度
  • 遊戲中:

    • 左鍵點擊: 揭開格子
    • 右鍵點擊: 切換標記 (無/旗子/問號)
    • 中鍵點擊: 同右鍵
  • 結束遊戲:

    • 勝利或失敗後,按 R 鍵返回菜單

資源載入備用機制

程式設計時考慮了資源檔案可能不存在的情況:

  • 如果 brick.png 不存在,使用 GenImageChecked() 生成格子狀圖片
  • 如果 num.png 不存在,使用 GenImageChecked() 生成數字區域
  • 如果音效檔案不存在,程式仍能正常運行,只是沒有音效

這使得程式在沒有完整資源的情況下也能運行,適合開發和測試。

最佳實踐

  • 使用紋理圖集 (atlas) 而非個別圖片,提高載入效率
  • 有效率的地雷生成演算法,避免重複隨機位置
  • 遞歸揭開演算法處理連續空白區域
  • 狀態機設計清晰分離遊戲邏輯和繪製
  • 資源管理:載入時初始化,結束時清理