三子棋
目錄
一、問題介紹
三子棋,在民間又叫井字棋,因為人們在游玩時常常不畫棋盤的邊框,正如漢字中的“井”字,多稱為“井字棋”,
三子棋的游戲規則十分的簡單:
在3×3的棋盤雙方輪流下棋(先手一般的棋子為“X”,后手為“O”),當有一方所下的棋子連成一條直線即為勝利!
?
二、實作思路
- 創建游戲選單
- 初始化棋盤
- 列印棋盤
- 玩家下棋(判斷是否勝利)
- 電腦下棋(判斷是否勝利)
- 游戲結束
三、實作流程
1.創建游戲選單
//選單函式
void menu(void)
{
printf("|---------------|\n");
printf("|--- 1.START ---|\n");
printf("|--- 0.EXIT ---|\n");
printf("|---------------|\n");
}
1.開始游戲 0.退出游戲
2.初始化棋盤
使用全域變數創建3×3的棋盤
使用全域變數的原因:
- 后續修改棋盤大小更為便捷
- 代碼可讀性加強
//定義行、列
#define ROW 3
#define COL 3
//初始化棋盤函式
void InitChessBoard(char Board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
//把陣列中每個元素初始化為空格
Board[i][j] = ' ';
}
}
}
3.列印棋盤
在這里,為了后續棋盤的大小方便改變,將分割行分別列印
//列印棋盤函式
void DisplayChessBoard(char Board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
//列印“ 字符 | 字符 | 字符 ”
printf(" %c ", Board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
//列印完一行之后換行
printf("\n");
if (i <row-1)
{
//列印“---|---|---”
for (j = 0; j < row; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
}
//列印完一行之后換行
printf("\n");
}
}
4.玩家下棋
玩家需通過輸入[1,3]區間內的數字來落子“x”
- 當玩家輸入超出棋盤大小的坐標時,提醒玩家輸入坐標錯誤并重新輸入
- 當玩家輸入已被占用的棋盤坐標時,提醒玩家輸入坐標錯誤并重新輸入
//玩家下棋函式
void PlayerMove(char Board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("player(行 列):>");
//玩家輸入坐標
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//玩家輸入區間為[1, 3]
if (Board[x - 1][y - 1] == ' ')
{
Board[x - 1][y - 1] = 'x';
break;
}
else
{
printf("該坐標已被占用,請重新輸入!\a\n\n");
}
}
else
{
printf("輸入坐標非法,請重新輸入!\a\n\n");
}
}
}
5.電腦下棋
電腦下棋需要使用生成亂數種子,并且保證電腦在空的坐標上落子
在主調函式中使用生成亂數函式, 確保生成的亂數為隨機:
srand((unsigned int)time(NULL));
//time的函式回傳型別是time_t
//在這里使用強制轉換型別(unsigned int)
//電腦下棋函式
void ComputerMove(char Board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("computer:\n");
while (1)
{
//獲取時間亂數
x = rand() % row;
y = rand() % col;
if (Board[x][y] == ' ')
{
Board[x][y] = 'o';
break;
}
}
}
6.判斷游戲勝利
在這一步我們需要定義兩個函式:
- IsWin函式(判斷是否勝利)
- IsFull函式(判斷棋盤是否下滿)
我們約定當回傳“x”時玩家勝利
回傳“o”時電腦勝利
回傳“q”時代表平局
回傳“c”時代表棋盤未被填滿游戲繼續
//判斷是否勝利函式
char IsWin(char Board[ROW][COL], int row, int col)
{
int i = 0;
//判斷行
for (i = 0; i < row; i++)
{
if (Board[i][0] == Board[i][1]
&& Board[i][1] == Board[i][2]
&& Board[i][1] != ' ')
{
return Board[i][1];
}
}
//判斷列
for (i = 0; i < col; i++)
{
if (Board[0][i] == Board[1][i]
&& Board[1][i] == Board[2][i]
&& Board[1][i] != ' ')
{
return Board[1][i];
}
}
//判斷對角線"\"
if (Board[0][0] == Board[1][1]
&& Board[1][1] == Board[2][2]
&& Board[1][1] != ' ')
{
return Board[1][1];
}
//判斷對角線"/"
if (Board[0][2] == Board[1][1]
&& Board[1][1] == Board[2][0]
&& Board[1][1] != ' ')
{
return Board[1][1];
}
//檢查棋盤是否填滿
if (IsFull == 1)
{
//回傳平局
return 'q';
}
//回傳繼續
return 'c';
}
//判斷棋盤是否被填滿函式
int IsFull(char Board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for(i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (Board[i][j] == ' ')
return 0;
}
}
return 1;
}
7.游戲函式和主調函式
//游戲實作函式
void Game(char Board[ROW][COL], int row, int col)
{
InitChessBoard(Board, ROW, COL);
DisplayChessBoard(Board, ROW, COL);
while (1)
{
PlayerMove(Board, ROW, COL);
DisplayChessBoard(Board, ROW, COL);
if (IsWin(Board, ROW, COL) != 'c')
break;
ComputerMove(Board, ROW, COL);
DisplayChessBoard(Board, ROW, COL);
if (IsWin(Board, ROW, COL) != 'c')
break;
}
if (IsWin(Board, ROW, COL) == 'x')
printf("PLAYER WIN!\n\n");
else if (IsWin(Board, ROW, COL) == 'o')
printf("COMPUTER WIN!\n\n");
else
printf("平局!\n\n");
}
//主調函式
int main(void)
{
srand((unsigned int)time(NULL));
char Board[ROW][COL] = { 0 };
int input = 0;
do
{
menu();
printf("please enter:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("GAME START\n");
Game(Board, ROW, COL);
break;
case 0:
printf("GAME EXIT\n\a");
break;
default:
printf("ERROR!\n\a");
}
} while (input);
return 0;
}
四、代碼總覽
#define _CRT_SECURE_NO_WARNINGS 1
//程式所需頭檔案
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//定義行、列
#define ROW 3
#define COL 3
//選單函式
void menu(void)
{
printf("|---------------|\n");
printf("|--- 1.START ---|\n");
printf("|--- 0.EXIT ---|\n");
printf("|---------------|\n");
}
//初始化棋盤函式
void InitChessBoard(char Board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
Board[i][j] = ' ';
}
}
}
//列印棋盤函式
void DisplayChessBoard(char Board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", Board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");//列印完一行之后換行
if (i <row-1)
{
for (j = 0; j < row; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
}
printf("\n");
}
}
//玩家下棋函式
void PlayerMove(char Board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("player(行 列):>");
//玩家輸入坐標
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//玩家輸入區間為[1, 3]
if (Board[x - 1][y - 1] == ' ')
{
Board[x - 1][y - 1] = 'x';
break;
}
else
{
printf("該坐標已被占用,請重新輸入!\a\n\n");
}
}
else
{
printf("輸入坐標非法,請重新輸入!\a\n\n");
}
}
}
//電腦下棋函式
void ComputerMove(char Board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("computer:\n");
while (1)
{
//獲取時間亂數
x = rand() % row;
y = rand() % col;
if (Board[x][y] == ' ')
{
Board[x][y] = 'o';
break;
}
}
}
//判斷棋盤是否被填滿函式
int IsFull(char Board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for(i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (Board[i][j] == ' ')
return 0;
}
}
return 1;
}
//判斷是否勝利函式
char IsWin(char Board[ROW][COL], int row, int col)
{
int i = 0;
//判斷行
for (i = 0; i < row; i++)
{
if (Board[i][0] == Board[i][1]
&& Board[i][1] == Board[i][2]
&& Board[i][1] != ' ')
{
return Board[i][1];
}
}
//判斷列
for (i = 0; i < col; i++)
{
if (Board[0][i] == Board[1][i]
&& Board[1][i] == Board[2][i]
&& Board[1][i] != ' ')
{
return Board[1][i];
}
}
//判斷對角線"\"
if (Board[0][0] == Board[1][1]
&& Board[1][1] == Board[2][2]
&& Board[1][1] != ' ')
{
return Board[1][1];
}
//判斷對角線"/"
if (Board[0][2] == Board[1][1]
&& Board[1][1] == Board[2][0]
&& Board[1][1] != ' ')
{
return Board[1][1];
}
//檢查棋盤是否填滿
if (IsFull == 1)
{
//回傳平局
return 'q';
}
//回傳繼續
return 'c';
}
//游戲實作函式
void Game(char Board[ROW][COL], int row, int col)
{
InitChessBoard(Board, ROW, COL);
DisplayChessBoard(Board, ROW, COL);
while (1)
{
PlayerMove(Board, ROW, COL);
DisplayChessBoard(Board, ROW, COL);
if (IsWin(Board, ROW, COL) != 'c')
break;
ComputerMove(Board, ROW, COL);
DisplayChessBoard(Board, ROW, COL);
if (IsWin(Board, ROW, COL) != 'c')
break;
}
if (IsWin(Board, ROW, COL) == 'x')
printf("PLAYER WIN!\n\n");
else if (IsWin(Board, ROW, COL) == 'o')
printf("COMPUTER WIN!\n\n");
else
printf("平局!\n\n");
}
//主調函式
int main(void)
{
srand((unsigned int)time(NULL));
char Board[ROW][COL] = { 0 };
int input = 0;
do
{
menu();
printf("please enter:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("GAME START\n");
Game(Board, ROW, COL);
break;
case 0:
printf("GAME EXIT\n\a");
break;
default:
printf("ERROR!\n\a");
}
} while (input);
return 0;
}
五、代碼注意事項
- 程式中哪里需要使用回圈,哪里不需要使用回圈應仔細分清
- Game()函式中,每當玩家下棋或是電腦下棋都需要判斷是否勝利
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/355409.html
標籤:其他
下一篇:斗地主功能測驗實戰一_需求分析
