// 演算法：一次掃描整個棋盤。對每個已填數字，檢查它所在的「列/行/小方塊」是否已出現過該數字。
// Algorithm: single pass. For each filled digit, check if it already appeared in its row / column / box.
// 用布林陣列當紀錄表（數字只有 1-9），命中重複就回傳 false，全部通過回傳 true。
// Use boolean tables (digits are 1-9 only); a repeat means false, otherwise true.

#include <stdbool.h>   // 讓我們能使用 bool / true / false / lets us use bool, true, false
#include <string.h>    // 提供 memset，用來把陣列一次清成 0 / provides memset to zero an array at once

// LeetCode 給的是「字串陣列的陣列」：board[i] 是一行字串，board[i][j] 是字元。
// LeetCode passes an array of strings: board[i] is one row, board[i][j] is a char.
bool isValidSudoku(char** board, int boardSize, int* boardColSize) {
    // 三張紀錄表，大小 9×10。第二維用 10 是為了讓索引能直接用數字 1..9（索引 0 不用，較直覺）。
    // Three tables, 9×10. Width 10 so we can index directly by digit 1..9 (index 0 unused, clearer).
    bool rows[9][10];
    bool cols[9][10];
    bool boxes[9][10];

    // memset 把整塊記憶體的每個 byte 設成 0；對 bool 來說 0 就是 false，等於全部清空。
    // memset sets every byte to 0; for bool, 0 means false, so this clears all tables.
    memset(rows, 0, sizeof(rows));
    memset(cols, 0, sizeof(cols));
    memset(boxes, 0, sizeof(boxes));

    // 外層走 9 列，內層走 9 行，逐格檢查。
    // Outer loop over 9 rows, inner over 9 columns; visit each cell.
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            char c = board[i][j];          // 取出這一格的字元 / read this cell's char

            if (c == '.') continue;        // 空格不檢查，直接跳到下一格 / empty cell: skip to next

            // 字元轉成數字：'5' - '0' == 5。字元在記憶體裡是編碼，相減得到 0..9 的整數。
            // Char to int: '5' - '0' == 5. Chars are codes; subtracting '0' yields the integer 0..9.
            int d = c - '0';

            // 小方塊編號：i/3 是整數除法（丟小數），把列壓成 0/1/2；乘 3 再加 j/3，得到 0..8。
            // Box id: i/3 is integer division (drops fraction) giving 0/1/2; *3 + j/3 yields 0..8.
            int b = (i / 3) * 3 + (j / 3);

            // 若這個數字已在「同列」或「同行」或「同方塊」出現過，就違反規則，回傳 false。
            // If this digit already appeared in same row / col / box, a rule is broken → return false.
            if (rows[i][d] || cols[j][d] || boxes[b][d]) {
                return false;
            }

            // 否則把這個數字在三張表裡都標記為「已出現」，供後面的格子比對。
            // Otherwise mark this digit as seen in all three tables for later cells to compare against.
            rows[i][d] = true;
            cols[j][d] = true;
            boxes[b][d] = true;
        }
    }

    // 全部掃完都沒衝突，棋盤有效。
    // No conflict after the full scan: the board is valid.
    return true;
}
