C++制作五子棋

news2024/9/24 9:27:24

正文

01

思路

我没有选择专业的五子棋棋型,用我自己的逻辑(初高中玩五子棋的方法),去实现简单的人机对战。

首先因为要计算五子棋每一步的分数,那么你就要分析每一步形成的棋盘,以下图为例:

当你即将在红色方框区域内落子时,通过数据处理获取四个方向的棋子存储在数组里面,然后就是分析这个数组属于那种棋型。


以横向为例:

row相当于上图红色矩形区域的行坐标

col 相当于上图红色矩形区域的列坐标

player是这个位置即将落子的颜色,-1黑子    1 白子

int Game_score(int row, int col, int player)	//player = -1黑子	player = 1 白子
{

	char arr[4][9] = { 0 };	//存放四个方向的棋子
	int grade[4];			//存放四个方向的总分
	int begin = 0, end = 0;
	/*========左右========*/
	//从Map[row][col]处往左找四个棋子,遇到边界结束得到左边落子数量
	//从Map[row][col]处往右找四个棋子,遇到边界结束得到右边落子数量
	for (int index = 1; index <= 4; index++)
	{
		//往左找
		if (col - index >= 0)
		{
			begin = index;
		}
		//往右找
		if (col + index < 15)
		{
			end = index;
		}
	}
	for (int temp = 0, index = col - begin; index <= col + end; index++, temp++)
	{
		arr[0][temp] = Map[row][index];	//将Map[row][col]附近九个位置的棋子放入到arr里面分析
	}
	arr[0][begin] = player;			//将预测的落子位置由0置player
}

这个时候横向的棋子已经存储在arr这个数组的第一行这个时候只需要分析横向的棋型属于那种类型。

这里插句嘴,当时我处理完得到四个方向的棋型之后我觉得五子棋AI已经完成了一大半,然而在判断每个方向属于那种棋型的时候我慌了。

我觉得将所有棋型,也就是专业的连五,活四,冲四,活三,眠三,活二,眠二这些棋型枚举出来,然后和这个arr数组匹配就完事了。一枚举,十五种可能的棋型,还不是固定大小,下面是我当时枚举的情况

int g_score[15][6] = {
	/*连五*/
	{1,1,1,1,1},
	/*活四*/
	{0,1,1,1,1,0},
	/*冲四*/
	{0,1,1,1,1,-1},
	{1,0,1,1,1},
	{1,1,0,1,1},
	/*活三*/
	{0,1,1,1,0},
	{1,0,1,1},
	//{1,1,0,1},
	/*眠三*/
	{1,1,1,-1},
	{1,0,1,1,-1},
	{1,1,0,1,-1},
	{1,0,0,1,1},
	{1,0,1,0,1},
	/*活二*/
	{1,1},
	{1,0,1},
	{1,0,0,1},
};

先不管棋型的宽度有6有2,尝试匹配,一算算了近3s,时间复杂度太高了,而且还算错了,还是因为棋型宽度不一致,匹配起来很难,当时我还想要不然用C++里面的string类里面的find函数去匹配,后面忘记了还是咋,换成了最简单的方法,就是看下当前落子位置相连的棋子数量为多少。

int count = 1;	//统计连子数量
/*从Map[row][col]往左找,统计player棋子的数量*/
for (int i = 1; i <= begin; i++)
{
	if (arr[0][begin - i] == player)
	{
		count++;
	}
	elseif (arr[0][begin - i] == -player)
	{
		if (count < 5)	//当最左边有一个异类棋子时权重降低 例如 xoooo 和 ooo	权重一样	
			count--;
		break;
	}
	elsebreak;
}
/*从Map[row][col]往右找,统计player的数量*/
for (int i = 1; i <= end; i++)
{
	if (arr[0][begin + i] == player)
	{
		count++;
	}
	elseif (arr[0][begin + i] == -player)
	{
		if (count < 5)
			count--;
		break;
	}
	elsebreak;
}
grade[0] = CountScore(count);	//根据player棋子数量统计分数

在这里我将专业术语里面的冲四和活三的权重认为是等同的,所以当坐左边或最右边有异类棋子时权重减一。

