五子棋(Gomoku)博弈程序

// 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_PERF
	LARGE_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;
#endif

	if(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_PERF
					break_at = i + 1;
#endif
					if((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_PERF
	QueryPerformanceCounter(&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;
#else
	cout << 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]++;
					} else
						cnt[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]++;
					} else
						cnt[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]++;
						else
							cnt[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]++;
						else
							cnt[2][2]++;
					} else
						cnt[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]++;
					} else
						cnt[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++;
								else
									c3b++;
							} else if(bclose[d] == 1 && jump[d] == 1) {
								if(onboard(x, y) && b[x][y] == 0) 
									c3a++;
								else
									c3b++;
							} 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;
}

你可能感兴趣的:(c,struct,Integer)