【C语言】三子棋详解(包教包会的那种)

news2024/12/24 2:12:42

在这里插入图片描述

君兮_的个人主页

勤时当勉励 岁月不待人

C/C++ 游戏开发


三子棋及五子棋详解

  • 前言
  • 三子棋的实现
    • 1. 打印菜单
    • 2.初始化并打印棋盘
      • 棋盘初始化函数功能的实现
      • 打印棋盘
    • 3.玩家下棋与模拟电脑下棋
      • 玩家下棋
      • 电脑下棋
        • 随机数的生成
    • 4.判断输赢
    • 我们的game函数
  • 源码
    • game.h
    • game.c
    • test.c
  • 总结

前言

当我们有一定的C语言基础后,就可以独立的设计一些小项目了,今天我来带大家一步一步实现三子棋这个简单的项目并把它改进为五子棋。跟着我一步一步来,我相信到最后你也能独立的编出属于自己的三子棋。话不多说,我们开始吧!

三子棋的实现

  • 三子棋虽然是一个小项目,但是整个过程中还是分不同的模块来实现不同的功能的,接下来我通过画图的方式讲一下具体由哪些模块并带大家一块一块的具体分析实现。
    在这里插入图片描述
  • 所有代码分三部分实现,它们分别是负责声明函数的头文件“game.h”,负责函数功能实现的“game.c”,以及负责测试(即用户使用)的“test.c”.

这里为什么要分几部分封装函数我在下面这篇博客中的自定义函数中提到过,感兴趣可以去看看,这里是链接:【C语言初阶】万字解析,带你0基础快速入门C语言(下)

1. 打印菜单

  • 这一步其实是非常简单的,代码如下
void menu()//打印菜单
{
	printf("*****************************\n");
	printf("*********** 1.play **********\n");
	printf("*********** 0.exit **********\n");
	printf("*****************************\n");

}

  • 好了,一个简单的菜单就写好了,但是此时的1和0是没有任何的选择效果的,我们接下来就让我们的菜单真正能做到输入1开始输入0结束的效果。
int main()
{
	srand((unsigned int)time(NULL));//暂时先不管,后面会讲这是什么
	int input = 0;
	
	do {
		
		menu();
		printf("请选择:> ");
		scanf("%d",&input);
		switch (input)
		{
		case 1:
			game();	//进入游戏	
			break;
		case 0:
			printf("退出游戏\n");
			break;
			
		default:
			printf("输入错误,请重新输入\n");//输入的非0非1时
			break;
		}
	}while(input);


	return 0;
}
  • 来测试一下我们这个菜单的效果

在这里插入图片描述

  • 非常完美,菜单算是打印完成了,我们进行下一步。

2.初始化并打印棋盘

  • 现在我们输入1进入游戏,首先要进行的就是对棋盘的初始化以及打印
  • 我们不妨把黑子白子设为’*‘与’#',由于我们的棋盘是分行与列的,要想打印一个棋盘把我们的”棋子“放进去,使用二维数组再合适不过。
  • 代码如下
void game()
{
	char board[Row][Col] = { 0 };
	InitBoard(board, Row, Col);//初始化棋盘的函数
	PrintBoard(board,Row, Col);//打印棋盘的函数

}
  • 此时有人肯定好奇Row和Col是什么
  • 为了方便我们以后改变棋盘的大小,我们用常数定义了Row和Col
#define Col 3
#define Row 3
  • 这样在我们以后想改变这个棋盘的大小时只需要改变定义的Col与Row的值就好,不需要把程序中每个有关棋盘大小的代码都修改一遍,是不是非常方便?
  • 我们继续
    当我们把二维数组以及对应的参数设计并放进函数里后,我们就要来实现具体函数的功能了,先讲讲初始化函数的实现。

棋盘初始化函数功能的实现

凡是函数我们在调用时都得先声明再使用,因此我们现在头文件中先声明一下。

void InitBoard(char board[Row][Col], int row, int col);//初始化棋盘

具体实现:

