五子棋ai半成品

#include <graphics.h>
#include <conio.h>
#include <list>
#include <vector>
constexpr auto A = 1;
constexpr auto B = 2;
constexpr auto N = 3;
using namespace std;
class gobang {
private:
	const short X = 600;
	const short Y = 600;
	short dx = X / 16;
	short dy = Y / 16;
	bool black[16][16];
	bool white[16][16];
	int ab_count[16][16];
	int count[16][16];
	bool black_flag = true;
	unsigned char five[5] = { A,A,A,A,A };//连五
	unsigned char four[6] = { N,A,A,A,A,N };//活四
	unsigned char go_four1[6] = { B,A,A,A,A,N };//冲四
	unsigned char go_four2[5] = { A,A,A,N,A };//冲四
	unsigned char go_four3[5] = { A,A,N,A,A };//冲四
	unsigned char three[5] = { N,A,A,A,N };//活三
	unsigned char jump_three[6] = { N,A,A,N,A,N };//跳活三
	unsigned char sleep_three1[6] = { B,A,A,A,N,N };//眠三系列
	unsigned char sleep_three2[6] = { B,A,A,N,A,N };
	unsigned char sleep_three3[6] = { B,A,N,A,A,N };
	unsigned char sleep_three4[5] = { A,A,N,N,A };
	unsigned char sleep_three5[5] = { A,N,A,N,A };
	unsigned char sleep_three6[7] = { B,N,A,A,A,N,B };
	unsigned char two1[6] = { N,N,A,A,N,N };
	unsigned char two2[5] = { N,A,N,A,N };
	unsigned char two3[6] = { N,A,N,N,A,N };
	unsigned char sleep_two1[6] = { B,A,A,N,N,N };
	unsigned char sleep_two2[6] = { B,A,N,A,N,N };
	unsigned char sleep_two3[6] = { B,A,N,N,A,N };
	unsigned char sleep_two4[5] = { A,N,N,N,A };
	list<COORD> seq;
	list<COORD> left_top;
	list<COORD> right_down;
	bool next_is_black = true;
	COORD legal_node;
	int alphabeta(COORD node,int depth, int alpha, int beta) {
		int a = value(node);
		if (depth == 0) {  return a; }
		if (a > 20)return a;
		int val;
		list<COORD>t = generate_legal_node();
		if (next_is_black) {
			black[node.X][node.Y] = true;
		}
		else {
			white[node.X][node.Y] = true;
		}next_is_black = !next_is_black;
		seq.push_back(node);
		put_area(node.X, node.Y);
		COORD point;
		while (t.empty() == false) {
			if (beta <= alpha)break;
			point = t.front();
			t.pop_front();
			val = alphabeta(point, depth - 1, alpha, beta);
			if (depth % 2 == 0) {
				alpha = max(val, alpha);
			}
			else {
				beta = min(val, beta);
			}
			}
		if (next_is_black) {
			white[node.X][node.Y] = false;
		}
		else {
			black[node.X][node.Y] = false;
		}next_is_black = !next_is_black;
		left_top.pop_back();
		right_down.pop_back();
		seq.pop_back();
		if (depth % 2 == 0) {
				//printf("%d ",alpha);
				return alpha;
			}
			else {
				//printf("%d ",beta); 
				return beta;
			}
	}
	
