IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【手把手带你搞定】C语言实现三子棋游戏,让你的代码有趣起来(超详细教程,从思路到代码,快码起来!) -> 正文阅读

[C++知识库]【手把手带你搞定】C语言实现三子棋游戏,让你的代码有趣起来(超详细教程,从思路到代码,快码起来!)


在学习完函数和数组的基本使用之后,我们应该把所学知识应用起来。其中,让我们的代码生动有趣起来的方法就是用它来写一个小游戏啦!

今天我们就来写一个简易的三子棋游戏吧!

在这里插入图片描述

什么是三子棋游戏

首先,我们还是简单地介绍一下简单的三子棋(tic-tac-toe)游戏吧~
在这里插入图片描述
一开始听到三子棋这个名字的时候,我还有些懵……三子棋是啥玩意儿?我只听说过五子棋啊……

后来才知道,原来是三子棋就是我小时候经常和小伙伴画着玩的井字棋,可能你光听名字也不知道这是啥,但是我猜你看到图片就明白了。上图!

当当当当~

在这里插入图片描述
敢问这是不是90后小伙伴们的童年回忆???(暴露年龄了!!!)

哈哈哈哈哈相信看完上图大家应该就都明白三子棋是怎么玩的了吧~那我们接下来就进入正题:C语言实现三子棋游戏。

分析

程序员虽然是敲代码的,但是代码前的分析尤为重要噢~

我们需要先分析一下整个游戏的逻辑以及实现的方式,才能更加顺利的写出好的代码噢!

首先,我们在VS2019中建立一个新的解决方案。
为了使我们的代码更加有序整洁,这里我们创建一个test.c文件用于测试整个游戏程序的执行,再创建一个game.c文件用于存放实现三子棋游戏所需要调用的函数,相应地创建一个game.h头文件。

首先,像我们之前写过的猜数字游戏(点击此处可跳转)一样,我们要先给出一个菜单,让用户进行选择(玩或者不玩),并且用户玩完之后可以再次进行选择。

然后,我们要开始实现三子棋游戏。

那么具体如何实现呢?

我们先看看下图:
在这里插入图片描述
想象一下,从前我们和小伙伴玩三子棋游戏的时候,是不是得先有纸和笔画出一个井字格来,然后再开始下棋。

下棋又分为玩家下棋和**电脑下棋 **,玩家的棋子为“*”,电脑的棋子为“#”,并且我们需要把下棋的数据记录下来,确保落了子的地方不会再被落子。

最后每落一子我们都要对结果进行判断

而每一次判断可能出现的结果有4种:玩家赢、电脑赢、平局和游戏继续。如果游戏继续,则继续下棋,否则,输出游戏结果,返回到游戏菜单。

以上就是三子棋的整个游戏实现逻辑,我们将其中的重点总结如下:

  1. 菜单
  2. 打印井字格
  3. 下棋
  4. 判断结果

代码实现

菜单

菜单是实现和之前的猜数字游戏一样,这里就直接给出代码了,如果有想要了解这一部分的代码是如何写的,可点击此处跳转到猜数字游戏的文章中了解。

#include <stdio.h>

void menu()
{
	printf("**********************\n");
	printf("******* 1.play *******\n");
	printf("******* 0.exit *******\n");
	printf("**********************\n");
}

int main()
{
	int input = 0;
	do
	{
		menu();//打印菜单
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)//根据intput的值做出响应
		{
		case 1:
			printf("开始游戏\n");
			//进入三子棋的游戏
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

程序运行如下:
在这里插入图片描述

打印井字格

创建二维棋盘数组

由于我们的棋盘是一个九宫格,并且在这个九宫格中还会存放游戏中下棋的数据(哪个位置放玩家的棋子,哪个位置放电脑的棋子)。

所以,这里我们应该创建一个3×3的二维数组

由于玩家和电脑的棋子是用“*”和“#”来表示的,所以我们创建一个字符类型的数组。
在这里插入图片描述
由于后面下棋时也会反复用到这个二维数组,在每次传参时我们都会将数组的行和列作为参数传给函数。

因此,我们不妨在头文件中将行和列分别定义为一个常量,这样代码的可读性将会更高,并且以后如果要对行和列进行更改,就可以直接在头文件中对相应的值进行更改。
在这里插入图片描述

在这里插入图片描述

初始化棋盘数组

接下来我们要对棋盘数组进行初始化。

在最开始没有下棋的时候,我们看到的数组内容是空的,所以我们可以认为初始化棋盘的时候,我们在里面放的是一空格,等到玩家或者电脑下棋的时候,再将其中的值覆盖为“*”或者“#”。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

打印棋盘

在将数组初始化之后,我们就要打印棋盘了。

首先我们先把打印棋盘函数的调用写出来,并将参数陈传进去:
在这里插入图片描述
然后再头文件中对打印棋盘函数进行声明:
在这里插入图片描述

最后完成打印棋盘的函数实现:
我们要打印的应该是下面这个棋盘。
在这里插入图片描述
我们可以将上面的井字格分割成三大行,一个大行包含一个数据行和一个分割行,每行有三列。
在这里插入图片描述
根据以上的拆解,我们就可以写出打印棋盘的代码了。

void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		//打印数据行
		int j = 0;
		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");
		}
	}
}

运行程序,可以看到棋盘被很好地打印出来了。
在这里插入图片描述

下棋

打印完棋盘之后,我们就要开始下棋了,这里的下棋分为玩家下棋和电脑下棋。分别封装为两个函数。