void InitBoard(char board[Row][Col], int row, int col)//把二维数组传进来同时把行数与列数也传进来
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j =0; j < col; j++)
		{
			board[i][j] = ' ';//把棋盘上的每一个元素都初始化为空格,方便我们落子

		}
	}
}
  • 其实没啥好讲的,无非是两个for循环嵌套,看看以上代码后的注释相信聪明的你理解应该没啥问题。

打印棋盘

  • 把棋盘初始化好后,我们就要开始尝试确定棋盘的格式来打印棋盘了,首先还是得在头文件中声明函数。
void PrintBoard(char board[Row][Col], int row, int col);//打印棋盘

代码的实现

void PrintBoard(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)
		{
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");//区分每一列的元素,在每个棋子下打印“---”
				if (j < col - 1)
					printf("|");
			}
			printf("\n");//一行打完换下一行
		}
	}
}

  • 这里讲一下为啥有时候i和j的范围是(row-1)和(col-1)

  • 其实非常简单啊,主要是为了美观。比如咱们打印一个3*3的棋盘,实际上只需要两行以及两列的分隔线就够了,再更加直接一点,如果我们想把一条线分割成三部分,是不是只需要切两次就足够了?

  • 可能上面这段画有点抽象,咱们配合下面实际打印出的棋盘的图来想象一下。
    在这里插入图片描述

  • 配合图看是不是就直观多了?

  • 如果觉得ok的话,那我们接下来来实现下棋的这部分代码


3.玩家下棋与模拟电脑下棋

  • 啊,我相信咱们程序猿的水平可能战胜阿尔法狗有点困难,但是与电脑随机落子下棋肯定绰绰有余,甚至咱们得让着它才能让它赢
  • 接下来我们讲讲我们该怎么下

玩家下棋

  • 同上,引用函数得先声明
void PlayBoard(char board[Row][Col], int row, int col);//玩家落子
  • 那么我们现在想想,我们该怎么下呢?
    - 首先咱们得先判断一下咱们下棋是否合法,总不能下着下着下到棋盘外了吧??
  • 其次,我们得判断一下我们现在选择的这个坐标是否有棋子,一个坐标下无法存放两个棋子的
    代码实现一下:
void PlayBoard(char board[Row][Col], int row, int col)
{
	int x, y = 0;
	while (1)
	{
	   //先提示一下此时轮到玩家了以及此时玩家应该做什么,
		printf("玩家下棋>:\n");
		printf("请输入要下的坐标,中间用空格隔开\n");
		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");//选择的坐标不在我们规定的棋盘内

	}

}
  • 注意:
  • 在判断该位置是否有“棋子”时,我们使用的是board[x - 1][y - 1].。
  • 程序和我们程序猿当然知道咱们的数组下标是从0开始的呀,但是,如果是一个没接触过编程的人来玩这个游戏时,ta会想当然的认为棋盘的坐标是从1开始的,比如第一行第一列的坐标,我们知道是(0,0),可ta想的却是(1,1),为了方便这些用户游玩我们的三子棋,我们最好就把每个位置的坐标设置成从1开始。这就是上面判断是否有“棋子”以及落子时使用board[x - 1][y - 1]的原因。

电脑下棋

  • 我们自己与自己玩自然无趣,此时不妨让电脑陪我们下棋。
  • 其实电脑下棋与我们玩家下棋类似,但是我们首先要解决一个问题,怎么让它随机的落子呢?
  • 为了让电脑能随机的下棋,我们得保证它每一次落子的坐标都变化,那有没有什么东西是一直在变化能被我们使用实现生成随机落子坐标的呢?
  • 此时我们想到,有一个东西正无时无刻不在发生变化,那就是时间,恰好符合我们的要求。
  • 接下来先讲讲怎么通过时间戳生成随机数。