	list<COORD> generate_legal_node() {
		init_count(); table_count(next_is_black);
		COORD lf = left_top.back(); lf.X -= 2; lf.Y -= 2;
		COORD rd = right_down.back(); rd.X += 2; rd.Y += 2;
		list<COORD> tmp; 
		set_valid(lf); set_valid(rd);
		for (short x = left_top.back().X; x <= right_down.back().X; x++) {
			for (short y = left_top.back().Y; y <= right_down.back().Y; y++) {
				if (black[x][y] == false && white[x][y] == false&&count[x][y]>8)
				{
					tmp.push_back({ x,y });
				}
			}
		}
		for (short x = lf.X; x <= rd.Y; x++) {
			for (short y = lf.Y; y <= rd.Y; y++) {
				if (black[x][y] == false && white[x][y] == false&&count[x][y] > 8)
				{
					if((x > right_down.back().X||x<left_top.back().X)&&(y > right_down.back().Y || y < left_top.back().Y)&&count[x][y]>=8)
					tmp.push_back({ x,y });
				}
			}
		}return tmp;
	}
	int value(COORD tmp) {
		int a=
			47 * check_five({ tmp.X,tmp.Y }, next_is_black)
			+ 23 * check_four({ tmp.X,tmp.Y }, next_is_black)
			+ 11 * check_go_four({ tmp.X,tmp.Y }, next_is_black)
			+ 11 * check_three({ tmp.X,tmp.Y }, next_is_black)
			+ 5 * check_sleep_three({ tmp.X,tmp.Y }, next_is_black)
			+ 5 * check_two({ tmp.X,tmp.Y }, next_is_black)
			+ 2 * check_sleep_two({ tmp.X,tmp.Y }, next_is_black)
			//+ 1100 * check_skip_two({ tmp.X,tmp.Y }, next_is_black)
			+ 46 * check_five({ tmp.X,tmp.Y }, !next_is_black)
			+ 22 * check_four({ tmp.X,tmp.Y }, !next_is_black)
			+ 10 * check_go_four({ tmp.X,tmp.Y }, !next_is_black)
			+ 10 * check_three({ tmp.X,tmp.Y }, !next_is_black)
			+ 4 * check_sleep_three({ tmp.X,tmp.Y }, !next_is_black)
			+ 4 * check_two({ tmp.X,tmp.Y }, !next_is_black)
			+ 1 * check_sleep_two({ tmp.X,tmp.Y }, !next_is_black);
			//+ 1000 * check_skip_two({tmp.X,y},!next_is_black);
			
			if (next_is_black)return a;
			else return -a;
	}
	void print_count() {
		for (int i = 0; i <= 14; i++) {
			for (int j = 0; j <= 16; j++) {
				printf("%3d ",ab_count[j][i]);
			}printf("\n");
		}
	}
	void AI_draw_black() {
		if (next_is_black) {
			table_count(true);
			//my_new_count();
			printf("\n\n\n");
			print_count();
			COORD tmp = max_table_ab();
			AI_draw(tmp.X, tmp.Y);
		}
	}
	void my_new_count() {
		init_ab(); table_count(next_is_black);
		COORD lf = left_top.back(); lf.X -= 3; lf.Y -= 3;
		COORD rd = right_down.back(); rd.X += 3; rd.Y += 3;
		set_valid(lf); set_valid(rd);
		list<COORD>m;
		for (short x = lf.X; x <= rd.Y; x++) {
			for (short y = lf.Y; y <= rd.Y; y++) {
				if (count[x][y] > 8)
					m.push_back({ x,y });
				if (black[x][y] || white[x][y])ab_count[x][y] = -33;
			}
		}
		while (m.empty() == false) {
			ab_count[m.back().X][m.back().Y] = alphabeta({ m.back().X,m.back().Y }, 8, -99999, 99999);
			m.pop_back();
		}
	}


	void init_board() {
		for (short i = 0; i < 16; i++) {
			for (short j = 0; j < 16; j++) {
				black[i][j] = false;
				white[i][j] = false;
			}
		}
	}
	void init_count() {
		for (short i = 0; i < 16; i++) {
			for (short j = 0; j < 16; j++) {
				count[i][j] = 0;
			}
		}
	}
	void init_ab() {
		for (short i = 0; i < 16; i++) {
			for (short j = 0; j < 16; j++) {
				ab_count[i][j] = -1;
			}
		}
	}
	void init() {
		setbkcolor(0xA9A9A9);
		cleardevice();
		setlinecolor(BLACK);
		for (short i = 1; i <= 15; i++) {
			line(dx / 2, i*dy, 15 * dx + dx / 2, i*dy);
			line(i*dx, dy / 2, i*dx, 15 * dy + dy / 2);
		}
		next_is_black = true;
		init_board();
		//root.a =(tree_node *)malloc(sizeof(tree_node));
		while (left_top.empty() == false)left_top.pop_back();
		while (right_down.empty() == false)right_down.pop_back();
		while (seq.empty() == false)seq.pop_back();
		left_top.push_back({ -1,-1 });
		right_down.push_back({ -1,-1 });
		int a;
		scanf_s("%d", &a);
		if (a)black_flag = true;
		else black_flag = false;
		if (black_flag)AI_draw(7, 7);
		FlushMouseMsgBuffer();
	}
	void AI_draw(short x, short y) {
		draw_black(dx*(x + 1), dy*(y + 1)) || draw_white(dx*(x + 1), dy*(y + 1));
	}

