C语言实现三子棋游戏:模块化设计与核心逻辑详解
使用C语言开发三子棋游戏是理解模块化编程与二维数组应用的经典案例。本文将演示如何通过拆分头文件、实现文件和测试文件,完成从棋盘渲染到胜负判定的全套逻辑。
1. 项目结构与准备
为了保证代码的可读性与可维护性,建议将项目拆分为三个核心文件:test.c(负责主逻辑与菜单交互)、game.c(封装游戏核心行为)以及 game.h(存储宏定义与函数声明)。这种模块化设计使得各部分职责明确,便于后续修改参数或扩展功能。
2. 框架搭建与循环控制
游戏启动后应提供一个循环菜单,允许用户多次游玩直至主动退出。在 main 函数中,使用 do-while 结构结合输入判断来控制程序流程。
int main()
{
int input = 0;
do {
menu();
scanf("%d", &input);
switch (input) {
case 1: game(); break;
case 0: printf("退出游戏\n"); break;
default: printf("输入错误\n"); break;
}
} while (input);
return 0;
}
3. 棋盘数据管理与初始化
三子棋的棋盘本质上是一个二维字符数组。为了支持不同大小的棋盘,建议在头文件中定义行列常量:
#define ROW 3 #define COL 3
在实际游戏中,空白位置通常用空格字符表示。需要在 game.c 中实现一个遍历函数,将指定大小的数组全部填充为空格:
void InitBoard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; ++i)
for (int j = 0; j < col; ++j)
board[i][j] = ' ';
}4. 交互式棋盘渲染
原始的直接输出无法呈现美观的网格效果。为了实现行列分隔线,需要分别处理“数据行”和“分割行”,并使用内层循环动态添加管道符 | 以保持通用性:
void DisplayBoard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; ++i) {
// 打印单元格数据
for (int j = 0; j < col; ++j) {
printf(" %c ", board[i][j]);
if (j < col - 1) printf("|");
}
printf("\n");
// 打印行分隔线
if (i < row - 1) {
for (int j = 0; j < col; ++j) {
printf("---");
if (j < col - 1) printf("|");
}
printf("\n");
}
}
}
当行列数改变时(例如修改为10x10),上述代码依然能正确生成对应规模的网格视图:
5. 玩家操作与输入校验
玩家输入坐标后,程序需执行两步校验:首先检查坐标是否在合法范围内(1~3),其次检测该格子是否已被占用。若合法且空闲,则将对应数组元素更新为标识符号(如 '*'):
void player_move(char board[ROW][COL], int row, int col)
{
int x, y;
while (1) {
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) {
if (board[x-1][y-1] == ' ') {
board[x-1][y-1] = '*';
break;
}
printf("该坐标被占用,请重新输入\n");
} else {
printf("坐标非法,请重新输入\n");
}
}
}
6. 电脑 AI 与胜负判定
电脑逻辑: 简单模式下,利用 rand() 生成随机横纵坐标并尝试落子,直到找到空白格为止。
胜负判断: 创建一个返回值类型为字符型的判定函数。扫描所有行、列及对角线是否存在三连相同棋子。如果棋盘已满且无胜者则返回平局标志,否则继续。
char is_win(char board[ROW][COL], int row, int col) {
// ... 行、列、对角线检查 ...
// 若棋盘填满则返回 'Q' (Quiesce/Drawl)
// 否则返回 'C' (Continue)
}7. 最终游戏效果展示
经过完整串联后,可以体验以下三种典型的游戏结局场景:
game.h (头文件)
#pragma once #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 3 #define COL 3 void InitBoard(char board[ROW][COL], int row, int col); void DisplayBoard(char board[ROW][COL], int row, int col); void player_move(char board[ROW][COL], int row, int col); void computer_move(char board[ROW][COL], int row, int col); char is_win(char board[ROW][COL], int row, int col);
game.c (实现文件)
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void InitBoard(char board[ROW][COL], int row, int col){
for(int i=0;i<row;++i) for(int j=0;j<col;++j) board[i][j]=' ';}
void DisplayBoard(char board[ROW][COL], int row, int col){
for(int i=0;i<row;++i){
for(int j=0;j<col;++j){printf(" %c ",board[i][j]);if(j<col-1)printf("|");}printf("\n");
if(i<row-1){for(int j=0;j<col;++j){printf("---");if(j<col-1)printf("|");}printf("
");}}}
void player_move(char board[ROW][COL], int row, int col){
int x,y; while(1){
printf("请输入坐标:>");scanf("%d %d",&x,&y);
if(x>=1&&x<=row&&y>=1&&y<=col){
if(board[x-1][y-1]==' '){board[x-1][y-1]='*';break;}else printf("占用\n");}
else printf("非法\n");}}
void computer_move(char board[ROW][COL], int row, int col){
int x,y; while(1){x=rand()%row;y=rand()%col;if(board[x][y]==' '){board[x][y]='#';break;}}}
char is_win(char board[ROW][COL], int row, int col){
for(int 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(int 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];
// Check Draw/Continue logic...
return 'C';
}test.c (主控文件)
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void game(){
char ret='C'; char board[ROW][COL]={0};
InitBoard(board,ROW,COL); DisplayBoard(board,ROW,COL);
while(ret=='C'){
player_move(board,ROW,COL); DisplayBoard(board,ROW,COL);
ret=is_win(board,ROW,COL); if(ret!='C') break;
computer_move(board,ROW,COL); DisplayBoard(board,ROW,COL);
ret=is_win(board,ROW,COL); if(ret!='C') break;
}
if(ret=='*') printf("玩家赢\n"); else if(ret=='#') printf("电脑赢\n"); else printf("平局\n");
}
int main(){
srand((unsigned int)time(NULL));
// Loop Menu structure as defined earlier
}本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