随机数的生成

  • 什么是时间戳?
  • 时间戳是计算机科学中常见的术语,是指一种记录时间的方式,通常用于记录某个事件的发生时间或者文件的创建、修改时间等信息。简单的说,时间戳就是一串数字,表示从某个固定时间点(1970年1月1日00:00:00)开始到现在的时间长度,通常以秒为单位计算。
  • 生成随机数的函数
#include<stolib>//使用该函数所需的头文件
rand()
  • 我们通过msdn来认识一下它

在这里插入图片描述

  • rand的返回值为一个整型,注意最后一句话哦:

在这里插入图片描述

  • 博主只会用,英语能力有限,这里征用一下百度翻译
    在这里插入图片描述
  • 也就是说,在使用rand之前,我们得先调用一下srand为其设定生成随机数的起点(或者生成器)”
  • srand函数msdn定义如下:
    在这里插入图片描述
  • 当我们调用srand函数时,必须满足的条件是传给它的值是一个变化的值,此时就可以用我们前面讲到的时间戳了
#include<time.h>//使用time函数所需头文件
srand((unsigned int)time(NULL));//把时间置空传给srand同时由于srand要求参数必须为unsigned int型,把time(NULL)强制类型转换一下
  • 注意,rand生成的其实是一个伪随机数。

  • 好了,到此我们就可以开始尝试实现电脑下棋了
  • 先在头文件中声明函数
void ComputerBoard(char board[Row][Col], int row, int col);//电脑下棋

具体代码如下:

void ComputerBoard(char board[Row][Col], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋:>\n");//提示此时轮到电脑下
	while(1)
	{
		x = rand() % row;//为了防止落子到棋盘外,使生成的随机数范围为0到row-1
		y = rand() % col;//同理,生成0到col-1的数
		
		if (board[x][y] == ' ')//判断此时该坐标是否被占用
		{
			board[x][y] = '#';//落子
			break;
		}

	}
  • 除了上面随机数的生成,其他都与玩家下棋类似,这里不做缀叙了。

4.判断输赢

  • 这里我们离实现三子棋就差一步了,那就是判断输赢。
  • 这里我们把具体的情况总结一下
  • 1)玩家下的棋存在连续三个横着或竖着或者两条对角线,此时玩家胜
  • 2)同理,上面也是电脑的获胜条件。
  • 3)当我们把棋盘所有格子(坐标)都占满了,此时还没有出现上面两种情况,说明此时平局。
    首先还是先在头文件里声明函数
int IsFull(char board[Row][Col], int row, int col);//棋盘是否已满
int Is_Win(char board[Row][Col], int row, int col);//判断谁赢

具体代码:

int IsFull(char board[Row][Col], int row, int col)//判断棋盘是否已满
{
	int i ,j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')//还有空格,说明没满
				return 0;
		}
	}
	return 1;//没有空格了,说明已满,返回1
}


int Is_Win(char board[Row][Col], int row, int col)
{
	int x = 0;
	int y = 0;
	//竖着
	if (board[x][0] == board[x][1] && board[x][1] == board[x][2] && board[x][0] !=' ')
	{
		return board[x][0];//返回三个坐标中随意哪个都行,因为如果满足上面获胜条件,三个坐标中一定放着‘*’或者‘#’,下面的判断同理
	}
	//横着
	if (board[0][y] == board[1][y] && board[1][y] == board[2][y] && board[0][y] != ' ')
	{
		return board[0][y];
	}
	//两条对角线
	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];

	if (IsFull(board, row, col) == 1)//返回值如果为1说明棋盘满了
	{
		return 'Q';
	}
	return 'C';

}
  • 注意:
  • 上面这段代码中,如果玩家赢了,就返回‘*’
  • 如果电脑赢了,就返回‘#’
  • 如果平局,返回‘Q’
  • 如果上面三种情况都没发生,说明还没分出胜负,返回‘C’

我们的game函数

当我们把上面要实现的功能都封装在一个函数中,就能实现我们的三子棋游戏啦,此时我们来讲讲game函数中上述函数是怎样组合放置的。

  • 由于这里的game在主程序所在文件中,不需要声明
