#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#define GRIDSIZE 15
#define judge_black 0
#define judge_white 1
//棋盘空白位置为0,黑子为1,白子为-1;
#define grid_blank 0
#define grid_black 1
#define grid_white -1
using namespace std;
int currBotColor; // 本方所执子颜色(1为黑,-1为白,棋盘状态亦同)
int gridInfo[GRIDSIZE][GRIDSIZE] = { 0 }; // 先x后y,记录棋盘状态
//评分规则:
//从前到后分别是 六连, 长连, 活五, 眠五, 死五,活四, 眠四, 死四,活三,朦胧三,眠三,死三,活二,眠二,死二 :
int Score_us[15] = { 5000000, 5000000,25000, 800, 0, 20000, 1500, 0 , 600, 400, 200, 0, 500, 2, 0 };
int Score_enemy[15] = { 1000000, 1000000,1000000, 1000000, 0, 1000000, 1000000,0 , 600, 400, 200, 0, 500, 2, 0 };
// 判断是否在棋盘内
inline bool inMap(int x, int y)
{
if (x < 0 || x >= GRIDSIZE || y < 0 || y >= GRIDSIZE)
return false;
return true;
}
// 在坐标处落子,检查是否合法或模拟落子
bool ProcStep(int x0, int y0, int x1, int y1, int grid_color, bool check_only)
{
if (x1 == -1 || y1 == -1) {
if (!inMap(x0, y0) || gridInfo[x0][y0] != grid_blank)
return false;
if (!check_only) {
gridInfo[x0][y0] = grid_color;
}
return true;
}
else {
if ((!inMap(x0, y0)) || (!inMap(x1, y1)))
return false;
if (gridInfo[x0][y0] != grid_blank || gridInfo[x1][y1] != grid_blank)
return false;
if (!check_only) {
gridInfo[x0][y0] = grid_color;
gridInfo[x1][y1] = grid_color;
}
return true;
}
}
/*以下为我补充的代码*/
typedef struct Pos {
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;
int val = 0;
};
/* 以下是十五种可能的棋形分析函数,这些函数将对一路上存在多少种该种棋形进行统计 */
int* nextcreat(int patt[], int patt_len) {
int* next = new int[patt_len];
next[0] = 0;
int prefix_suffix_len = 0;
int i = 1;
int len = patt_len;
while (i < len) {
if (patt[prefix_suffix_len] == patt[i])
{
prefix_suffix_len++;
next[i] = prefix_suffix_len;
i++;
}
else {
if (prefix_suffix_len == 0)
{
next[i] = prefix_suffix_len;
i++;
}
else {
prefix_suffix_len = next[prefix_suffix_len - 1];
next[i] = next[prefix_suffix_len];
i++;
}
}
}
return next;
}//创建next数组实现kmp
int kmp(int* b, int* patt2, int* next, int patt_len, int a_len) {
int i = 0;
int j = 0;
int len2 = a_len;
int len = patt_len;
while (i < len2) {
if (b[i] == patt2[j])
{
i++;
j++;
}
else if (j > 0)
j = next[j - 1];
else i++;
if (j == len)return i - j;
}
return -1;
}//kmp函数
//1&&2:六连,长连
//oooooo 或者 ooooooo
//六颗或七颗及以上棋子不间隔的相连;
/***********************************************************************/
/*已经被验证过*/
int OneRoad_SixConnect_Count(int a[], int side) {
int count = 0; //用以计数连子个数
int result = 0;
for (int i = 0; i < 15; i++)
{
if (a[i] == side)
count++;
else
{
if (count >= 6)
{
result++;
count = 0;
}
else
count = 0;
}
if (i == 14 && count >= 6)
result++;
}
return result;
}
/*************************************************************************/
//3:活5
//gooooog 或者 ggoooogo 或者 ogoooogg
//对手需要用两颗棋子才能阻止我们达成六连或长连;
/*************************************************************************/
/*已经被验证过*/
int OneRoad_LiveFive_Count(int a[], int side) {
int cheak1[7] = { 0,side,side,side,side,side,0 };
int cheak[2][8] = {
{ 0,0,side,side,side,side,0,side },
{ side,0,side,side,side,side,0,0 },
}
;
int count = 0;
int a_len = 15;
int cheak_len;
for (int i = 2; i >= 0; i--) {
if (i == 2) {
cheak_len = 7;
int* next = nextcreat(cheak1, cheak_len);
int j = kmp(a, cheak1, next, cheak_len, a_len);
if (j != -1) {
count++;
if ((j + 6) <= 8)
{
int temp = j + 6;
int b_len = 14 - temp + 1;
int* b = new int[b_len];
int temp2 = 0;
for (int m = temp; m < 15; m++) {
b[temp2] = a[m];
temp2++;
}
j = kmp(b, cheak1, next, cheak_len, b_len);
if (j != -1)count++;//对于0-14,对于每种棋型,最多两次kmp!
}
}
}
else {
cheak_len = 8;
int* next = nextcreat(cheak[i], cheak_len);
int j = kmp(a, cheak[i], next, cheak_len, a_len);
if (j != -1)
count++;
}
}
return count;
}
/*************************************************************************/
//4:眠5
//xooooog 或者 gooooox 或者
//ab当中至少有一个是x,c到h当中有五个o,一个g
//gh当中至少有一个是x,a到f当中有五个o,一个g;
//对手只需要一颗棋子就可以阻止我们达成六连或长连;
int OneRoad_SleepFive_Count(int a[], int side) {
int count = 0;
int cheak1[9][7] = {
{side,side,0,side,side,side,0},
{0,side,side,side,0,side,side},
{side,side,0,side,0,side,side},
{-side,side,side,side,side,side,0},
{0,side,side,side,side,side,-side},
{-side,side,side,side,0,side,side},
{-side,side,side,side,side,0,side},
{side,side,0,side,side,side,-side},
{side,0,side,side,side,side,-side},
};
int cheak2[12][8] = {
{0,side,side,side,0,side,0,side},
{side,side,0,side,side,0,side,0},
{0,side,0,side,side,0,side,side},
{side,0,side,0,side,side,side,0},
{0,side,side,side,0,0,side,side},
{side,side,0,0,side,side,side,0},
{-side,side,side,0,side,side,side,0},
{0,side,side,side,0,side,side,-side},
{-side,side,side,side,0,0,side,side},
{-side,side,side,side,side,0,0,side},
{side,side,0,0,side,side,side,-side},
{side,0,0,side,side,side,side,-side}
};
int a_len = 15;
for (int i = 0; i < 9; i++) {
int cheak_len = 7;
int* next = nextcreat(cheak1[i], cheak_len);
int j = kmp(a, cheak1[i], next, cheak_len, a_len);
if (j != -1) {
count++;
if (i != 2) {
if ((j + 7) <= 8)
{
int temp = j + 7;
int b_len = 14 - temp + 1;
int* b = new int[b_len];
int temp2 = 0;
for (int m = temp; m < 15; m++) {
b[temp2] = a[m];
temp2++;
}
j = kmp(b, cheak2[i], next, cheak_len, b_len);
if (j != -1)count++;//对于0-14,对于每种棋型,最多两次kmp!
}
}
else if ((j + 6) <= 8)
{
int temp = j + 6;
int b_len = 14 - temp + 1;
int* b = new int[b_len];
int temp2 = 0;
for (int m = temp; m < 15; m++) {
b[temp2] = a[m];
temp2++;
}
j = kmp(b, cheak2[i], next, cheak_len, b_len);
if (j != -1)count++;//对于0-14,对于每种棋型,最多两次kmp!
}
}
}
for (int i = 0; i < 12; i++) {
int cheak_len = 8;
int* next = nextcreat(cheak2[i], cheak_len);
int j = kmp(a, cheak2[i], next, cheak_len, a_len);
if (j != -1) {
count++;
}
}
return count;
}
//5:死5
//xooooox
//本身没有任何价值,我们不做研究;
//6:活4
//ggoooogg
//对手需要使用两个棋子才能阻止我们达成六连或长连;
/***********************************************************************************/
/*已经验证过*/
int OneRoad_LiveFour_Count(int a[], int side) {
int check1[8] = { 0,0,side,side,side,side,0,0 };
int count = 0;
for (int i = 0; i < 8; i++)
{
int k = 0;
for (int j = i; j < i + 8; j++)
{
if (check1[k] != a[j])
break;
if (j == i + 7 && check1[k] == a[j])
count++;
k++;
}
}
return count;
}
/***********************************************************************************/
//7:眠4:
//ah当中至少有一个是敌方棋子,中间的b到g有四个我方棋,两个空格;
//对手只需要用一个棋子就可以阻止我们达成六连或长连;
int OneRoad_SleepFour_Count(int a[], int side) {
int count = 0;
int cheak1[2][6] = {//side中无空格
{-side,side,side,side,side,0},
{0,side,side,side,side,-side},
};
int cheak2[11][7] = {//side中有1个空格
{0,side,side,side,side,0,-side},
{0,side,0,side,side,side,-side},
{0,side,side,0,side,side,-side},
{0,side,side,side,0,side,-side},
{-side,0,side,side,side,side,0},
{-side,side,0,side,side,side,0},
{-side,side,side,0,side,side,0},
{-side,side,side,side,0,side,0},//1个-side,1个0包围
{0,side,0,side,side,side,0},
{0,side,side,0,side,side,0},
{0,side,side,side,0,side,0}//2个0包围
};
int cheak3[33][8] = {//side中有2个空格
{0,side,0,0,side,side,side,-side},
{0,side,side,0,0,side,side,-side},
{0,side,side,side,0,0,side,-side},
{0,side,0,side,0,side,side,-side},
{0,side,0,side,side,0,side,-side},
{0,side,side,0,side,0,side,-side},
{-side,side,0,0,side,side,side,0},
{-side,side,side,0,0,side,side,0},
{-side,side,side,side,0,0,side,0},
{-side,side,0,side,0,side,side,0},
{-side,side,0,side,side,0,side,0},
{-side,side,side,0,side,0,side,0},//1个-side,1个0包围
{0,side,0,0,side,side,side,0},
{0,side,side,0,0,side,side,0},
{0,side,side,side,0,0,side,0},
{0,side,0,side,0,side,side,0},
{0,side,0,side,side,0,side,0},
{0,side,side,0,side,0,side,0},//2个0包围
{-side,0,0,side,side,side,side,-side},
{-side,side,0,0,side,side,side,-side},
{-side,side,side,0,0,side,side,-side},
{-side,side,side,side,0,0,side,-side},
{-side,side,side,side,side,0,0,-side},
{-side,0,side,0,side,side,side,-side},
{-side,0,side,side,0,side,side,-side},
{-side,0,side,side,side,0,side,-side},
{-side,0,side,side,side,side,0,-side},
{-side,side,0,side,0,side,side,-side},
{-side,side,0,side,side,0,side,-side},
{-side,side,0,side,side,side,0,-side},
{-side,side,side,0,side,0,side,-side},
{-side,side,side,0,side,side,0,-side},
{-side,side,side,side,0,side,0,-side}//2个-side包围
};
int a_len = 15;
for (int i = 0; i < 2; i++) {
int cheak_len = 6;
int* next = nextcreat(cheak1[i], cheak_len);
int j = kmp(a, cheak1[i], next, cheak_len, a_len);
if (j != -1) {
count++;
if ((j + 6) <= 9)
{
int temp = j + 6;
int b_len = 14 - temp + 1;
int* b = new int[b_len];
int temp2 = 0;
for (int m = temp; m < 15; m++) {
b[temp2] = a[m];
temp2++;
}
j = kmp(b, cheak1[i], next, cheak_len, b_len);
if (j != -1)count++;//对于0-14,对于每种棋型,最多两次kmp!
}
}
}
for (int i = 0; i < 11; i++) {
int cheak_len = 7;
int* next = nextcreat(cheak2[i], cheak_len);
int j = kmp(a, cheak2[i], next, cheak_len, a_len);
if (j != -1) {
count++;
if (i != 6 && i != 7 && i != 8) {
if ((j + 7) <= 8)
{
int temp = j + 7;
int b_len = 14 - temp + 1;
int* b = new int[b_len];
int temp2 = 0;
for (int m = temp; m < 15; m++) {
b[temp2] = a[m];
temp2++;
}
j = kmp(b, cheak2[i], next, cheak_len, b_len);
if (j != -1)count++;//对于0-14,对于每种棋型,最多两次kmp!
}
}
else if ((j + 6) <= 8)
{
int temp = j + 6;
int b_len = 14 - temp + 1;
int* b = new int[b_len];
int temp2 = 0;
for (int m = temp; m < 15; m++) {
b[temp2] = a[m];
temp2++;
}
j = kmp(b, cheak2[i], next, cheak_len, b_len);
if (j != -1)count++;//对于0-14,对于每种棋型,最多两次kmp!
}
}
}
for (int i = 0; i < 33; i++) {
int cheak_len = 8;
int* next = nextcreat(cheak3[i], cheak_len);
int j = kmp(a, cheak3[i], next, cheak_len, a_len);
if (j != -1) {
count++;
if (i <= 11) {
1;
}
else if ((j + 7) <= 7)
{
int temp = j + 7;
int b_len = 14 - temp + 1;
int* b = new int[b_len];
int temp2 = 0;
for (int m = temp; m < 15; m++) {
b[temp2] = a[m];
temp2++;
}
j = kmp(b, cheak2[i], next, cheak_len, b_len);
if (j != -1)count++;//对于0-14,对于每种棋型,最多两次kmp!
}
}
}
return count;
}
//8:死4:
//xoooox ,xgoooox;
//没有任何价值,不做研究;
//9:活3:
//ggoooggg 或者 gggooogg 或者 ggoogogg 或者 ggogoogg;
//我们在下一颗棋子就可以达成活四;
int OneRoad_LiveThree_Count(int a[], int side) {
int count = 0;
int cheak[4][8] = {
{0,0,side,side,side,0,0,0},
{0,0,0,side,side,side,0,0},
{0,0,side,side,0,side,0,0},
{0,0,side,0,side,side,0,0}
};
int a_len = 15;
int cheak_len = 8;
for (int i = 0; i < 4; i++) {
int* next = nextcreat(cheak[i], cheak_len);
int j = kmp(a, cheak[i], next, cheak_len, a_len);
if (j != -1) {
count++;
if ((j + 6) <= 7)
{
int temp = j + 6;
int b_len = 14 - temp + 1;
int* b = new int[b_len];
int temp2 = 0;
for (int m = temp; m < 15; m++) {
b[temp2] = a[m];
temp2++;
}
j = kmp(b, cheak[i], next, cheak_len, b_len);
if (j != -1)count++;//对于0-14,对于每种棋型,最多两次kmp!
}
}
}
return count;
}
//10:朦胧3:
//(1)ah当中至少有一个敌方棋,bg两个位置为空,c到f当中有三个我方棋,三个空格;
//(2)a是敌方棋,hi为空,b到g当中有三个我方棋,三个空格;
//(3)i是敌方棋,ab为空格,c到h当中有三个我方棋,三个空格;
//我们在下一颗棋子可以达成眠四,同时我们在下两颗棋子就可以达成活五;
int OneRoad_UnsureThree_Count(int a[], int side) {
int judge_continuous = 0;
int ans = 0;
for (int i = 0; i < 15; i++)
{
int recover_i = i;
int judgeempty = 0;
if (a[i] == 0)
{
i += 1;
if (i > 13)
break;
int tempi = i + 5;
for (i; i < tempi; i++)
{
if (a[i] == side || a[i] == 0)
{
judge_continuous += 1;
if (a[i] == 0)
judgeempty += 1;
}
else if (a[i] == -1)
{
while (i < 18 && a[i + 1] != -1)
i += 1;
judge_continuous = 0;
goto here10;
}
else
{
i = recover_i;
break;
}
}
}
if (judge_continuous == 5 && judgeempty == 2 && a[i] == 0)
{
ans += 1;
for (int j = 1; j < 6; j++)
{
if (a[i - j] == side)
a[i - j] = -1;
}
}
else
{
judge_continuous = 0;
i = recover_i;
}
here10:i = i;
}
return ans;
}
//11:眠3:
//(1)ab当中至少有一个是敌方棋,c到h当中有三个我方棋,三个空格;
//(2)gh当中至少有一个是敌方棋,a到f当中有三个是我方棋,有三个是空格;
//我们在下两颗棋子也只能达成眠五;
int OneRoad_SleepThree_Count(int a[], int side) {
int oppside = 0 - side;
int count = 0;//此种棋型的个数
int counts = 0, countg = 0;//counts为范围6内我方棋的个数,countg为空格的个数
for (int i = 0; i < 8; i++) {
int j = i;
if (a[j] == oppside || a[j + 1] == oppside) {//a或b至少有一个为敌方棋
for (int j = i + 2; j < i + 8; j++) {
if (a[j] == side)
counts++;
else if (a[j] == 0)
countg++;
}
if (counts == 3 && countg == 3)
{
count++;
i = i + 6;
}
counts = 0;
countg = 0;
}
else if (a[j + 6] == oppside || a[j + 7] == oppside) {//g或h至少有一个为敌方棋
for (int j = i; j < i + 6; j++) {
if (a[j] == side)
counts++;
else if (a[j] == 0)
countg++;
}
if (counts == 3 && countg == 3)
{
count++;
i = i + 4;
}
counts = 0;
countg = 0;
}
}
return count;
}
//12:死3:
//xooox;
//没有任何价值,不做研究;
//13:活2:
//ggoogggg 或者 ggogoggg 或者 ggoggogg
//gggooggg 或者 gggogogg 或者 ggggoogg
//我们在下两颗棋子就能形成活四;
int OneRoad_LiveTwo_Count(int a[], int side) {
int count = 0;
int cheak[6][8] = {
{0,0,side,side,0,0,0,0},
{0,0,side,0,side,0,0,0},
{0,0,side,0,0,side,0,0},
{0,0,0,side,side,0,0,0},
{0,0,0,side,0,side,0,0},
{0,0,0,0,side,side,0,0}
};
int a_len = 15;
int cheak_len = 8;
for (int i = 0; i < 6; i++) {
int* next = nextcreat(cheak[i], cheak_len);
int j = kmp(a, cheak[i], next, cheak_len, a_len);
if (j != -1) {
count++;
if ((j + 6) <= 7)
{
int temp = j + 6;
int b_len = 14 - temp + 1;
int* b = new int[b_len];
int temp2 = 0;
for (int m = temp; m < 15; m++) {
b[temp2] = a[m];
temp2++;
}
j = kmp(b, cheak[i], next, cheak_len, b_len);
if (j != -1)count++;//对于0-14,对于每种棋型,最多两次kmp!
}
}
}
return count;
}
//14:眠2:
//(1)ab当中至少有一个是敌方棋,c到h之中有两个我方棋子,有四个空格;
//(2)ah当中至少有一个是敌方棋,b到g之间有两个我方棋子,四个空格;
//(3)gh当中至少有一个是敌方棋,a到f之间有两个我方棋子,四个空格;
//我们在下两颗棋子也只能达成眠四;
int OneRoad_SleepTwo_Count(int a[], int side) {
int oppside = 0 - side;
int count = 0;
int counts = 0, countg = 0;//counts为范围6内我方棋的个数,countg为空格的个数
for (int i = 0; i < 8; i++) {
int j = i;
if (a[j] == oppside || a[j + 1] == oppside) {
for (int j = i + 2; j < i + 8; j++) {
if (a[j] == side)counts++;
else if (a[j] == 0)countg++;
else;
}
if (counts == 2 && countg == 4) { count++; }
counts = 0;
countg = 0;
i = i + 6;
}
else if (a[j] == oppside || a[j + 7] == oppside) {
for (int j = i + 1; j < i + 7; j++) {
if (a[j] == side)counts++;
else if (a[j] == 0)countg++;
else;
}
if (counts == 2 && countg == 4) { count++; }
counts = 0;
countg = 0;
i = i + 5;
}
else if (a[j + 6] == oppside || a[j + 7] == oppside) {
for (int j = i; j < i + 6; j++) {
if (a[j] == side)counts++;
else if (a[j] == 0)countg++;
else;
}
if (counts == 2 && countg == 4) { count++; }
counts = 0;
countg = 0;
i = i + 4;
}
else;
}
return count;
}
//15:死2
//xoox;
//没有任何价值,我们不做研究;
//取路函数,我们可以利用这个函数将一个点在某个方向上的路取出来,在调用类型计数之后返回各棋形数量:
//水平方向上的取路函数:
void GetRoad_Horizontal(int Grid[GRIDSIZE][GRIDSIZE], int res[], int side, int x, int y) {
for (int i = 0; i < 15; i++)
{
res[i] = Grid[x][i];
}
}
//竖直方向上的取路函数:
void GetRoad_Vertical(int Grid[GRIDSIZE][GRIDSIZE], int res[], int side, int x, int y) {
for (int i = 0; i < 15; i++)
{
res[i] = Grid[i][y];
}
}
//主对角线方向上的取路函数:
void GetRoad_LeadingDiagonal(int Grid[GRIDSIZE][GRIDSIZE], int res[], int side, int x, int y) {
int opside = 0 - side;
for (int i = 0; i < 15; i++) res[i] = opside;
int num = 0;
int i = x; int j = y;
int temp = 1;
int lis = 0;
if (x > y) // 下半区
{
num = 15 - x + y;
lis = x - y;
for (int i = 0; i < num; i++) {
res[i] = Grid[i + lis][i];
}
}
else
{
num = 15 - y + x;
lis = y - x;
for (int i = 0; i < num; i++) {
res[i] = Grid[i][i + lis];
}
}
}
//副对角线上的取路函数:
void GetRoad_CounterDiagonal(int Grid[GRIDSIZE][GRIDSIZE], int res[], int side, int x, int y) {
int opside = 0 - side;
for (int i = 0; i < 15; i++) res[i] = opside;
int num = 0;
int i = x; int j = y;
int temp = 1;
int lis = 0;
if (x + y > 14) // 下半区
{
int k = 0;
lis = x + y;
for (int i = lis - 14; i < 15; i++) {
res[k] = Grid[i][lis - i];
k++;
}
}
else //上半区
{
num = x + y + 1;
lis = x + y;
for (int i = 0; i < num; i++) {
res[i] = Grid[i][lis - i];
}
}
}
//定义一个单路我方棋子数量的统计函数:
int NumOfUs_OneRoad(int a[], int side) {
int ans = 0;
for (int i = 0; i < 15; i++) {
if (a[i] == side) {
ans++;
}
}
return ans;
}
//判断四周是否有棋子的函数,如果该点两个格子的范围内有棋子,则返回真,否则返回假:
bool NotEmpty(int Grid[GRIDSIZE][GRIDSIZE], int x, int y) {
//Grid记录了当前的棋盘状况,(x,y)为当前考察的点坐标:
//在以(x-2 , y-2),(x-2 , y+2),(x+2 , y-2),(x+2 , y+2)为顶点的矩阵内搜索,在除了九个特殊点之外,只要能够找到一个非零点,即可返回true;
//在判断这个点的数值之前,我们要先确保该点没有越界:
for (int i = x - 2; i <= x + 2; i++) {
for (int j = y - 2; j <= y + 2; j++) {
if (i >= 0 && i < 15 && j >= 0 && j < 15) { //没越界;
if (!((i == x && j == y) || (i == x - 2 && j == y - 1) || (i == x - 2 && j == y + 1) || (i == x - 1 && j == y - 2) || (i == x - 1 && j == y + 2) || (i == x + 1 && j == y - 2) || (i == x + 1 && y + 2) || (i == x + 2 && j == y - 1) || (i == x + 2 && j == y + 1))) {
if (Grid[i][j] != 0) {
return true;
}
}
}
}
}
return false;
}
//单路整体的分析函数:
void OneRoad_analyze(int road[], int res[], int side) {
int NumOfUs = NumOfUs_OneRoad(road, side);
if (NumOfUs >= 6) {
res[0] += OneRoad_SixConnect_Count(road, side);
res[1] += OneRoad_SixConnect_Count(road, side);
}
if (NumOfUs >= 5) {
res[2] += OneRoad_LiveFive_Count(road, side);
res[3] += OneRoad_SleepFive_Count(road, side);
res[4] += 0;
}
if (NumOfUs >= 4) {
res[5] += OneRoad_LiveFour_Count(road, side);
res[6] += OneRoad_SleepFour_Count(road, side);
res[7] += 0;
}
if (NumOfUs >= 3) {
res[8] += OneRoad_LiveThree_Count(road, side);
res[9] += OneRoad_UnsureThree_Count(road, side);
res[10] += OneRoad_SleepThree_Count(road, side);
res[11] += 0;
}
if (NumOfUs >= 2) {
res[12] += OneRoad_LiveTwo_Count(road, side);
res[13] += OneRoad_SleepTwo_Count(road, side);
res[14] += 0;
}
}
//计算在某一点落子之后可以获得的分数:
int GetScore(int Grid[GRIDSIZE][GRIDSIZE], int side, int x, int y) {
//该分数将由四部分组成,即横,竖,主对角线,副对角线四个方向上的分数和:
int Road_horizontal_direction[15];
GetRoad_Horizontal(Grid, Road_horizontal_direction, side, x, y);
int Road_vertical_direction[15];
GetRoad_Vertical(Grid, Road_vertical_direction, side, x, y);
int Road_leading_diagonal[15];
GetRoad_LeadingDiagonal(Grid, Road_leading_diagonal, side, x, y);
int Road_counter_diagonal[15];
GetRoad_CounterDiagonal(Grid, Road_counter_diagonal, side, x, y);
//总分数结果我们保留到Res_All当中,然后乘上评分规则累加和:
int Res_All[15] = { 0 };
OneRoad_analyze(Road_horizontal_direction, Res_All, side);
OneRoad_analyze(Road_vertical_direction, Res_All, side);
OneRoad_analyze(Road_leading_diagonal, Res_All, side);
OneRoad_analyze(Road_counter_diagonal, Res_All, side);
int ans = 0;
if (side == currBotColor) {
for (int i = 0; i < 15; i++) {
ans += Res_All[i] * Score_us[i];
}
}
else {
for (int i = 0; i < 15; i++) {
ans += Res_All[i] * Score_enemy[i];
}
}
return ans;
}
//核心函数:获取最终的落点坐标函数
void AI_Get_FinalPos(int ans[]) {
//我们在调用函数时尽量使用复制的棋盘,防止出现不可逆的错误:
int Grid_Init[GRIDSIZE][GRIDSIZE];
for (int i = 0; i < GRIDSIZE; i++)
for (int j = 0; j < GRIDSIZE; j++)
Grid_Init[i][j] = gridInfo[i][j];
Pos max_pos;
max_pos.val = -1e9;
max_pos.x1 = -1;
max_pos.y1 = -1;
max_pos.x2 = -1;
max_pos.y2 = -1;
for (int i = 0; i < GRIDSIZE; i++) {
for (int j = 0; j < GRIDSIZE; j++) {
if (Grid_Init[i][j] == 0 && NotEmpty(Grid_Init, i, j)) {
for (int k = 0; k < GRIDSIZE; k++) {
for (int m = 0; m < GRIDSIZE; m++) {
if (i == k && j == m) continue;
if (Grid_Init[k][m] == 0 && NotEmpty(Grid_Init, k, m)) {
//在我们落下任何一颗棋子之前,我们获取一下此时双方的分数:
int Score_Enemy_Before = GetScore(Grid_Init, -currBotColor, i, j) + GetScore(Grid_Init, -currBotColor, k, m);
/*int Score_Us_Before = GetScore(Grid_Init, currBotColor, i, j) + GetScore(Grid_Init, currBotColor, k, m);*/
//在两个坐标落下我们的棋子之后,我们获取一下此时我方以及对方的分数:
Grid_Init[i][j] = Grid_Init[k][m] = currBotColor;
int Score_Us = GetScore(Grid_Init, currBotColor, i, j) + GetScore(Grid_Init, currBotColor, k, m);
int Score_Enemy_After = GetScore(Grid_Init, -currBotColor, i, j) + GetScore(Grid_Init, -currBotColor, k, m);
//最后我们使用我方获得的分数加上对方两次分数的差值表示此次落子最终的得分:
int Score_Final = Score_Us + Score_Enemy_Before - Score_Enemy_After;
//把棋盘恢复,方便后面的估值:
Grid_Init[i][j] = Grid_Init[k][m] = 0;
if (Score_Final > max_pos.val) {
max_pos.val = Score_Final;
max_pos.x1 = i;
max_pos.y1 = j;
max_pos.x2 = k;
max_pos.y2 = m;
}
}
}
}
}
}
}
//最终得出的四个坐标将保存到ans当中,并在函数的末尾返回:
ans[0] = max_pos.x1;
ans[1] = max_pos.y1;
ans[2] = max_pos.x2;
ans[3] = max_pos.y2;
}
int main()
{
int x0, y0, x1, y1;
// 分析自己收到的输入和自己过往的输出,并恢复棋盘状态
int turnID;
cin >> turnID;
currBotColor = grid_white; // 先假设自己是白方
for (int i = 0; i < turnID; i++)
{
// 根据这些输入输出逐渐恢复状态到当前回合
cin >> x0 >> y0 >> x1 >> y1;
if (x0 == -1)
currBotColor = grid_black; // 第一回合收到坐标是-1, -1,说明我是黑方
if (x0 >= 0) //模拟对方落子:
ProcStep(x0, y0, x1, y1, -currBotColor, false);
if (i < turnID - 1) {//模拟己方落子:
cin >> x0 >> y0 >> x1 >> y1;
if (x0 >= 0)
ProcStep(x0, y0, x1, y1, currBotColor, false);
}
}
/************************************************************************************/
/***在下面填充你的代码*****/
int first_x = 0, first_y = 0, second_x = 0, second_y = 0;
bool selfFirstBlack = (turnID == 1 && currBotColor == grid_black);//selfFristBlack作为布尔变量,本方为黑方时为真,否则为假;
if (selfFirstBlack) {//假如说我们是黑方先手,我们直接在棋盘中央开局即可:
first_x = 7, first_y = 7;
second_x = -1, second_y = -1;
}
else {//如果此时已经不是黑方先手了,我们进入正常的决策状态:
//最终决策的结果将由postion接受,并相应的赋值给四个坐标变量:
int Postion[4];
//直接调用核心函数,分析的过程将在核心函数当中实现,最终返回一组坐标表示落子位置:
AI_Get_FinalPos(Postion);
first_x = Postion[0], first_y = Postion[1];
second_x = Postion[2], second_y = Postion[3];
}
/****在上方填充你的代码****/
/************************************************************************************/
// 决策结束,向平台输出决策结果:
cout << first_x << ' ' << first_y << ' ' << second_x << ' ' << second_y << endl;
return 0;
}
六子棋AI(一个非常无脑的贪心版本)
最新推荐文章于 2025-03-11 11:28:52 发布