三子棋是一款經典的棋盤遊戲,規則簡單卻極具策略性。本文將帶領大家使用 C 語言從零開始實作一個可在終端機執行的三子棋遊戲,涵蓋棋盤繪製、玩家與電腦輪流落子、勝負判定等核心邏輯。無論你是程式設計新手,或是想複習陣列與函式操作,這都是一個極佳的練習專案。
遊戲的核心在於棋盤狀態的管理。我們使用一個 3x3 的二維字元陣列 char board[3][3] 來儲存棋盤資訊,初始化為空格 ' '。玩家使用 '@' 代表棋子,電腦使用 '#'。另設一個全域變數 int movesLeft = 9 記錄剩餘可落子位置,每落一子遞減,作為判斷平手的依據。
printBoard()使用雙層迴圈遍歷陣列,配合 printf 格式化輸出,將棋盤以直觀的格線形式呈現在終端機。每次落子後呼叫此函式,即可即時更新畫面。
playerMove()board[r][c] != ' ')。movesLeft。computerMove()srand(time(NULL)) 設定種子,rand() % 3 產生 0-2 的隨機索引。while 迴圈確保隨機到的位置為空,避免覆蓋既有棋子。checkWinner()直接硬編碼列舉所有 8 種獲勝條件(3 橫、3 直、2 對角線),分別檢查是否為三個 '@'(玩家贏)或三個 '#'(電腦贏)。若棋盤滿 movesLeft == 0 且無贏家,回傳平手。此寫法雖程式碼較長,但執行效率極高,適合初學者理解邏輯。
main() 函式初始化棋盤後,進入無限迴圈 while(1):
迴圈結束後,根據 checkWinner() 回傳值輸出最終結果:「玩家獲勝」、「電腦獲勝」或「平手」。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char board[3][3] = {0};
int movesLeft = 9;
void printBoard() {
int i, j;
printf(" | | \n");
for (i = 0; i < 3; i++) {
printf("_%c_|_%c_|_%c_\n", board[i][0], board[i][1], board[i][2]);
if (i < 2) printf(" | | \n");
}
}
void playerMove() {
int r, c;
printf("玩家(@) 請輸入座標 (行 列): ");
scanf("%d %d", &r, &c);
if (r < 1 || r > 3 || c < 1 || c > 3 || board[r-1][c-1] != ' ') {
printf("該位置無法落子,請重新輸入!\n");
playerMove();
} else {
board[r-1][c-1] = '@';
movesLeft--;
}
}
void computerMove() {
int r, c;
printf("電腦(#) 正在思考...\n");
srand((unsigned)time(NULL));
do {
r = rand() % 3;
c = rand() % 3;
} while (board[r][c] != ' ');
board[r][c] = '#';
movesLeft--;
}
int checkWinner() {
// 檢查玩家 (@)
if ((board[0][0]==board[0][1] && board[0][1]==board[0][2] && board[0][2]=='@') ||
(board[1][0]==board[1][1] && board[1][1]==board[1][2] && board[1][2]=='@') ||
(board[2][0]==board[2][1] && board[2][1]==board[2][2] && board[2][2]=='@') ||
(board[0][0]==board[1][0] && board[1][0]==board[2][0] && board[2][0]=='@') ||
(board[0][1]==board[1][1] && board[1][1]==board[2][1] && board[2][1]=='@') ||
(board[0][2]==board[1][2] && board[1][2]==board[2][2] && board[2][2]=='@') ||
(board[0][0]==board[1][1] && board[1][1]==board[2][2] && board[2][2]=='@') ||
(board[0][2]==board[1][1] && board[1][1]==board[2][0] && board[2][0]=='@'))
return 1;
// 檢查電腦 (#)
if ((board[0][0]==board[0][1] && board[0][1]==board[0][2] && board[0][2]=='#') ||
(board[1][0]==board[1][1] && board[1][1]==board[1][2] && board[1][2]=='#') ||
(board[2][0]==board[2][1] && board[2][1]==board[2][2] && board[2][2]=='#') ||
(board[0][0]==board[1][0] && board[1][0]==board[2][0] && board[2][0]=='#') ||
(board[0][1]==board[1][1] && board[1][1]==board[2][1] && board[2][1]=='#') ||
(board[0][2]==board[1][2] && board[1][2]==board[2][2] && board[2][2]=='#') ||
(board[0][0]==board[1][1] && board[1][1]==board[2][2] && board[2][2]=='#') ||
(board[0][2]==board[1][1] && board[1][1]==board[2][0] && board[2][0]=='#'))
return 0;
if (movesLeft == 0) return -1; // 平手
return 2; // 遊戲繼續
}
int main() {
int i, j;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
board[i][j] = ' ';
while (1) {
printBoard();
int result = checkWinner();
if (result != 2) break;
playerMove();
printBoard();
result = checkWinner();
if (result != 2) break;
computerMove();
}
switch (checkWinner()) {
case 1: printf("\n恭喜!玩家獲勝!\n"); break;
case 0: printf("\n電腦獲勝,再接再厲!\n"); break;
case -1: printf("\n平手!\n"); break;
}
system("pause");
return 0;
}
system("cls") (Windows) 或 ANSI 轉義碼清屏,提升視覺體驗。這個專案完整展示了 C 語言處理陣列、函式模組化、隨機數生成與流程控制的基礎能力,是從「寫代碼」邁向「設計程式」的關鍵一步。建議動手敲一遍,並嘗試加入上述優化,加深理解。