void game()
{
	char board[Row][Col] = { 0 };
	InitBoard(board, Row, Col);
	PrintBoard(board,Row, Col);
	char ret = 0;
	while (1)
	{
		PlayBoard(board, Row, Col);//玩家下棋
		PrintBoard(board, Row, Col);//打印此时的棋盘
		ret = Is_Win(board, Row, Col);//把返回值存放在ret里
		if (ret != 'C')//判断是否分出胜负,返回‘C’才说明需要继续
		break; 
		
		ComputerBoard(board, Row, Col);//电脑下棋
		PrintBoard(board, Row, Col);//打印此时的棋盘
		ret = Is_Win(board, Row, Col);//与上面同理
		if (ret != 'C')
		break;
	}
	if (ret == '*')
		printf("玩家赢\n");
	if (ret == '#')
		printf("电脑赢\n");
	if (ret == 'Q')
		printf("平局\n");
}
  • 这样我们的三子棋项目就完成了,我们来具体玩一下吧

在这里插入图片描述这里博主提醒大家:

游戏虽好,可不要贪玩哦!!!

在这里插入图片描述


源码

以下为三子棋具体的每个文件中的源码哦,需要自取

game.h

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define Col 3
#define Row 3
void InitBoard(char board[Row][Col], int row, int col);//初始化棋盘
void PrintBoard(char board[Row][Col], int row, int col);//打印棋盘
void PlayBoard(char board[Row][Col], int row, int col);//玩游戏
void ComputerBoard(char board[Row][Col], int row, int col);//电脑下
int IsFull(char board[Row][Col], int row, int col);//棋盘是否已满
int Is_Win(char board[Row][Col], int row, int col);//判断谁赢

game.c

#include"game.h"
void InitBoard(char board[Row][Col], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j =0; j < col; j++)
		{
			board[i][j] = ' ';

		}
	}
}


void PrintBoard(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)
		{
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}

void PlayBoard(char board[Row][Col], int row, int col)
{
	int x, y = 0;
	while (1)
	{
		printf("玩家下棋>:\n");
		printf("请输入要下的坐标,中间用空格隔开\n");
		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 ComputerBoard(char board[Row][Col], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋:>\n");
	while(1)
	{
		x = rand() % row;//生成0-row-1的数
		y = rand() % col;//生成0-col-1的数
		
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}

	}



}
int IsFull(char board[Row][Col], int row, int col)
{
	int i ,j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}


int Is_Win(char board[Row][Col], int row, int col)
{
	int x = 0;
	int y = 0;
	//竖着
	if (board[x][0] == board[x][1] && board[x][1] == board[x][2] && board[x][0] !=' ')
	{
		return board[x][0];
	}
	//横着
	if (board[0][y] == board[1][y] && board[1][y] == board[2][y] && board[0][y] != ' ')
	{
		return board[0][y];
	}
	//对角线
	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];

	if (IsFull(board, row, col) == 1)
	{
		return 'Q';
	}
	return 'C';

}

test.c

#include"game.h"
void menu()//打印菜单
{
	printf("*****************************\n");
	printf("*********** 1.play **********\n");
	printf("*********** 0.exit **********\n");
	printf("*****************************\n");

}

void game()
{
	char board[Row][Col] = { 0 };
	InitBoard(board, Row, Col);
	PrintBoard(board,Row, Col);
	char ret = 0;
	while (1)
	{
		PlayBoard(board, Row, Col);
		PrintBoard(board, Row, Col);
		ret = Is_Win(board, Row, Col);
		if (ret != 'C')
		break; 
		
		ComputerBoard(board, Row, Col);
		PrintBoard(board, Row, Col);
		ret = Is_Win(board, Row, Col);
		if (ret != 'C')
		break;
	}
	if (ret == '*')
		printf("玩家赢\n");
	if (ret == '#')
		printf("电脑赢\n");
	if (ret == 'Q')
		printf("平局\n");
}
int main()
{
	srand((unsigned int)time(NULL));
	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;
}

总结

