首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

掃雷遊戲純 C 實現(二):round_num_mines 優化演進與數組越界疑惑解析

     編輯:關於C語言

優化演進路線圖

  1. 初版:手寫 8 種邊界情況,代碼冗長、易出錯。
  2. 統一迴圈版:雙層 for 遍歷 3×3 區域,配合 if (ni>=0 ...) 邊界檢查。
  3. 哨兵擴展版:陣列四周各加一圈 '0',核心迴圈**零邊界判斷**,最符合《C程式設計語言》風格。

讀者提問:為何哨兵法不會數組越界?

原始碼片段:


char round_num_mines(int i, int j) {
    if (map[i][j] == '*') return '*';
    int k = 0;
    if (map[i+1][j] == '*') k++;
    if (map[i+1][j-1] == '*') k++;
    if (map[i+1][j+1] == '*') k++;
    if (map[i][j+1] == '*') k++;
    if (map[i-1][j] == '*') k++;
    if (map[i-1][j+1] == '*') k++;
    if (map[i][j-1] == '*') k++;
    if (map[i-1][j-1] == '*') k++;
    return k;
}

答案:此段代碼**假設**調用者傳入的 i,j 已經是**物理陣列下標**(即已含哨兵偏移),且物理陣列大小為 [MAX_X+2][MAX_Y+2]。
若邏輯棋盤為 m×n,物理索引範圍為 1..m, 1..n,哨兵佔據 0 與 m+1/n+1。
核心迴圈最大訪問 i±1, j±1 ∈ [0..m+1],**嚴格在分配範圍內**。

教科書改進版(書本代碼重現)


// 1. 定義方向向量
static const int dx[8] = {-1,-1,-1, 0,0, 1,1,1};
static const int dy[8] = {-1, 0, 1,-1,1,-1,0,1};

char round_num_mines(int x, int y) { // x,y 為邏輯座標 0-based
    if (map[x+1][y+1] == '*') return '*';
    int cnt = 0;
    for (int d = 0; d < 8; ++d)
        if (map[x+1+dx[d]][y+1+dy[d]] == '*') cnt++;
    return (char)('0' + cnt);
}
  • 方向向量 消除手寫 8 條 if,便於維護與擴展(如六角棋盤只需改向量表)。
  • 哨兵偏移 +1** 統一處理,核心邏輯極其乾淨。

常見錯誤對照表

錯誤現象原因修正
運行時崩潰/異常數值未分配哨兵圈,或邏輯座標未 +1 直接用於物理陣列陣列定義 [MAX+2][MAX+2],初始化哨兵,調用時 +1
邊緣格子計數錯誤忘記跳過自身 (dx,dy)==(0,0)方向向量表只含 8 個鄰居,或迴圈內 continue
地雷顯示為數字未優先判斷 map[x+1][y+1]=='*'函式開頭立即返回 '*'

效能對比(參考)

  • 三種寫法在現代編譯器 -O2 下編譯出的機器碼**幾乎相同**(循環展開、邊界檢查消除)。
  • 哨兵版原始碼最短、認知負擔最低,**推薦作為最終版本**。

下一步

第三篇將進入 **Win32 API 視窗建立、GDI 繪圖、訊息迴圈**,把邏輯層接上圖形介面。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved