一、算法思路
由于五子棋规则比较简单,我们可以胜负判断分为以下几个方面分别判断:
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;
}