三子棋游戏实现:分支、循环、数组与函数结合
三子棋(Tic-Tac-Toe)是一款简单的二维棋盘游戏,玩家在一个3x3的棋盘上轮流放置棋子,通常由两个玩家进行。目标是让自己的棋子在横向、纵向或对角线上排列成一行,首先完成这一目标的玩家获胜。在实现过程中,结合了 分支、循环、数组 和 函数 这几大编程概念,使得整个实现更加结构化、清晰和易于扩展。
1. 游戏结构分析
三子棋游戏需要几个基本的元素:
- 棋盘:使用一个3x3的数组来表示。每个位置可以是空白(表示未占用)、玩家1的棋子(例如
X
)、玩家2的棋子(例如O
)。 - 玩家轮流:两个玩家轮流进行操作,直到某一方获胜或棋盘满员(平局)。
- 游戏胜利条件:某一玩家的棋子在横向、纵向或对角线上排列成一行时,该玩家获胜。
2. 核心功能实现
在C语言中实现三子棋游戏时,我们需要重点关注以下几个功能:
- 显示棋盘。
- 让玩家输入坐标放置棋子。
- 判断游戏是否结束,包括平局、胜利或继续。
2.1 定义棋盘及相关变量
首先,我们定义一个3x3的字符数组来表示棋盘,并用两个字符 'X'
和 'O'
来表示玩家1和玩家2的棋子。
#include <stdio.h>
char board[3][3]; // 3x3棋盘
int currentPlayer = 1; // 当前玩家,1代表玩家X,2代表玩家O
2.2 初始化棋盘
为了初始化棋盘,我们创建一个函数,用 '-'
表示棋盘上的空位置。
void initializeBoard() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = '-'; // 初始化为空
}
}
}
2.3 显示棋盘
为了让玩家看到棋盘的当前状态,我们需要一个函数来打印出棋盘。
void displayBoard() {
printf("\n");
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("\n");
}
2.4 玩家输入
我们需要一个函数来让玩家输入坐标,放置棋子。假设玩家输入的坐标从1开始(即1-3行,1-3列),我们将其转换为数组的索引。
int isValidMove(int row, int col) {
if (row < 0 || row >= 3 || col < 0 || col >= 3) {
return 0; // 无效的坐标
}
if (board[row][col] != '-') {
return 0; // 已经有棋子了
}
return 1; // 合法位置
}
void playerMove() {
int row, col;
printf("Player %d's turn (Enter row and column): ", currentPlayer);
while (1) {
scanf("%d %d", &row, &col);
row--; col--; // 调整为数组索引
if (isValidMove(row, col)) {
board[row][col] = (currentPlayer == 1) ? 'X' : 'O'; // 放置棋子
break;
} else {
printf("Invalid move! Try again: ");
}
}
}
2.5 判断胜利条件
我们需要一个函数判断是否有玩家获胜。判断的方法是检查每一行、每一列以及两条对角线。
int checkWin() {
// 检查行
for (int i = 0; i < 3; i++) {
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != '-') {
return 1; // 行胜利
}
}
// 检查列
for (int j = 0; j < 3; j++) {
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != '-') {
return 1; // 列胜利
}
}
// 检查对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != '-') {
return 1; // 对角线胜利
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != '-') {
return 1; // 对角线胜利
}
return 0; // 无胜利
}
2.6 判断平局
游戏在没有胜利的情况下,如果棋盘满了,可以判断为平局。
int checkDraw() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j] == '-') {
return 0; // 还有空位置,未平局
}
}
}
return 1; // 棋盘满,平局
}
2.7 切换玩家
为了在每回合切换玩家,可以使用一个简单的函数。
void switchPlayer() {
currentPlayer = (currentPlayer == 1) ? 2 : 1;
}
3. 游戏主循环
最后,我们需要一个主函数来启动游戏并进行循环。游戏会一直进行,直到有玩家获胜或平局。
int main() {
initializeBoard();
while (1) {
displayBoard();
playerMove();
if (checkWin()) {
displayBoard();
printf("Player %d wins!\n", currentPlayer);
break;
}
if (checkDraw()) {
displayBoard();
printf("It's a draw!\n");
break;
}
switchPlayer();
}
return 0;
}
4. 游戏运行流程
- 初始化棋盘:通过
initializeBoard()
创建一个空的3x3棋盘。 - 显示棋盘:每次回合结束后,通过
displayBoard()
显示当前棋盘状态。 - 玩家输入:玩家输入坐标放置自己的棋子,使用
playerMove()
获取玩家输入并检查合法性。 - 胜利判断:每轮操作后,通过
checkWin()
检查是否有玩家获胜。 - 平局判断:若棋盘已满且无人获胜,则通过
checkDraw()
判断平局。 - 切换玩家:每轮操作后,通过
switchPlayer()
切换玩家。
5. 总结
通过以上的实现,三子棋游戏的主要功能得以实现,包括棋盘初始化、玩家输入、胜利和平局判断,以及玩家之间的切换。利用 分支 控制程序流程,循环 进行多次玩家回合,数组 存储棋盘状态,函数 进行模块化管理,可以更好地组织和维护代码。