本来就写的不是很好这个AI,所以一切从简。

02

评分

因为一切从简,所以评分规则也是异常的简单。

int CountScore(int num)
{
	if (num >= 5)	//五子
		return50000;
	if (num == 4)	//四子
		return4320;
	if (num == 3)	//三子
		return720;
	if (num == 2)	//二子
		return120;
	if (num == 1)	//一子
		return20;
	return0;
}

在分给出每一个方向的评分后我给出了一个综合得分,这个综合得分是分析四个方向给出最高分

/*给出综合得分*/
int max_score = 0;
for (int i = 0; i < 4; i++)
{
	if (max_score < grade[i])
	{
		max_score = grade[i];
	}
	elseif (max_score == grade[i])
	{
		max_score += grade[i];
	}
}

03

分析落子

分析黑棋落子点是在白棋下完之后,对每一个空白处评分。

//确保鼠标在棋盘区域
if (x >= 15 && x <= 465 && y >= 15 && y <= 465)
{
	//此处无子
	if (Map[(y - 30 + 15) / 30][(x - 30 + 15) / 30] == 0)
	{
		//下子,改变currentPos
		currentPos.X = (x - 30 + 15) / 30;
		currentPos.Y = (y - 30 + 15) / 30;
		//map赋值
		Map[currentPos.Y][currentPos.X] = 1;	//玩家白棋
		GameDraw();
		if (Game_Juge())
		{
			return;
		}
        }
}

白棋下完之后,计算黑棋落子可能得分和白棋下一步落子可能评分,也就是进攻和防守。

struct GRADE
{
	int m_x;
	int m_y;
	int m_score;
};
GRADE attack_grade[MAP_ROW][MAP_COL];	//攻击分数
GRADE define_grade[MAP_ROW][MAP_COL];	//防御分数
//计算得分
for (int row = 0; row < MAP_ROW; row++)
{
	for (int col = 0; col < MAP_COL; col++)
	{
		if (Map[row][col] == 0)
		{
			define_grade[row][col].m_x = attack_grade[row][col].m_x = col;
			define_grade[row][col].m_y = attack_grade[row][col].m_y = row;
			attack_grade[row][col].m_score = Game_score(row, col, -1);
			define_grade[row][col].m_score = Game_score(row, col, 1);
		}
		else
		{
			define_grade[row][col].m_x = attack_grade[row][col].m_x = col;
			define_grade[row][col].m_y = attack_grade[row][col].m_y = row;
			define_grade[row][col].m_score = attack_grade[row][col].m_score = 0;
		}
	}
}

给出评分后确定黑子的落子点,就是判断进攻还是防守

//计算黑白棋最佳落子点
for (int row = 0; row < MAP_ROW; row++)
{
	for (int col = 0; col < MAP_COL; col++)
	{
		if (MaxAttackScore.m_score < attack_grade[row][col].m_score)
		{
			MaxAttackScore.m_score = attack_grade[row][col].m_score;
			MaxAttackScore.m_x = attack_grade[row][col].m_x;
			MaxAttackScore.m_y = attack_grade[row][col].m_y;
		}
		if (MaxDefineScore.m_score < define_grade[row][col].m_score)
		{
			MaxDefineScore.m_score = define_grade[row][col].m_score;
			MaxDefineScore.m_x = define_grade[row][col].m_x;
			MaxDefineScore.m_y = define_grade[row][col].m_y;
		}
	}
}
//选择进攻	还是		防守一波(放手一搏)
if (MaxAttackScore.m_score >= MaxDefineScore.m_score)
{
	Map[MaxAttackScore.m_y][MaxAttackScore.m_x] = -1;
	currentPos.X = MaxAttackScore.m_x;
	currentPos.Y = MaxAttackScore.m_y;
}
elseif (MaxAttackScore.m_score < MaxDefineScore.m_score)
{
	Map[MaxDefineScore.m_y][MaxDefineScore.m_x] = -1;
	currentPos.X = MaxDefineScore.m_x;
	currentPos.Y = MaxDefineScore.m_y;
}
GameDraw();
//判断输赢
if (Game_Juge())
{
	return;
}

