#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();
}