以上就是今天的所有内容啦,希望你在看完后不要光看不练,只有自己亲手敲过之后,才能知道自己到底会不会,眼高手低是万万不可的哦!!

  • 如果你有任何疑问欢迎在评论区指出或者私信我哦!
  • 创作不易,如果感觉文章内容对你有所帮助的话,留下三连再走呗!你们的支持就是我创作的动力,下次再见啦!!!
    -在这里插入图片描述

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

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

相关文章

PMP课堂模拟题目及解析(第18期)

171. 一个项目已经结束&#xff0c;然而&#xff0c;项目经理和项目团队成员仍然被要求解决技术问题&#xff0c;进行一些变更&#xff0c;并评估新的需求。若要保证项目开发的产品或服务现在具有运营支持&#xff0c;项目经理应该执行下列哪些工作&#xff1f; &#xff08;选…

Nacos配置中心交互模型是push还是pull?

对于Nacos大家应该都不太陌生&#xff0c;出身阿里名声在外&#xff0c;能做动态服务发现、配置管理&#xff0c;非常好用的一个工具。然而这样的技术用的人越多面试被问的概率也就越大&#xff0c;如果只停留在使用层面&#xff0c;那面试可能要吃大亏。 比如我们今天要讨论的…

44从零开始学Java之详解容易让初学者懵圈的abstract抽象类、抽象方法

作者&#xff1a;孙玉昌&#xff0c;昵称【一一哥】&#xff0c;另外【壹壹哥】也是我哦 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 经过前面几篇文章的讲解&#xff0c;我们现在已经对面向对象有了基本的认知&#xff0c;掌握了面向对…

基于Java员工信息管理系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

2.04_基于矩阵分解的协同过滤推荐

矩阵分解发展史 Traditional SVD: 通常SVD矩阵分解指的是SVD(奇异值)分解技术,在这我们姑且将其命名为Traditional SVD(传统并经典着)其公式如下: Traditional SVD分解的形式为3个矩阵相乘,中间矩阵为奇异值矩阵。如果想运用SVD分解的话,有一个前提是要求矩阵是稠密…

AAC ADTS格式分析

标题 1.AAC简介2. AAC ADTS格式分析2.1 adts_fixed_header详细介绍2.2 adts_variable_header详细介绍 1.AAC简介 AAC音频格式:Advanced Audio Coding(⾼级⾳频解码)&#xff0c;是⼀种由MPEG-4标准定义的有损⾳频压缩格式&#xff0c;由Fraunhofer发展&#xff0c;Dolby, Sony…

[CISCN 2023 初赛]puzzle 解析

打开文件包给了一堆拼图碎片&#xff0c;由于文件数量高达2880张&#xff0c;这里不考虑gaps的方式进行修正拼图 &#xff08;因为跑了也只会把gaps跑冒烟&#xff09; tmp类型的拼图&#xff0c;因为tmp文件特性在文件头的位置会有其在原图片上的位置坐标 于是&#xff0c;我…

MyBatis-Plus一级缓存和二级缓存-redis解决缓存的脏数据

MyBatis-Plus一级缓存和二级缓存 文章目录 MyBatis-Plus一级缓存和二级缓存[TOC](文章目录) 基本缓存问题一级缓存-MyBatis默认打开一级缓存、不允许关闭二级缓存&#xff08;默认是开启)注意:二级缓存的作用域不然更新了数据,还是使用查询到缓存的数据&#xff09;操作演示第一…

系统编程(1):基本程序框架--IO

文章目录 一、main函数二、IO&#xff08;输入/输出&#xff09;2.1 标准IO和文件IO2.2 文件描述符2.2 open函数 一、main函数 #include <stdio.h> #include <stdlib.h>int main(int argc, char* argv[]) {// argc&#xff1a;表示是命令行中参数的个数// argv&am…

天融信堡垒机怎么结合国密OTP动态令牌实现双因子身份认证?

