代碼意圖:用 wasd 或 lavy 控制字符 'o' 在 5×10 地圖移動,按 q 退出。實際運行:無論按鍵,畫面靜止,「卡住」不動。
x、y 作用域錯位(致命)int x,y; // 全局/外層作用域
x=1; y=1; // 初始化
c=getch();
while (c!='q') {
// ...
for (x=0; x<5; x++) { // 此處 x 被循環覆蓋為 0..4
for (y=0; y<10; y++) // y 同理被覆蓋
printf("%c", a[x][y]);
}
c=getch();
}
後果:每次渲染循環結束後,x=4、y=9。下一次按鍵處理時,角色坐標已非玩家移動後的位置,而是固定在右下角,導致「看不見移動效果」。
for (x=0; ...) 直接使用外層邏輯坐標變量作為循環計數器,屬於經典「變量復用」反模式。
while (c!='q') {
clrscr();
// 移動邏輯保持不變,操作外層 x, y
if (c=='l') { a[x][y]=' '; y++; a[x][y]='o'; }
// ... 其他方向
// 渲染用新變量 i, j
for (int i=0; i<5; i++) {
for (int j=0; j<10; j++)
printf("%c", a[i][j]);
printf("\n");
}
c=getch();
}
void render(char map[5][10]) {
system("cls"); // 或 clrscr()
for (int i=0; i<5; i++) {
for (int j=0; j<10; j++) putchar(map[i][j]);
putchar('\n');
}
}
int main() {
char map[5][10] = { ... }; // 初始化地圖
int px=1, py=1; // 玩家坐標獨立變量
map[px][py] = 'o';
render(map);
while ((c=getch()) != 'q') {
map[px][py] = ' ';
switch(c) {
case 'l': py++; break;
case 'a': py--; break;
case 'y': px--; break;
case 'v': px++; break;
}
// 邊界檢查...
map[px][py] = 'o';
render(map);
}
return 0;
}
px、py 是否在 [0,4]×[0,9] 範圍內,防止數組越界崩潰。clrscr() 非標準,Windows 用 system("cls"),Linux/Mac 用 system("clear"),或用 ANSI 轉義序列 printf("\033[2J\033[H")。getch() 會阻塞,若需實時遊戲循環,需用 kbhit() 配合或多線程。「卡住」實為邏輯坐標被渲染循環變量覆蓋。牢記:循環計數器專用,業務變量專用,絕不混用。養成「最小作用域」習慣,在 for 循環頭部直接 int i=0 宣告,從根源杜絕此類低級錯誤。