[c语言日寄]精英怪:三子棋(tic-tac-toe)3命慢通[附免费源码]

哈喽盆友们,今天带来《c语言》游戏中三子棋boss速通教程!我们的目标是一边编写博文,一边快速用c语言实现三子棋游戏。准备好瓜子,我们计时开始!

前期规划

在速通中,我们必须要有清晰的前期规划,我选用了一下框架

c 复制代码
int main() {

	//棋盘
	return 0;
}
//初始UI
//游玩显示模块
//用户操作模块
//胜利判定模块
//结算界面

初始UI

初始UI是最为简单的部分之一,我们可以在此快速输出,为接下来的算法腾出时间。

我们使用printf函数直接实现可视化UI,然后使用scanf读取用户的操作。

c 复制代码
	int num = 0;
	printf("-----------------------\n");
	printf("  欢迎来到三子棋游戏!\n");
	printf("   # 1.开始游戏\n");
	printf("   # 2.退出游戏\n");
	printf("-----------------------\n");
	printf("请输入操作序号:");
	scanf_s("%d", &num);

使用switch函数进行分流,并且添加上一个简单的输入检测:

c 复制代码
	again:
	int num = 0;
	printf("-----------------------\n");
	printf("  欢迎来到三子棋游戏!\n");
	printf("   # 1.开始游戏\n");
	printf("   # 2.退出游戏\n");
	printf("-----------------------\n");
	printf("请输入操作序号:");
	scanf_s("%d", &num);
	switch (num) {
	case 1:return 1;
	case 2:return -1;
	default:
		system("cls");
		printf("#无效的操作符输入\n");
		goto again;//通过goto实现快速构建循环。
	}

配合return,函数的声明为:int UI();

在主函数中通过if语句引用UI,并且实现退出选项。

UI函数到此为止。完整代码如下:

c 复制代码
#include<stdio.h>
#include<windows.h>

int UI();

int main() {
	
	//展示UI
	if (UI() == -1)return 0;
	//棋盘
	return 0;
}

//初始UI

int UI() {

	again:
	int num = 0;
	printf("-----------------------\n");
	printf("  欢迎来到三子棋游戏!\n");
	printf("   # 1.开始游戏\n");
	printf("   # 2.退出游戏\n");
	printf("-----------------------\n");
	printf("请输入操作序号:");
	scanf_s("%d", &num);
	switch (num) {
	case 1:return 1;
	case 2:return -1;
	default:
		system("cls");
		printf("#无效的操作符输入\n");
		goto again;
	}

}
//游玩显示模块
//用户操作模块
//胜利判定模块
//结算界面

具体的效果如下:

此时的时间为:

棋盘

清理了小兵之后,boss战才开始打响:

我们需要构建三子棋的棋盘。

为了方便判定,我将33的棋盘嵌入55的数组中。

c 复制代码
	//棋盘
	int chess[5][5];
	memset(chess, 0, sizeof(int) * 25);//棋盘初始化

通过string.h头文件中memset函数,我们完成了对棋盘的初始化。

游玩显示模块

此时,boss血条已经下降了四分之一,boss进入红温阶段。

我们需要建立一个函数输出游玩时的界面。

这是一个双人游戏,所以棋盘有3种状态:空白,X棋子,O棋子。

我用0代表空格,用1代表X棋子,用2代表O棋子。

建立print_under函数实现对单个格子的可视化:

c 复制代码
void print_under(int*arr ,int i, int j) {

	if (*(arr + i * 3 + j) == 0)printf("·\t");
	else if (*(arr + i * 3 + j) == 1)printf("X\t");
	else if (*(arr + i * 3 + j) == 2)printf("O\t");
	else printf("Error\t");
	return;
}

通过vision函数实现棋盘整体的输出:

c 复制代码
//游玩显示模块
void vision(int* arr) {

	system("cls");

	printf("-----------------------\n");
	for (int i = 1; i < 4; i++) {
		for (int j = 1; j < 4; j++) {
			print_under(arr,i, j);
		}
		printf("\n");
	}
	printf("-----------------------");

}

效果如下

不过,我在此时发现一个bug,就是在UI()函数中,goto语句将变量定义包涵进去了,这样会导致变量的重定义,这吓了我一身冷汗,急忙改了回来:

c 复制代码
//原式
int UI() {
	again:
	int num = 0;//原来的定义放在again标签前
	printf("-----------------------\n");
c 复制代码
//改后
int UI() {
	int num = 0;//转移到标签外面
	again:
	printf("-----------------------\n");

很好,此时我们成功完成了这个模块。

用时:

用户操作模块

boss血量剩下50%,boss进入第二阶段!!boss放大招了!我们必须挺过这里!

建立op()函数,引入user变量实现玩家1和玩家2的区分。

用scanf读取用户操作,并且设立输入检查:

c 复制代码
void op(int* arr, int user) {
	int i, j;
	again1:
	if (user % 2 == 0) {
		printf("玩家1:请输入落子位置");
		scanf_s("%d%d", &i, &j);
		if (i < 4 && i > 0)
			if (j < 4 && j > 0)
				if (*(arr + 3 * i + j) == 0)
					*(arr + 3 * i + j) = 1;
				else { printf("#无效的操作:你似乎下在了已经有棋子的地方哦\n");goto again1; }
			else { printf("#无效的操作:你似乎下到了界外诶\n");goto again1; }
		else { printf("#无效的操作:你似乎下到了界外诶\n");goto again1; }

	}
	if (user % 2 == 1) {
		printf("玩家2:请输入落子位置");
		scanf_s("%d%d", &i, &j);
		if (i < 4 && i > 0)
			if (j < 4 && j > 0)
				if (*(arr + 3 * i + j) == 0)
					*(arr + 3 * i + j) = 2;
				else { printf("#无效的操作:你似乎下在了已经有棋子的地方哦\n");goto again1; }
			else {printf("#无效的操作:你似乎下到了界外诶\n");goto again1; }
		else { printf("#无效的操作:你似乎下到了界外诶\n");goto again1; }
	}

}

此时,我还对游玩显示模块进行了优化

c 复制代码
void vision(int* arr) {

	system("cls");

	printf("----------------------------\n");
	printf("\t1\t2\t3\n");
	for (int i = 1; i < 4; i++) {
		printf("%d\t", i);
		for (int j = 1; j < 4; j++) {
			print_under(arr,i, j);
		}
		printf("\n");
	}
	printf("----------------------------\n");

}

此时的效果:

此时,我一共花费了以下时间:(显示问题:真实的时间为图示的时间加上1个小时)

胜利判定

此时boss血量见底,让我们来一段漂亮的斩杀把!

完成胜利判定模块:

c 复制代码
// 胜利判定模块
int victory(int* arr, int user) {
	int player = (user % 2 == 0) ? 1 : 2;

	// 横向判定
	for (int i = 1; i < 4; i++) {
		if (*(arr + i * 3 + 1) == player && *(arr + i * 3 + 2) == player && *(arr + i * 3 + 3) == player) {
			return player;
		}
	}

	// 纵向判定
	for (int j = 1; j < 4; j++) {
		if (*(arr + 1 * 3 + j) == player && *(arr + 2 * 3 + j) == player && *(arr + 3 * 3 + j) == player) {
			return player;
		}
	}

	// 左斜线判定
	if (*(arr + 1 * 3 + 1) == player && *(arr + 2 * 3 + 2) == player && *(arr + 3 * 3 + 3) == player) {
		return player;
	}

	// 右侧斜线判定
	if (*(arr + 1 * 3 + 3) == player && *(arr + 2 * 3 + 2) == player && *(arr + 3 * 3 + 1) == player) {
		return player;
	}

	return 0;
}

经历了痛苦的改bug,

我终于意识到,原来数组只要3*3就好了TAT,于是我默默的把标题的1命速通改为3命速通(悲)。

那么用时多久呢?

没错,两个半小时!(计时器忽略了小时计数)

一位破防的靓仔把标题的1命速通改为3命慢通......

嘿嘿

虽然速通失败,但是博主其实很有实力的!

关注博主,总有一天我会证明给你看(OvO)~

相关推荐
Zenova EdgeOS3 分钟前
Python 工业边缘 redis-py 异步实战
开发语言·redis·python
huang57914718 分钟前
哈希算法的抗碰撞机制与安全性增强策略4
算法
林浩杨_40 分钟前
SIGIR 2026|南京大学:Video-GAR:“通过生成 Query 来验证视频语义理解”的生成增强范式
论文阅读·人工智能·算法
君顾140 分钟前
西安 24 小时自助健身房系统开发实战指南
java·开发语言·健身房
白色的北极熊1 小时前
c语言 scanf 输入流有空格,逗号 说明
c语言
Logic1011 小时前
C语言/数据结构位运算题解:异或XOR找出货船中的“独特载货量“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
Elsa️7461 小时前
算法一周刷题总结
c++·算法
小羊没烦恼!1 小时前
Memory 记忆设计讨论:Agent Memory 的数据模型可以怎么设计
java·开发语言·前端·c++·c#
小小程序猴11 小时前
深圳乘路资讯AI培训怎么样?课程靠谱吗?——一套课程可信度评估模型与实证分析
人工智能·算法
云上先途2 小时前
标签化服务适合哪些人?常见适用场景一次讲清
大数据·人工智能·算法·音视频