	void AI_draw_white() {
		if (!next_is_black) {
			table_count(false);
			COORD tmp = max_table();
			AI_draw(tmp.X, tmp.Y);
			
		};
	}
	void set_valid(COORD &x) {
		if (x.X < 0)x.X = 0;
		if (x.X > 14)x.X = 14;
		if (x.Y < 0)x.Y = 0;
		if (x.Y > 14)x.Y = 14;
	}
	//t代表是连t,
	unsigned char change_to_ABN(COORD x, bool tmpA[16][16], bool tmpB[16][16]) {
		if (x.X < 0 || x.Y < 0 || x.Y>14 || x.X>14)return 7;
		if (tmpA[x.X][x.Y])return A;
		if (tmpB[x.X][x.Y])return B;
		return N;
	}
	bool reverse_is_same(unsigned char arr[], short n) {
		for (int i = 0; i < n; i++) {
			if (arr[i] != arr[n - i - 1])return false;
		}return true;
	}
	short check(COORD x, unsigned char arr[], short n,bool tmpA[16][16],bool tmpB[16][16]) {
		short count = 0;
		bool re = reverse_is_same(arr, n);
		bool t = tmpA[x.X][x.Y];
		if (t||tmpB[x.X][x.Y])
			return 0;
		tmpA[x.X][x.Y] = true;
		for (short i = 1; i <=n; i++) {
			bool flag[8] = { 1,1,1,1,1,1,1,1 };
			for (short j = 0; j < n; j++) {
				//顺向
				if (change_to_ABN({ x.X - n + i+j,x.Y }, tmpA, tmpB) != arr[j]) {flag[0] = false; }
				if (change_to_ABN({ x.X,x.Y-n+i+j}, tmpA, tmpB) != arr[j])flag[1] = false;
				if (change_to_ABN({ x.X-n+i+j,x.Y - n + i+j }, tmpA, tmpB) != arr[j])flag[2] = false;
				if (change_to_ABN({ x.X - n + i+j,x.Y + n - i-j }, tmpA, tmpB) != arr[j])flag[3] = false;
				//反向,如果对称就不反向
				if (re==false) {
					if (change_to_ABN({ x.X - n + i + j,x.Y }, tmpA, tmpB) != arr[n - j - 1])flag[4] = false;
					if (change_to_ABN({ x.X,x.Y - n + i + j }, tmpA, tmpB) != arr[n - j - 1])flag[5] = false;
					if (change_to_ABN({ x.X - n + i + j,x.Y - n + i + j }, tmpA, tmpB) != arr[n - j - 1])flag[6] = false;
					if (change_to_ABN({ x.X - n + i + j,x.Y + n - i - j }, tmpA, tmpB) != arr[n - j - 1])flag[7] = false;
				}
			}
			short k;
			if (re)k = 4;
			else k = 8;
			for (short i = 0; i < k; i++) {
				if (flag[i])count++;
			}
		}
		tmpA[x.X][x.Y] = t;
		return count;
	}
	short check_five(COORD x, bool tmp_b) {
		if (tmp_b) {return check(x, five, 5, black, white);}
		else {return check(x, five, 5, white,black);}
	}
	short check_go_four(COORD x, bool tmp_b) {
		short count = 0;
		if (tmp_b) { 
			count=count+check(x, go_four3, 5, black, white); 
			count = count + check(x, go_four1, 6, black, white);
			count = count + check(x, go_four2, 5, black, white);
		}
		else {
			count = count + check(x, go_four3, 5, white,black);
			count = count + check(x, go_four1, 6, white, black);
			count = count + check(x, go_four2, 5, white, black);
		}return count;
	}
	short check_four(COORD x, bool tmp_b) {
		if (tmp_b) { return check(x, four, 6,black,white ); }
		else { return check(x, four, 6, white, black); }
	}
	short check_three(COORD x, bool tmp_b) {
		if (tmp_b) { return check(x, three, 5, black, white); }
		else { return check(x, three, 5, white, black); }
	}
	short check_jump_three(COORD x, bool tmp_b) {
		if (tmp_b) { return check(x, jump_three, 6, black, white); }
		else { return check(x, jump_three, 6, white, black); }
	}
	short check_sleep_three(COORD x, bool tmp_b) {
		short count = 0;
		if (tmp_b) { 
			count = count + check(x, sleep_three1, 6, black, white);
			count = count + check(x, sleep_three2, 6, black, white);
			count = count + check(x, sleep_three3, 6, black, white);
			count = count + check(x, sleep_three4, 5, black, white);
			count = count + check(x, sleep_three5, 5, black, white);
			count = count + check(x, sleep_three6, 7, black, white);
		}
		else { 
			count = count + check(x, sleep_three1, 6, white, black);
			count = count + check(x, sleep_three2, 6, white, black);
			count = count + check(x, sleep_three3, 6, white, black);
			count = count + check(x, sleep_three4, 5, white, black);
			count = count + check(x, sleep_three5, 5, white, black);
			count = count + check(x, sleep_three6, 7, white, black);
		
		}return count;
	}
	short check_two(COORD x, bool tmp_b) {
		short count = 0;
		if (tmp_b) {
			count = count + check(x, two1, 6, black, white);
			count = count + check(x, two2, 5, black, white);
			count = count + check(x, two3, 6, black, white);
		}
		else {
			count = count + check(x, two1, 6, white, black);
			count = count + check(x, two2, 5, white, black);
			count = count + check(x, two3, 6, white, black);
		}return count;
	}
	short check_sleep_two(COORD x, bool tmp_b) {
		short count = 0;
		if (tmp_b) {
			count = count + check(x, sleep_two1, 6, black, white);
			count = count + check(x, sleep_two2, 6, black, white);
			count = count + check(x, sleep_two3, 6, black, white);
			count = count + check(x, sleep_two4, 5, black, white);
		}
		else {
			count = count + check(x, sleep_two1, 6, white, black);
			count = count + check(x, sleep_two2, 6, white, black);
			count = count + check(x, sleep_two3, 6, white, black);
			count = count + check(x, sleep_two4, 5, white, black);
		}return count;
	}
	