下棋的实现其实就是在棋盘的对应位置中放入代表玩家的的棋子的字符“*”或者代表电脑的棋子的“#”。所以我们还是要将数组的地址以及数组的行和列传参给函数。

但是下棋不是只下一次,如果双方都下完一步棋,米有分出胜负,则要继续走下一步,所以这里我们应该把下棋这一部分的代码放在一个循环里面。
在这里插入图片描述
同时我们也在game.h文件中对这两个函数进行声明。
在这里插入图片描述

玩家下棋

在玩家下棋的函数中,我们要实现的关键有以下几点:

  1. 我们要打印提示提醒玩家下棋(输入坐标)
  2. 判断玩家输入的坐标是否可用,如果不可用则需要重新输入,因此需要将坐标的输入放在一个循环中。
  3. 坐标分为三种:非法坐标(不在棋盘范围内)、已被占用的坐标、可以下棋的坐标。
  4. 在正确的坐标上下棋:放入“*”,此时跳出循环

玩家下棋的函数代码如下:

void PlayerMove(char board[ROW][COL], int row, int col)
{
	printf("玩家走\n");
	int x = 0;
	int y = 0;
	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");
		}
	}
}

注意玩家下完棋之后,要让玩家下的棋被看到,所以我们要打印一下棋盘,同理电脑电脑下棋之后也要打印棋盘。
在这里插入图片描述
这是运行程序,分别输入几组下标,结果如下:
在这里插入图片描述

电脑下棋

那么电脑下棋应该怎么实现呢?

首先,应该生成一个坐标。

而电脑生成的坐标应该是随机的,所以这里我们要先生成随机值。

关于随机值的生成,可参考我之前的博客:【手把手带你搞定】第一个C语言猜数字游戏(超详细教程,不仅学如何写代码,更学方法思路!)

在这里插入图片描述
在这里插入图片描述
然后再让行(或列)的坐标等于生成的随机数%行数(或者列数),就可以生成一个合法的随机坐标。
在这里插入图片描述
生成坐标之后,我们要判断坐标所指向的位置是否已经被占用:

如果没被占用,则在该位置中放入“#”。
如果已经占用,则要重新生成随机坐标,直到得到一个未被占用的位置。

因此,生成随机坐标的代码块也需要放到一个循环中。

电脑下棋的函数代码如下:

void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑走\n");
	while (1)
	{   //生成随机坐标
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')//判断坐标是否被占用
		{
			board[x][y] = '#';
			break;
		}
	}
}

运行代码:
在这里插入图片描述
在这里插入图片描述

判断结果

每次下完棋,我们都应该对棋局的结果进行判断。

而棋局的结果分为四种:玩家赢、电脑赢、平局和继续。其中若得到前三种结果,游戏结束,否则游戏继续。

我们可以写一个返回类型为char的函数,如果函数返回“*”,则代表玩家赢了,如果返回“#”则说明电脑赢了,如果返回“q”则是平局,返回“c”则继续下棋。

在这里插入图片描述
当然,在封装 IsWin( ) 函数时,别忘了对其进行声明噢。
在这里插入图片描述
首先判断输赢。判断输赢又分为三种情况:分别判断横、竖、对角线方向上相邻三个元素是否均相同且不等于空格。

如果有三个相邻元素相同,说明赢家已经产生了。我们只需要把相同的元素(字符)返回去,便可轻松得到对应的赢家

如果没有赢家产生,说明只剩下平局和继续两种情况,我们可以通过调用一个 IsFull( ) 函数来判断棋盘是否已经放满。

这里就直接上代码了:

int IsFull(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)//遍历数组
		{
			if (board[i][j] == ' ')
				return 0;//棋盘不满
		}
	}
	return 1;
}


char IsWin(char board[ROW][COL], int row, int col)
{
	//1.判断输赢
	//行
	int i = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] != ' ')//三个元素均相同且不等于空格
			return board[i][0];
	}
	//列
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] != ' ')
			return board[0][i];
	}
	//对角线
	if (board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] != ' ')
		return board[0][0];
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
		return board[1][1] != ' ';

	//2.判断平局
	if (IsFull(board, row, col))//调用一个IsFull函数
		return 'q';
		//3.游戏继续
		return 'c';
}

下面让代码跑起来看看~~(只截最后一部分啦!)
在这里插入图片描述

完整代码

走到这里,三子棋游戏的代码咱们就写完啦~
在这里插入图片描述

你学会了吗?

如果你觉得本文对你有用,记得点赞收藏加关注噢~

下面我把完整的代码截图一份放这里,并且在gitee中上传三子棋的完整代码,欢迎大家自取~

game.h文件:
在这里插入图片描述
game.c文件:
在这里插入图片描述
test.c文件:
在这里插入图片描述

总结

这是我们入门C语言之后写出的第一个比较长的程序。通过对三子棋游戏的实现,我们对于这两块内容的理解应该更加深刻。

下面给出几点总结:

  1. 在写游戏代码时,我们先思考整个游戏程序的大致流程和逻辑,然后再进行代码的编写。先分析,后代码,整个过程应该是十分流畅并且逻辑清晰的。

  2. 在函数设计上,我们一般先根据我们的需要把函数的调用写出来,然后再来完成函数内部的代码。

  3. 写完一个关键步骤之后,测试(运行)一下代码,保证每一步代码都是按照我们的思路执行的,这样后面如果出错了也更好找问题。

在这里插入图片描述
关注我~学写更多有趣的C语言程序!

在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-24 15:22:34  更:2021-08-24 15:24:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 6:57:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计