摘要&#xff1a; 结合宁盾国密OTP动态令牌为天融信堡垒机登录开启双因子身份认证机制&#xff0c;能有效增强运维人员的账号安全&#xff0c;满足等保合规要求。 天融信运维安全审计系统&#xff08;简称“堡垒机”&#xff09;是面向政府、企事业单位等组织机构推出的兼具运…

一篇文章教你pytest+yaml实现参数化

目录 一、使用背景 二、parametrize 三、yaml 四、将yaml数据转换成parametrize可读的列表形式 总结&#xff1a; 一、使用背景 当我们在设计用例的时候&#xff0c;经常会出现需要不同参数的情况&#xff0c;例如一个登录的用例&#xff0c;我们需要测试它登录名正常、为…

【JAVA集合篇】深入理解HashMap源码

文章目录 HashMap简介源码分析关键参数获取数组下标put方法resize扩容过程jdk1.7的扩容实现jdk1.8的扩容实现 get()方法remove()方法 总结 关于HashMap&#xff0c;一直都是一个非常热门的话题&#xff0c;只要你出去面试&#xff0c;一定少不了它&#xff01; 本文主要结合 JD…

Scala--04

第 8 章 高级语法 Scala//需求&#xff1a;制作一个计算器&#xff0c;实现你传一个字符串给我&#xff0c;比如 23&#xff0c;然后我返回一个结果5给你 def plus(str: String): String { var res "" if (str.contains("")) { val arr: Array[S…

Halcon 循环找出多张电路板上的焊盘 (PCB板的有效区域在图中位置不一样)

文章目录 1 问题描述2 关键代码演示2.1 缩减范围,提高效率2.2 求差,去掉矩形块,只剩下圆3.3 最终效果3 完整代码1 问题描述 如图,循环找出下面四张电路板上的 焊盘; 四张图的有效区域在图中的位置不一样; 且图中还有和焊盘区域相近的矩形黑块; 为了提高效率,先找到产…

[数据分析与可视化] Python绘制数据地图3-GeoPandas使用要点

本文主要介绍GeoPandas的使用要点。GeoPandas是一个Python开源项目&#xff0c;旨在提供丰富而简单的地理空间数据处理接口。GeoPandas扩展了Pandas的数据类型&#xff0c;并使用matplotlib进行绘图。GeoPandas官方仓库地址为&#xff1a;GeoPandas。GeoPandas的官方文档地址为…

模糊聚类在负荷实测建模中的应用(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Python如何把列表自定义分组后并重复2次

一、问题的由来 之前&#xff0c;我写过一篇调用同花顺机器翻译api&#xff0c;批量翻译字幕的文章。 在调用机器翻译api过程中&#xff0c;我遇到一个问题&#xff0c;就是网站给的Python样例代码中只接收字符长度少于5000的列表&#xff0c;所以我想&#xff0c;如果我们一…

Docker常用命令(+仓库,镜像,容器的关系)

一、仓库&#xff08;repository&#xff09;&#xff0c;镜像&#xff08;image&#xff09;&#xff0c;容器&#xff08;container&#xff09;的关系 Docker 是一个开源的C/S架构应用容器引擎&#xff08;客户端&#xff08;client&#xff09;和服务端&#xff08;server&…

Android实现一个可拖拽带有坐标尺的进度条

拿到上边的UI效果图&#xff0c;给我的第一印象就是这实现起来也太简单了吧&#xff0c;SeekBar轻轻松松就搞定了&#xff0c;换个thumb&#xff0c;加个渐变不就完成了&#xff0c;说搞就搞&#xff0c;搞着搞着就抑郁了&#xff0c;底部坐标尺还能搞&#xff0c;等比例分割后…

Springboot开发微信小游戏后台-玩家登录流程

最近使用Springboot开发了一个微信小游戏的后台服务&#xff0c;为小游戏提供接口&#xff0c;其中登录需要前后端与微信服务端配合。 注意使用自己开发的服务作为小游戏后端&#xff0c;前提条件是必须要有域名证书&#xff0c;提供https服务&#xff0c;否则在微信正式环境下…