void InitMap(int *a, int m) { // m = 9/16/25
a[0] = 0; // 空格固定在位置 0?實際應隨機
for (int i=1; i
關鍵數學結論:N-Puzzle 可解條件為逆序對數 + 空格行號 奇偶性不變。隨機打亂有 50% 不可解。正確做法:從目標態出發隨機合法移動 N 步,保證可解。
void Move(int *a, int m, int r) { // r=3/4/5
char ch = _getch();
int offset;
if (ch=='w') offset = -r; // 上:索引 - 列數
else if (ch=='s') offset = r; // 下:索引 + 列數
else if (ch=='a') offset = -1; // 左:索引 -1
else if (ch=='d') offset = 1; // 右:索引 +1
else return;
// 關鍵:防止跨行移動(如第3列左移到第2列末尾)
int zeroPos = FindZero(a, m);
if (ch=='a' && zeroPos % r == 0) return; // 左邊界不能左移
if (ch=='d' && zeroPos % r == r-1) return; // 右邊界不能右移
if (ch=='w' && zeroPos < r) return; // 頂行不能上移
if (ch=='s' && zeroPos >= m-r) return; // 底行不能下移
// 交換
a[zeroPos] = a[zeroPos + offset];
a[zeroPos + offset] = 0;
step++;
}
void Draw(int *a, int m, int r) {
system("cls");
for (int i=0; i
int main() {
srand(time(NULL));
char ch;
printf("Select: 1.3x3 2.4x4 3.5x5 4.Exit\n");
ch = _getch();
int m, r;
if (ch=='1') { m=9; r=3; }
else if (ch=='2') { m=16; r=4; }
else if (ch=='3') { m=25; r=5; }
else return 0;
int a[25];
InitMap(a, m);
Draw(a, m, r);
while (1) Move(a, m, r); // 內部含死循環讀取按鍵
}
拼圖遊戲是練習一維數組模擬二維邏輯、邊界條件處理、隨機算法、遊戲循環的優秀案例。核心難點在於跨行移動阻擋與可解性生成,掌握這兩點即可舉一反三實現更複雜的棋類/益智遊戲邏輯。