五子棋(Gomoku)博弈程序

来源:互联网 发布:淘宝开店规定 编辑:程序博客网 时间:2024/05/18 13:27
// Five AI Player// Author: coolypf// #define TEST_PERF#ifdef TEST_PERF#include <Windows.h>#endif#include <iostream>#include <string>#include <algorithm>#include <math.h>#include <memory.h>#include <time.h>using namespace std;const int infinite = 10000000;const int s[4][3][2] = {{{100000, 0},{15000, -200000},{10, 0}},{{15000, -50000},{100, -200},{5, 0}},{{50, -50},{10, -5},{2, 0}},{{10, -5},{2, -1},{1, 0}}};const int range = 15;const int black = 1;const int white = 2;int self, enemy;int rnd;clock_t start_time;int tle;int board[range][range];struct Combo {int x;int y;int score;bool operator < (const Combo &ano) const { return (score > ano.score); }};void AI(int, int);int backtrace(int, int, int[][range], int);int evalutatestep(const int[][range], int, int, int);int evaluate(const int[][range], int);inline int onboard(int x, int y){return (x>=0 && y>=0 && x<range && y<range) ? 1 : 0;}int main(){int x, y;string cmd;rnd = 0;memset(board, 0, sizeof(board));cin >> cmd;cin >> self;enemy = black + white - self;while(1){rnd ++;cin >> cmd;cin >> x >> y;if(onboard(x, y))board[x][y] = enemy;start_time = clock();tle = 0;AI(x, y);}return 0;}void AI(int px, int py){int x = 0, y = 0;int decide = 0;int guess = 0;static int ppx, ppy, myx, myy, cx, cy;#ifdef TEST_PERFLARGE_INTEGER pf_li;double pf_freq, pf_st, pf_ed, pf_t;static double pf_maxtime = 0.0;QueryPerformanceFrequency(&pf_li);pf_freq=(double)pf_li.QuadPart;QueryPerformanceCounter(&pf_li);pf_st=(double)pf_li.QuadPart;int break_at = 0;#endifif(self == black && rnd == 1) {decide = 1;x = 7;y = 7;}if(self == white && rnd == 1) {int mindelta = infinite;if((px - 7)*(px - 7) + (py - 7)*(py - 7) > 32) {x = 7;y = 7;decide = 1;} else for(int i=3; i<=11; ++i)for(int j=3; j<=11; ++j) {int d1 = (i - px)*(i - px) + (j - py)*(j - py);int d2 = (i - 7)*(i - 7) + (j - 7)*(j - 7);if(d1 == 2 && d2 < mindelta) {mindelta = d2;x = i;y = j;decide = 1;cx = px;cy = py;}}}if(!decide) {static Combo vc[range*range];static int mark[range][range];int cur = 0;memset(mark, 0, sizeof(mark));for(int i=0; i<range; ++i) {for(int j=0; j<range; ++j) {if(board[i][j] == 0 && (onboard(i, j-1) && board[i][j-1]||  onboard(i, j-2) && board[i][j-2]||  onboard(i, j+1) && board[i][j+1]||  onboard(i, j+2) && board[i][j+2]||  onboard(i-1, j) && board[i-1][j]||  onboard(i-2, j) && board[i-2][j]||  onboard(i+1, j) && board[i+1][j]||  onboard(i+2, j) && board[i+2][j]||  onboard(i-1, j-1) && board[i-1][j-1]||  onboard(i-2, j-2) && board[i-2][j-2]||  onboard(i+1, j+1) && board[i+1][j+1]||  onboard(i+2, j+2) && board[i+2][j+2]||  onboard(i-1, j+1) && board[i-1][j+1]||  onboard(i-2, j+2) && board[i-2][j+2]||  onboard(i+1, j-1) && board[i+1][j-1]||  onboard(i+2, j-2) && board[i+2][j-2])) {vc[cur].x = i;vc[cur].y = j;vc[cur].score = evalutatestep(board, i, j, self);cur ++;mark[i][j] = 1;}}}sort(vc, vc+cur);guess = cur;cur = min(cur, 22);if(vc[0].score < infinite && rnd < 107) {int maxs = -infinite-100;for(int i=0; i<cur; ++i) {int nx = vc[i].x, ny = vc[i].y;int bakx[25], baky[25], bakc = 0;board[nx][ny] = self;for(int u=-2; u<=2; ++u) {for(int v=-2; v<=2; ++v)if(onboard(nx+u, ny+v) && mark[nx+u][ny+v] == 0&& abs(u) + abs(v) != 3) {mark[nx+u][ny+v] = 1;bakx[bakc] = nx + u;baky[bakc] = ny + v;bakc ++;}}vc[i].score = backtrace(4, 11, mark, maxs);if(vc[i].score > maxs) {maxs = vc[i].score;}board[nx][ny] = 0;for(int j=0; j<bakc; ++j)mark[bakx[j]][baky[j]] = 0;}sort(vc, vc + cur);if((clock() - start_time)*1000/CLOCKS_PER_SEC < 960) {maxs = -infinite-100;int maxi = -1;for(int i=0; i<cur; ++i) {int nx = vc[i].x, ny = vc[i].y;int bakx[25], baky[25], bakc = 0;board[nx][ny] = self;for(int u=-2; u<=2; ++u) {for(int v=-2; v<=2; ++v)if(onboard(nx+u, ny+v) && mark[nx+u][ny+v] == 0&& abs(u) + abs(v) != 3) {mark[nx+u][ny+v] = 1;bakx[bakc] = nx + u;baky[bakc] = ny + v;bakc ++;}}vc[i].score = backtrace(6, 11, mark, maxs);if(tle == 0 && vc[i].score > maxs) {maxs = vc[i].score;maxi = i;}board[nx][ny] = 0;for(int j=0; j<bakc; ++j)mark[bakx[j]][baky[j]] = 0;#ifdef TEST_PERFbreak_at = i + 1;#endifif((clock() - start_time)*1000/CLOCKS_PER_SEC > 960 || tle)break;}if(maxi >= 0)vc[0] = vc[maxi];}}decide = 1;x = vc[0].x;y = vc[0].y;}ppx = px;ppy = py;myx = x;myy = y;board[x][y] = self;#ifdef TEST_PERFQueryPerformanceCounter(&pf_li);pf_ed = (double)pf_li.QuadPart;pf_t = (pf_ed - pf_st) / pf_freq * 1000;if(pf_t > pf_maxtime)pf_maxtime = pf_t;cout << x << " " << y << " " << break_at << " "<< (int)pf_t << " " << (int)pf_maxtime << endl << flush;#elsecout << x << " " << y << endl << flush;#endif}int evaluate(const int b[][range], int c){static const int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1};static const int dy[] = {0, 1, 1, 1, 0, -1, -1, -1};int score = 0;int close[8], bclose[8], jump[8], bjump[8];int cnt[4][3];for(int i=0; i<range; ++i)for(int j=0; j<range; ++j) {if(b[i][j] == 0)continue;int color = b[i][j];int factor = (color != c) ? 1 : 0;memset(cnt, 0, sizeof(cnt));memset(close, 0, sizeof(close));memset(bclose, 0, sizeof(bclose));memset(jump, 0, sizeof(jump));memset(bjump, 0, sizeof(bjump));for(int d=0; d<8; ++d) {int x = i + dx[d], y = j + dy[d];for( ; onboard(x, y) && b[x][y] == color;x+=dx[d], y+=dy[d], ++close[d]);for( ; onboard(x, y) && b[x][y] == 0;x+=dx[d], y+=dy[d], ++bclose[d]);for( ; onboard(x, y) && b[x][y] == color;x+=dx[d], y+=dy[d], ++jump[d]);for( ; onboard(x, y) && b[x][y] == 0;x+=dx[d], y+=dy[d], ++bjump[d]);}for(int d=0; d<4; ++d) {int l = d + 4;if(close[l] + close[d] >= 4)return (1 - 2*factor) * infinite;else if(close[l] + close[d] == 3) {if(bclose[l] > 0 && bclose[d] > 0) {if(factor) return -infinite;else cnt[0][0]++;} else if(bclose[l] > 0 || bclose[d] > 0) {if(factor) return -infinite;else cnt[0][1]++;} elsecnt[0][2]++;} else if(close[l] + close[d] == 2) {if(bclose[l] > 0 && bclose[d] > 0) {if(jump[l] > 0 && bclose[l] == 1|| jump[d] > 0 && bclose[d] == 1) {if(factor) return -infinite;else cnt[0][1]++;} else if(bclose[l] > 1 || bclose[d] > 1)cnt[1][0]++;else cnt[1][1]++;} else if(bclose[l] > 0 || bclose[d] > 0) {if(bclose[l] == 1 && jump[l] > 0|| bclose[d] == 1 && jump[d] > 0) {if(factor) return -infinite;else cnt[0][1]++;} else if(bclose[l] > 1 || bclose[d] > 1)cnt[1][1]++;else cnt[1][2]++;} elsecnt[1][2]++;} else if(close[l] + close[d] == 1) {if(bclose[l] > 0 && bclose[d] > 0) {if(bclose[l] == 1 && jump[l] > 1|| bclose[d] == 1 && jump[d] > 1) {if(factor) return -infinite;else cnt[0][1]++;} else if(bclose[l] == 1 && jump[l] == 1 && bjump[l] > 0|| bclose[d] == 1 && jump[d] == 1 && bjump[d] > 0)cnt[1][0]++;else if(bclose[l] == 1 && jump[l] == 1|| bclose[d] == 1 && jump[d] == 1)cnt[1][1]++;else if(bclose[l] > 1 || bclose[d] > 1)cnt[2][0]++;elsecnt[2][2]++;} else if(bclose[l] > 0 || bclose[d] > 0) {if(bclose[l] == 1 && jump[l] > 1|| bclose[d] == 1 && jump[d] > 1) {if(factor) return -infinite;else cnt[0][1]++;} else if(bclose[l] == 1 && jump[l] == 1 && bjump[l] > 0|| bclose[d] == 1 && jump[d] == 1 && bjump[d] > 0)cnt[1][1]++;else if(bclose[l] > 2 || bclose[d] > 2)cnt[2][1]++;elsecnt[2][2]++;} elsecnt[2][2]++;} else {if(bclose[l] > 0 && bclose[d] > 0) {if(bclose[l] == 1 && jump[l] > 2|| bclose[d] == 1 && jump[d] > 2) {if(factor) return -infinite;else cnt[0][1]++;} else if(bclose[l] == 1 && jump[l] == 2 && bjump[l] > 0|| bclose[d] == 1 && jump[d] == 2 && bjump[d] > 0) cnt[1][0]++;else if(bclose[l] == 1 && jump[l] == 2|| bclose[d] == 1 && jump[d] == 2)cnt[1][1]++;else if(bclose[l] == 1 && jump[l] == 1 && bjump[l] > 1|| bclose[d] == 1 && jump[d] == 1 && bjump[d] > 1)cnt[2][0]++;else if(bclose[l] > 2 || bclose[d] > 2)cnt[3][0]++;else cnt[3][1]++;} else if(bclose[l] > 0 || bclose[d] > 0) {if(bclose[l] == 1 && jump[l] > 2|| bclose[d] == 1 && jump[d] > 2) {if(factor) return -infinite;else cnt[0][1]++;} else if(bclose[l] == 1 && jump[l] == 2 && bjump[l] > 0|| bclose[d] == 1 && jump[d] == 2 && bjump[d] > 0)cnt[1][1]++;else if(bclose[l] == 1 && jump[l] == 1 && bjump[l] > 1|| bclose[d] == 1 && jump[d] == 1 && bjump[d] > 1)cnt[2][1]++;else if(bclose[l] > 3 || bclose[d] > 3)cnt[3][1]++;else cnt[3][2]++;} elsecnt[3][2]++;}}for(int u=0; u<4; ++u)for(int v=0; v<3; ++v)score += cnt[u][v]*s[u][v][factor];if(cnt[0][1] > 1 || cnt[0][1] == 1 && cnt[1][0] > 0)score += s[0][0][factor] * 2;}return score;}int evalutatestep(const int b[][range], int i, int j, int c){static const int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1};static const int dy[] = {0, 1, 1, 1, 0, -1, -1, -1};int score = 0;int close[8], bclose[8], jump[8];int c4a, c4b, c3a, c3b, c2a, c2b, c1a, c1b;for(int test=0; test<2; ++test) {c4a = 0;c4b = 0;c3a = 0;c3b = 0;c2a = 0;c2b = 0;c1a = 0;c1b = 0;memset(close, 0, sizeof(close));memset(bclose, 0, sizeof(bclose));memset(jump, 0, sizeof(jump));for(int d=0; d<4; ++d) {int l = d + 4;int x = i + dx[d], y = j + dy[d];int u = i + dx[l], v = j + dy[l];for( ; onboard(x, y) && b[x][y] == c; x+=dx[d], y+=dy[d], ++close[d]);for( ; onboard(u, v) && b[u][v] == c; u+=dx[l], v+=dy[l], ++close[l]);if(close[l] + close[d] >= 4) {if(test == 0) return infinite;return (infinite - 1000);} else {for( ; onboard(x, y) && b[x][y] == 0; x+=dx[d], y+=dy[d], ++bclose[d]);for( ; onboard(u, v) && b[u][v] == 0; u+=dx[l], v+=dy[l], ++bclose[l]);if(close[l] + close[d] == 3) {if(bclose[l] > 0 && bclose[d] > 0)c4a++;else if(bclose[l] > 0 || bclose[d] > 0)c4b++;} else if(bclose[l] > 0 || bclose[d] > 0) {for( ; onboard(x, y) && b[x][y] == c; x+=dx[d], y+=dy[d], ++jump[d]);for( ; onboard(u, v) && b[u][v] == c; u+=dx[l], v+=dy[l], ++jump[l]);if(close[l] + close[d] == 2) {if(bclose[l] > 0 && bclose[d] > 0) {if(jump[l] > 0 && bclose[l] == 1|| jump[d] > 0 && bclose[d] == 1)c4b++;else if(bclose[l] > 1 || bclose[d] > 1)c3a++;else c3b++;} else {if(bclose[l] == 1 && jump[l] > 0|| bclose[d] == 1 && jump[d] > 0)c4b++;else if(bclose[l] > 1 || bclose[d] > 1)c3b++;}} else if(close[l] + close[d] == 1) {if(bclose[l] > 0 && bclose[d] > 0) {if(bclose[l] == 1 && jump[l] > 1|| bclose[d] == 1 && jump[d] > 1)c4b++;else if(bclose[l] == 1 && jump[l] == 1) {if(onboard(u, v) && b[u][v] == 0) c3a++;elsec3b++;} else if(bclose[d] == 1 && jump[d] == 1) {if(onboard(x, y) && b[x][y] == 0) c3a++;elsec3b++;} else if(bclose[l] > 1 || bclose[d] > 1)c2a++;} else {if(bclose[l] == 1 && jump[l] > 1|| bclose[d] == 1 && jump[d] > 1)c4b++;else if(bclose[l] == 1 && jump[l] == 1 && onboard(u, v) && b[u][v] == 0) c3b++;else if(bclose[d] == 1 && jump[d] == 1 && onboard(x, y) && b[x][y] == 0) c3b++;else if(bclose[l] > 1 || bclose[d] > 1)c2b++;}} else {if(bclose[l] > 0 && bclose[d] > 0) {if(bclose[l] == 1 && jump[l] > 2|| bclose[d] == 1 && jump[d] > 2)c4b++;else if(bclose[l] == 1 && jump[l] == 2) {if(onboard(u, v) && b[u][v] == 0) c3a++;else c3b++;} else if(bclose[d] == 1 && jump[d] == 2) {if(onboard(x, y) && b[x][y] == 0) c3a++;else c3b++;} else if(bclose[l] == 1 && jump[l] == 1 && onboard(u, v) && b[u][v] == 0&& onboard(u+dx[l], v+dy[l]) && b[u+dx[l]][v+dy[l]] == 0) c2a++;else if(bclose[d] == 1 && jump[d] == 1 && onboard(x, y) && b[x][y] == 0&& onboard(x+dx[d], y+dy[d]) && b[x+dx[d]][y+dy[d]] == 0)c2a++;else if(bclose[l] > 2 || bclose[d] > 2)c1a++;} else {if(bclose[l] == 1 && jump[l] > 2|| bclose[d] == 1 && jump[d] > 2)c4b++;else if(bclose[l] == 1 && jump[l] == 2 && onboard(u, v) && b[u][v] == 0) c3b++;else if(bclose[d] == 1 && jump[d] == 2 && onboard(x, y) && b[x][y] == 0) c3b++;else if(bclose[l] == 1 && jump[l] == 1 && onboard(u, v) && b[u][v] == 0&& onboard(u+dx[l], v+dy[l]) && b[u+dx[l]][v+dy[l]] == 0) c2b++;else if(bclose[d] == 1 && jump[d] == 1 && onboard(x, y) && b[x][y] == 0&& onboard(x+dx[d], y+dy[d]) && b[x+dx[d]][y+dy[d]] == 0)c2b++;else if(bclose[l] > 2 || bclose[d] > 2)c1b++;}}}}}if(test == 0) {score += c4a * s[0][0][0];score += c4b * s[0][1][0];score += c3a * s[1][0][0];score += c3b * s[1][1][0];score += c2a * s[2][0][0];score += c2b * s[2][1][0];score += c1a * s[3][0][0];score += c1b * s[3][1][0];if(c4b > 1 || c4b == 1 && c3a > 0)score += s[0][0][0];} else {score -= c4a * s[1][0][1];score -= c4b * s[1][1][1];score -= c3a * s[2][0][1];score -= c3b * s[2][1][1];score -= c2a * s[3][0][1];score -= c2b * s[3][1][1];if(c4b > 1 || c4b == 1 && c3a > 0)score -= s[1][0][1];}c = self + enemy - c;}return score;}int backtrace(int turn, int limit, int mark[][range], int mm){static Combo vch[10][range*range];if(turn <= 0)return evaluate(board, self);int color = (turn % 2) ? self : enemy;Combo *vc = vch[turn];int cur = 0;int tmpscore;if((clock() - start_time)*1000/CLOCKS_PER_SEC > 960) {tle = 1;return 0;}for(int i=0; i<range; ++i) {for(int j=0; j<range; ++j)if(board[i][j] == 0 && mark[i][j] != 0) {tmpscore = evalutatestep(board, i, j, color);if(tmpscore >= infinite) {if(color == enemy) return -(infinite + turn);else return (infinite + turn);}vc[cur].x = i;vc[cur].y = j;vc[cur].score = tmpscore;cur ++;}}sort(vc, vc + cur);cur = min(cur, limit);int ret = (color == self) ? (-infinite-100) : (infinite+100);for(int i=0; i<cur; ++i) {int nx = vc[i].x, ny = vc[i].y;int bakx[25], baky[25], bakc = 0;board[nx][ny] = color;for(int u=-2; u<=2; ++u) {for(int v=-2; v<=2; ++v)if(onboard(nx+u, ny+v) && mark[nx+u][ny+v] == 0&& abs(u) + abs(v) != 3) {mark[nx+u][ny+v] = 1;bakx[bakc] = nx + u;baky[bakc] = ny + v;bakc ++;}}int score = backtrace(turn - 1, limit, mark, ret);if(color == self && score > ret) {ret = score;} else if(color == enemy && score < ret) {ret = score;}board[nx][ny] = 0;for(int j=0; j<bakc; ++j)mark[bakx[j]][baky[j]] = 0;if(color == self && ret >= mm|| color == enemy && ret <= mm)return ret;if(tle)return 0;}return ret;}
原创粉丝点击