04

关于五子棋人机

这个AI只能说简单的实现了最基本的人机对战,很多方面因素我都没有考虑到,纯粹是自己看了几个AI实现的方法,再发挥下自己的想象力,七平八凑凑出来的,参考下我的思路即可,不要深究,毕竟失败是成功它妈。因为有些学校集训的时候会有五子棋AI的项目,我没有这个经历,考虑的方向或方法可能不对,我这就属于失败的产物,娱乐一下就好。如果以后有时间了我会改进下五子棋AI算法。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/696775.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝桥杯专题-试题版含答案-【风险度量】【括号配对问题】【ASCII码排序】【素数求和】

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

【Java高级编程】枚举类注解

枚举类&注解 1、枚举类的使用1.1、枚举类的使用1.2、如何定义枚举类1.3、Enum类的主要方法 2、注解的使用2.1、注解的概述2.2、常见的Annotation示例2.3、如何自定义注解&#xff1a;参照SuppressWarnings定义2.4、JDK提供的4种元注解2.5、JDK 8中注解的新特性&#xff1a;…

2023-06-25:redis中什么是缓存穿透?该如何解决?

2023-06-25&#xff1a;redis中什么是缓存穿透&#xff1f;该如何解决&#xff1f; 答案2023-06-25&#xff1a; 缓存穿透 缓存穿透指的是查询一个根本不存在的数据&#xff0c;在这种情况下&#xff0c;无论是缓存层还是存储层都无法命中。因此&#xff0c;每次请求都需要访…

关于C++图论树的某些题图形提示

一、去教室的路。 猫猫大学有n条路&#xff0c;每条路都有一个数字编号&#xff0c;其中的一条路一定与另外2条路相连&#xff0c;请你打出这个学校的地图。 输入1&#xff1a; 1 2 3 4 2 3 45 4 45 1 输出1&#xff1a; 1 2 3 4 5 45 图解 &#xff1…

动态住宅代理VS静态住宅代理,怎么选择?

现在&#xff0c;越来越多的海外代理服务商均支持动态住宅IP与静态住宅IP,很多小伙伴就疑惑&#xff0c;这二者有什么区别呢&#xff1f;哪个更好&#xff1f;其实&#xff0c;没有哪个更好&#xff0c;只有哪一个更合适您的业务。 无论动态住宅IP还是静态住宅IP都来自真实的住…

【软件测试】10道性能测试高频面试题,你能答上多少?

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、性能测试包含了…

表格el-table多出一条横线,怎么解决(el-table表格下方多一条线的问题)

最近在写el-table表格的时候&#xff0c;发现的问题&#xff0c;表格多出一条横线&#xff0c; 可以看出其它行&#xff0c;都是正常显示&#xff0c;只有第7行多出一条横线&#xff0c;找了好久&#xff0c; 最后发现是el-table表格的伪元素&#xff0c;问题就出在这&#xf…

B站化播放量为播放时长,是谁的狂欢?

6月26日晚&#xff0c;B站举办了14周年庆典晚会。在晚会上&#xff0c;除了周深、美依礼芽同框献唱受到关注&#xff0c;B站董事长兼CEO陈睿的演讲内容同样值得深思&#xff1a; 一来&#xff0c;陈睿提到&#xff0c;要将目前B站视频前台显示的播放量数据从次数改为分钟数&am…

精进ARM计算架构,催生人工智能产业的巨大跨越

在优化ARM计算架构以支持人工智能应用方面&#xff0c;以下是一些常见的方法和技术&#xff1a; 算法和模型设计优化&#xff1a;选择合适的算法和模型结构对于在ARM架构上高效执行人工智能任务至关重要。设计轻量级的模型、减少冗余操作和参数量&#xff0c;使用适合ARM架构的…

【K8S系列】深入解析K8S调度

序言 做一件事并不难&#xff0c;难的是在于坚持。坚持一下也不难&#xff0c;难的是坚持到底。 文章标记颜色说明&#xff1a; 黄色&#xff1a;重要标题红色&#xff1a;用来标记结论绿色&#xff1a;用来标记论点蓝色&#xff1a;用来标记论点 Kubernetes (k8s) 是一个容器编…