	bool draw_black(short x, short y) {
		if (next_is_black&&x&&y&&x<=15*dx&&y<=15*dy) {
			put_area(x/dx-1,y/dy-1);
			setfillcolor(BLACK);
			solidcircle(x, y, dx / 2);
			next_is_black = false;
			seq.push_back({ x / dx - 1,y / dy - 1 });
			set_board({ x / dx - 1,y / dy - 1 }, true, black);
			return true;
		}return false;
	}

	void put_area(short x,short y) {//更新判断边界;
		if (left_top.back().X == -1) {
			left_top.push_back({ x,y });
			right_down.push_back({x,y});
		}
		else {
			COORD tmp = left_top.back();
			if (x < left_top.back().X)tmp.X = x;
			if (y < left_top.back().Y)tmp.Y = y;
			left_top.push_back(tmp);
			tmp = right_down.back();
			if (x > right_down.back().X)tmp.X = x;
			if (y > right_down.back().Y)tmp.Y = y;
			right_down.push_back(tmp);
		}
	}
	bool draw_white(short x, short y) {
		if (next_is_black == false && x&&y&&x <= 15 * dx&&y <= 15 * dy) {
			setfillcolor(WHITE);
			solidcircle(x, y, dx / 2);
			put_area(x / dx - 1, y / dy - 1);
			seq.push_back({ x / dx - 1,y / dy - 1 });
			next_is_black = true;
			set_board({ x / dx - 1,y / dy - 1 }, true, white);
			return true;
		}return false;
	}
	void set_board(COORD x,bool t,bool borw[16][16]) {
		borw[x.X][x.Y] = t;
	}
	bool putdown(COORD x) {
		if (black[x.X][x.Y]||white[x.X][x.Y]) {
			return false;
		}return true;
	}
	void back() {
		if (seq.empty() == false) {
			setfillcolor(0xA9A9A9);
			COORD t = seq.back();
			black[t.X][t.Y] = false;
			white[t.X][t.Y] = false;
			t.X = (t.X+1)*dx; t.Y = (t.Y+1)*dy;
			seq.pop_back();
			solidrectangle(t.X-dx/2,t.Y-dy/2,t.X+(dx+1)/2,t.Y+(dy+1)/2);
			setlinecolor(BLACK);
			line(t.X - dx/2, t.Y, t.X + (dx + 1)/2, t.Y);
			line(t.X,t.Y-dy/2,t.X,t.Y+(dy+1)/2);
			right_down.pop_back();
			left_top.pop_back();
			next_is_black = !next_is_black;
		}
	}
	void draw(short x,short y) {
		short gap = X / 16;
		short real_x=(x+gap/2)/gap*gap;
		short real_y=(y+gap/2)/gap*gap;
		if (putdown({ real_x /gap - 1,real_y / gap - 1 })) {
			draw_black(real_x, real_y)||draw_white(real_x, real_y); 
		}
	}
	int pow(int x, int y) {
		int sum=0;
		for (int i = 1; i <= y; i++) {
			sum = sum + i * x;
		}return sum;
	}
	COORD max_table() {
		int max = -99999999; COORD tmp;
		COORD lf = left_top.back(); lf.X -= 2; lf.Y -= 2;
		COORD rd = right_down.back(); rd.X += 2; rd.Y += 2;
		set_valid(lf); set_valid(rd);
		for (short x = lf.X; x <= rd.Y; x++) {
			for (short y = lf.Y; y <= rd.Y; y++) {
				//printf("%d",count[x][y]);
					if (count[x][y] > max) {
						max = count[x][y];
						tmp.X = x; tmp.Y = y;
					}
			}
		}return tmp;
	}
	COORD max_table_ab() {
		int max = -99999999; COORD tmp;
		COORD lf = left_top.back(); lf.X -= 3; lf.Y -= 3;
		COORD rd = right_down.back(); rd.X += 3; rd.Y += 3;
		set_valid(lf); set_valid(rd);
		for (short x = lf.X; x <= rd.Y; x++) {
			for (short y = lf.Y; y <= rd.Y; y++) {
				//printf("%d",count[x][y]);
				if (ab_count[x][y] > max) {
					max = ab_count[x][y];
					tmp.X = x; tmp.Y = y;
				}
			}
		}return tmp;
	}
	void end() {
		if (next_is_black == false) {
			set_board(seq.back(), false, black);
			if (check_five(seq.back(), true) > 0) { 
				
				printf("胜负己分");
				Sleep(2000);
				init();
				FlushMouseMsgBuffer();
			}
			else { set_board(seq.back(), true, black); }
		}
		else {
			set_board(seq.back(), false, white);
			if (check_five(seq.back(), false) > 0) { 
				printf("胜负己分");
				Sleep(2000);
				init(); FlushMouseMsgBuffer();
			}
			else { set_board(seq.back(), true, white); }
		}
		
	}


