使用C语言实现三子棋小游戏:模块化编程与逻辑实战

花开有时
花开有时
发布时间:2026-10-16 | 2人浏览过
原创

本文将指导你如何通过模块化思想,在C语言中从零开始构建一个完整的三子棋(Tic-Tac-Toe)小游戏。内容涵盖项目结构设计、核心数据结构的处理、人机交互逻辑、AI随机决策算法以及复杂的胜负判断机制,并提供经过修正和优化的完整代码示例。

结果或目标

最终实现一个可以在终端运行的控制台程序。启动后显示菜单,选择开始后进入双人(人对电脑)对弈模式。棋盘为3x3网格,玩家输入坐标落子(' * '),电脑自动随机落子(' # ')。系统实时判断并宣布赢家或平局,支持重新开始或退出。

准备条件

  1. 开发环境:支持C99标准及以上的C编译器(如 GCC、Clang 或 MSVC)。
  2. 基础知识:掌握C语言基本语法、函数调用、指针/数组传参、预处理指令及控制流语句。
  3. 工具链:文本编辑器或IDE,终端命令行工具。

真实操作顺序

第1步:构建项目模块架构

目的:将游戏的入口、逻辑声明与具体实现分离,提高代码可读性与可维护性。

入口/动作:创建三个源文件:

  • main.c:包含主函数、菜单显示逻辑和游戏运行循环。
  • three_chess.h:包含常量定义(行列数)及所有函数的原型声明。
  • three_chess.c:包含初始化、棋盘显示、玩家移动、电脑移动及胜负判断的具体函数实现。

第2步:实现头文件与全局常量

目的:定义棋盘尺寸并暴露必要的接口。

代码实现(three_chess.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 PlayerMove(char board[ROW][COL], int row, int col);
void ComputerMove(char board[ROW][COL], int row, int col);
char IsGameOver(char board[ROW][COL], int row, int col);

第3步:实现主流程与菜单

目的:建立游戏的控制流,处理用户的选择分支。

代码实现(main.c):

#include "three_chess.h"

void menu()
{
	printf("##########################\n");
	printf("###    1. Play Game    ###\n");
	printf("###    0. Quit Game    ###\n");
	printf("##########################\n");
}

void game()
{
	int input = 0;
	srand((unsigned int)time(NULL)); // 初始化随机种子
	char board[ROW][COL] = {0};
	InitBoard(board, ROW, COL);       // 初始化棋盘

	while (1)
	{
		DisplayBoard(board, ROW, COL);      // 打印当前棋盘
		PlayerMove(board, ROW, COL);        // 玩家走一步

		char ret = IsGameOver(board, ROW, COL); // 检查是否结束
		if (ret != 'C') 
		{
			break; // C代表 Continue(继续),非C则结束
		}

		ComputerMove(board, ROW, COL);    // 电脑走一步
		ret = IsGameOver(board, ROW, COL); // 再次检查
		if (ret != 'C')
		{
			break;
		}
	}

	DisplayBoard(board, ROW, COL); // 打印最终状态
	if (ret == '*')
		printf("玩家赢!\n");
	else if (ret == '#')
		printf("电脑赢!\n");
	else
		printf("平局!\n");
}

int main()
{
	int input = 0;
	do {
		menu();
		printf("请选择: ");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏。\n");
			break;
		default:
			printf("输入无效,请重新选择。\n");
			break;
		}
	} while (input);
	return 0;
}

第4步:实现棋盘初始化与显示

目的:将内存中的字符数组转化为可视化的网格界面,初始化为空格 ' '。

代码实现(three_chess.c):

// 初始化棋盘为空格
void InitBoard(char board[ROW][COL], int row, int col)
{
	int i = 0, j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

// 可视化棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0, 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 < col; j++)
			{
				printf("--- ");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}

第5步:实现玩家移动(含输入校验)

目的:接收用户输入,确保坐标合法且在范围内,防止覆盖已存在的棋子。

关键逻辑:

  • 合法性检查:输入的 x 和 y 必须在 [1, ROW] 和 [1, COL] 之间。
  • 占用检查:将输入的行列转换为数组索引 [x-1][y-1],若该位置不为空格,则提示重试。

代码实现:

void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0, y = 0;
	while (1)
	{
		printf("请输入想要落子的坐标(x y): ");
		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("坐标非法,请输入 1-%d 范围内的数字。\n", row);
		}
	}
}

第6步:实现电脑随机移动

目的:模拟电脑落子,采用简单的随机算法寻找空位。

关键逻辑:

  • 使用 rand() % row 生成 [0, row) 范围内的随机行索引。
  • 使用 rand() % col 生成 [0, col) 范围内的随机列索引。
  • 利用 while 循环判断该随机位置是否为空,若非空则重新生成坐标,直到找到空位。

代码实现:

void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑正在思考...\n");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

第7步:实现胜负判断逻辑

目的:检测四种终局状态:玩家赢(*)、电脑赢(#)、平局(D)、继续(C)。

判断规则:

  1. 行相等:遍历每一行,若三个字符相同且不为空格,返回该字符。
  2. 列相等:遍历每一列,判断同上。
  3. 对角线相等:判断主对角线 (0,0)-(1,1)-(2,2) 和副对角线 (0,2)-(1,1)-(2,0)。
  4. 平局判定:若上述皆不满足,检查棋盘是否已满。若满且无胜者,返回 'D'。

代码实现:

// 辅助函数:判断棋盘是否填满
static int IsFull(char board[ROW][COL], int row, int col)
{
	for (int i = 0; i < row; i++)
		for (int j = 0; j < col; j++)
			if (board[i][j] == ' ')
				return 0; // 有空位,未填满
	return 1; // 全满
}

char IsGameOver(char board[ROW][COL], int row, int col)
{
	int i = 0, j = 0;

	// 1. 判断行
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
			return board[i][0];
	}

	// 2. 判断列
	for (j = 0; j < col; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')
			return board[0][j];
	}

	// 3. 判断对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
		return board[0][0];
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
		return board[0][2];

	// 4. 判断平局
	if (IsFull(board, row, col))
		return 'D';

	// 5. 继续
	return 'C';
}

完成判断

编译全部文件后运行 ./game(或对应平台的可执行文件)。观察控制台输出的棋盘格式是否正确,验证输入非法坐标时的提示信息,以及测试电脑是否能正确避开已占用的格子。当出现三连珠时,确认胜负判定无误。

简要总结

本示例展示了C语言在数据结构处理和逻辑控制方面的基础应用。通过将问题拆解为初始化、交互、计算和输出四个模块,降低了编码复杂度。实际开发中,电脑落子算法可以升级为极小化极大算法(Minimax)以提升AI水平,但当前的随机策略足以演示基本的程序架构。以上就是C语言实现三子棋小游戏的详细内容,更多关于C语言入门游戏开发的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表