【c语言五子棋】自定义类型五子棋/井字棋:胜负判断

一、算法思路

由于五子棋规则比较简单,我们可以胜负判断分为以下几个方面分别判断:

1:横向判断

2,竖向判断

3.斜向判断(从左下到右上)

4.斜向判断(从左上到右下)

二、算法原理(算法来源)

参考字符串匹配的处理方法,具体可以参考::从头到尾彻底理解KMP - Chris_z - 博客园 (cnblogs.com)

1.MP算法:即暴力寻找子串(胜利串),时间复杂度为O(M*N)n为文本串m为模板串

2.KMP算法:一种优化算法,时间复杂度为O(M+N),由于涉及数据不多所以可以暂时不考虑使用(主要是因为还不会)

3.【扩展】BM算法

4.【扩展】Sunday算法

5.c++自带strstr()

原理如下:(以7x7棋盘的4子棋为例)

1.局部扫描判定:(以“落子”标记为最近一次落的子)

以每次落子位置作为基准点,对其可能胜利的所有位置进行扫描。这种方法比每次落子时,对整个棋盘扫描效率更高

如图所示

 2.扫描方法:块扫描

把获胜连子数(四子棋,即4)打包扫描,进行行和列的扫描

 横向扫描如图所示,竖向同理

四个为一组打包,假设一组里都是同色棋子,则判断胜利,否则继续扫描,直至扫完成排/列

此处处理并不复杂,代码一看就懂

斜向扫描需要对子进行处理:分为左下到右上(/)和左上到右下(\)

当落子如图所示,则不需要进行/扫描,得出四个角都无需判断,直接跳过(进行\判断)

运行结果:

二、代码实现

总判断:

int win(int positionx, int positiony, int length, int winrule)
{
	if (ifwina(positionx, positiony, length, winrule) == 9999 || ifwinb(positionx, positiony, length, winrule) == 9999 || ifwinc(positionx, positiony, length, winrule) == 9999 || ifwind(positionx, positiony, length, winrule) == 9999)return 1;
	if (ifwina(positionx, positiony, length, winrule) == 10000 || ifwinb(positionx, positiony, length, winrule) == 10000 || ifwinc(positionx, positiony, length, winrule) == 10000 || ifwind(positionx, positiony, length, winrule) == 10000)return 2;
	int flag = 1;
	for (int i = 0; i < length; i++)
	{
		for (int j = 0; j < length; j++)
		{
			if (map[i][j] == 0) flag = 0;
		}
	}
	if (flag) return 3;
	return 0;
}

横向判断:

//横向判断
int ifwina(int positionx, int positiony, int length, int winrule)
{
	int whitewin = 0, blackwin = 0, score = 0;			//记录连续落子个数
	for (int i = 0; i < length - winrule + 1; i++)
	{
		whitewin = 0, blackwin = 0;
		for (int k = 0; k < winrule; k++)
		{
			if (wh[positionx][i + k] == 1)whitewin += 1;
			if (bl[positionx][i + k] == 1)blackwin += 1;
		}
		if (ifwin(whitewin, blackwin, winrule) == 1)return 9999;
		else if (blackwin > score)score = blackwin;
	}
	return score;
}

竖向判断:

//竖向判断
int ifwinb(int positionx, int positiony, int length, int winrule)
{
	int whitewin = 0, blackwin = 0, score = 0;
	for (int i = 0; i < length - winrule + 1; i++)
	{
		whitewin = 0, blackwin = 0;
		for (int k = 0; k < winrule; k++)
		{
			if (wh[i + k][positiony] == 1)whitewin++;
			if (bl[i + k][positiony] == 1)blackwin++;
		}
		if (ifwin(whitewin, blackwin, winrule) == 1)return 9999;
		else if (blackwin > score)score = blackwin;
	}
	return score;
}

斜向判断:

//然后斜向判断:从左上扫到右下
int ifwinc(int positionx, int positiony, int length, int winrule)
{
	int whitewin = 0, blackwin = 0,score = 0;			//记录连续落子个数
	int start = fabs(positionx - positiony);
	int scan = length - winrule + 1 - (fabs(positionx - positiony));

	if (scan <= 0)return 0;

	for (int i = 0; i < scan; i++)
	{
		whitewin = 0, blackwin = 0;
		//扫左下部分
		if (positionx > positiony)
			for (int j = 0; j < winrule; j++)
			{
				if (wh[start + i + j][i + j] == 1)whitewin++;
				if (bl[start + i + j][i + j] == 1)blackwin++;
			}
		//扫右上部分
		else
			for (int j = 0; j < winrule; j++)
			{
				if (wh[i + j][start + i + j] == 1)whitewin++;
				if (bl[i + j][start + j + i] == 1)blackwin++;
			}
		if (ifwin(whitewin, blackwin, winrule) == 1)return 9999;
		else if (blackwin > score)score = blackwin;
	}
	return score;
}
//最后斜向判断:从左下扫到右上
int ifwind(int positionx, int positiony, int length, int winrule)
{
	int whitewin = 0, blackwin = 0,score=0;
	int start, scan;

	if (positionx + positiony >= length-1)
	{
		start = positionx + positiony - length + 1;		//y的开始值
		scan = positionx + positiony - length + 2;
	}
	else
	{
		start = positionx + positiony;			//x的开始值
		scan = positionx + positiony - length + 2;
	}

	for (int i = 0; i < scan; i++)
	{
		whitewin = 0, blackwin = 0;
		//扫左下部分
		if (positionx + positiony >= length)
			for (int j = 0; j < winrule; j++)
			{
				if (wh[length - 1 - j - i][start + j + i] == 1)whitewin++;
				if (bl[length - 1 - j - i][start + j + i] == 1)blackwin++;
			}
		//扫右上部分
		else
			for (int j = 0; j < winrule; j++)
			{
				if (wh[start + j + i][length - 1 - j - i] == 1)whitewin++;
				if (bl[start + j + i][length - 1 - j - i] == 1)blackwin++;
			}

		if (ifwin(whitewin, blackwin, winrule) == 1)return 9999;
		else if (blackwin > score)score = blackwin;
	}
	return score;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值