	void table_count(bool b) {
		init_count();
		COORD lf = left_top.back(); lf.X -= 3; lf.Y -= 3;
		COORD rd = right_down.back(); rd.X += 3; rd.Y += 3;
		set_valid(lf); set_valid(rd);
		for (short x = lf.X ; x <= rd.Y;x++) {
			for (short y = lf.Y ; y <=rd.Y ; y++) {
				count[x][y] =
					1530 * check_five({ x,y }, b)
					+ 270 * check_four({ x,y }, b)
					+ 30 * check_go_four({ x,y }, b)
					+ 30 * check_three({ x,y }, b)
					+ 5 * check_sleep_three({ x,y }, b)
					+ 5 * check_two({ x,y }, b)
					+ 2 * check_sleep_two({ x,y }, b)
					//+ 1100 * check_skip_two({ x,y }, b)
					+ 510 * check_five({ x,y }, !b)
					+ 90 * check_four({ x,y }, !b)
					+ 10 * check_go_four({ x,y }, !b)
					+ 10 * check_three({ x,y }, !b)
					+ 4 * check_sleep_three({ x,y }, !b)
					+ 4 * check_two({ x,y }, !b)
					+ 1 * check_sleep_two({ x,y }, !b)
					//+ 1000 * check_skip_two({x,y},!b);
					;
			}
		}
	}

public:void test() {
		initgraph(600, 600, SHOWCONSOLE);
		setbkcolor(0xA9A9A9);
		cleardevice();
		init();
		MOUSEMSG m;		// 定义鼠标消息
		while (true)
		{
			// 获取一条鼠标消息
			m = GetMouseMsg();
			setbkcolor(WHITE);
			switch (m.uMsg)
			{
			case WM_LBUTTONDOWN:
				// 如果点左键的同时按下了 
				if (m.x>=dx&&m.x<=dx*15&&m.y>=dy&&m.y<=15*dy) {
					draw(m.x, m.y); end();
					if (black_flag)AI_draw_black();
					else AI_draw_white(); 
					end();
					//printf("%d %d %d\n", seq.size(), left_top.size(), right_down.size());
				}
				break;
			case WM_RBUTTONDOWN:
				back();
			default:break;
			}
		}
	}
};
int main()
{
	// 初始化图形窗口
	gobang a;
	a.test();
	// 关闭图形窗口
	closegraph();
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值