扩展ExtendedFloatingActionButton滚动收缩展开行为

效果 首先ExtendedFloatingActionButton有默认的Behavior : ExtendedFloatingActionButtonBehavior,这个类是为了ExtendedFloatingActionButton不被SnakBar所遮挡&#xff0c;并且这个类它是protected,所以为了保留原有的设计&#xff0c;自定义的Behavior不能在外部定义&#…

Go语言单元测试

1、Go语言单元测试 Go语言中的测试依赖 go test 命令&#xff0c;go test 命令是一个按照一定约定和组织的测试代码的驱动程序。在包目录 内&#xff0c;所有以 _test.go 为后缀名的源代码文件都是 go test 测试的一部分&#xff0c;不会被 go build 编译到最终的可执行 文件…

【Python爬虫】利用爬虫抓取双色球开奖号码,获取完整数据,简洁45行代码实现,更新时间2023-06-28

链接&#xff1a;https://pan.baidu.com/s/18oE308_NVNPaCOACw_H5Hw?pwdabc1 利用爬虫抓取双色球开奖号码&#xff0c;获取完整数据&#xff0c;简洁45行代码实现&#xff0c;更新时间2023-06-28 这是网上的数据&#xff0c;怎么将它爬取下来 它将只爬取最近30期的双色球开…

星辰秘典:解开Python项目的神秘面纱——迷宫之星(迷宫探索与求解)

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;html css js&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;你好&#x…

文件系统理解——磁盘文件

磁盘文件 1. 问题提出2. 了解磁盘的物理结构2.1 磁盘大体结构2.2 磁盘的具体物理结构 3.对磁盘结构逻辑抽象3.1 OS是通过CSH方法进行扇区的管理的吗&#xff1f;3.2 磁盘逻辑过程 4.文件系统4.1 管理思想4.2 区结构Boot BlockSuper BlockGroup Descriptor Tableinode Table &am…

共享办公室在国内外的发展史以及现状介绍

共享办公室&#xff0c;这个曾经陌生的概念&#xff0c;如今已成为全球范围内炙手可热的话题。在这个时代&#xff0c;越来越多的人开始关注灵活性和协作性&#xff0c;而共享办公室正是在这种需求下应运而生的。本文将带您一探共享办公室的国内外发展史、国内当前发展现状以及…

记录一次nginx占用cpu饱满解决

一天下午&#xff0c;突然就爆满了。刚开始服务器都登不上&#xff0c;后来服务器可以登录上&#xff0c;宝塔进不去&#xff0c;网站访问不了&#xff0c;top后发现nginx爆满 执行下列代码&#xff0c;停止nginx服务 systemctl stop nginx 虽然停止了 可以上宝塔 再次手动…

硬件工程师JD

不知道这么做合不合适&#xff0c;我先发一个试试&#xff0c;团队在招人&#xff0c; 岗位是 航天航空电子工程师1&#xff0c;混合电推和起发电方向&#xff1b; 电机控制硬件工程师1&#xff0c;新能源汽车电机控制器硬件开发方向。 工作内容&#xff1a; 1、负责硬件系…

美国首只杠杆比特币期货ETF开盘,成交量近550万美元!

纽约时间6月27日&#xff0c;美国首只杠杆比特币期货ETF&#xff08;股票代码&#xff1a;BITX&#xff09;在CBOE BZX交易所开盘&#xff0c;成交量近550万美元&#xff0c;成为今年推出的ETF中首日交易量最大的产品。 BITX的推出&#xff0c;正值贝莱德(BlackRock)向SEC递交现…

【教学类-36-04】Midjounery 各种图片切割(通用公式)

作品展示&#xff1a; 6*6切割36图 5*4图&#xff1a;20张 问题产生&#xff1a; 之前的代码是&#xff1a;一张图的四个坐标&#xff0c;有4张就要写4行。 后续发现&#xff0c;Midjounery生成的图片矩阵X Y数量不等&#xff0c;不仅有3*3&#xff0c;还有4*3、5*4的结构&am…