博弈树 c++ 实现五子棋

#include<iostream>
#include<stdbool.h>
#include<vector>
#include<deque>
#include<set>
#include <string.h>
#include <ctime>
#include <cstdlib>
#include<limits.h>
#include<memory>
using namespace std;
char board[15][15];
typedef struct cell {
    int cx;
    int cy;
    struct cell* father;
    char input[15][15];
    int x[15][15];//标记横向是否访问过
    int y[15][15];//标记纵向
    int z[15][15];//标记主对角线
    int h[15][15];//标记次对角线
    int depth;
    int value;
    struct cell*child[225];
}cell;
cell* root, * nextnode;
int ex =1;
int maxdepth =2;
cell*pos_insert[300];//构建环状队列
int top=0,tail=0,coun=0;
string black_form[31] = {
        "10000", "01000", "00100", "00010", "00001",
        "11000", "01100", "00110", "00011", "10100", "01010", "00101", "10010", "01001", "10001"
        "11100", "01110", "00111", "11010", "01101", "10110", "01011", "11001", "10011", "10101",
        "11110", "11101", "11011", "10111", "01111",
};
string white_form[31] = {
        "w0000", "0w000", "00w00", "000w0", "0000w",
        "ww000", "0ww00", "00ww0", "000ww", "w0w00", "0w0w0", "00w0w", "w00w0", "0w00w", "w000w"
        "www00", "0www0", "00www", "ww0w0", "0ww0w", "w0ww0", "0w0ww", "ww00w", "w00ww", "w0w0w",
        "wwww0", "www0w", "ww0ww", "w0www", "0wwww",
};
int score_white[31] = {
        35,35,35,35,35,
        800,800,800,800,800,800,800,800,800,800,
        15000,15000,15000,15000,15000,15000,15000,15000,15000,15000,
        30000,30000,30000,30000,30000
};
int score_black[31] = {
    15,15,15,15,15,
    400,400,400,400,400,400,400,400,400,400,
    14000,14000,14000,14000,14000,14000,14000,14000,14000,14000,
    40000,40000,40000,40000,40000

};
int evaluate(cell* a);//估值函数
bool ismax(cell* a);//判断是否为max节点
void f();//对root和nextnode初始化
cell* creat(cell* a, int x, int y);//生成孩子节点
vector<pair<int, int>>cunchu(cell* a);//把固定下棋区域的节点放入一个容器中
int expand_pos(cell* a);//配合creat生成博弈树
int af_bt(cell* a, int val);//af_bt剪枝(递归)
char qizi(char& s);//判断棋盘上某个节点黑白子或无落子情况
pair<int, int>game();//控制整个游戏
int black(string& s);//某个五元组黑棋的评分
int white(string& s);//某个五元组白棋的评分
void f(){
    root = NULL;
    root = (cell*)malloc(sizeof(cell));
    memcpy(root->input, board, sizeof(board));
    root->father = NULL;
    memset(root->child,NULL,sizeof(225));
    memset(pos_insert,NULL,sizeof(pos_insert));
    root->depth = 0;
    nextnode = NULL;
    root->cx=0;
    root->cy=0;
    memset(root->x,0,sizeof(root->x));
    memset(root->y,0,sizeof(root->y));
    memset(root->z,0,sizeof(root->z));
    memset(root->h,0,sizeof(root->h));
}
cell* creat(cell*b,cell* a, int x, int y) {
    b = NULL;
    b=(cell*)malloc(sizeof(cell));
    b->father = a;
    memset(b->child, NULL, sizeof(225));
    b->depth = a->depth + 1;
    b->cx = x;
    b->cy = y;
    memset(b->x, 0, sizeof(b->x));
    memset(b->y, 0, sizeof(b->y));
    memset(b->z, 0, sizeof(b->z));
    memset(b->h, 0, sizeof(b->h));
    b->value = 0;
    memcpy(b->input, a->input, sizeof(a->input));
    if (ismax(b))
        b->input[x][y] = 'w';
    else
        b->input[x][y] = '1';
    return b;
}
bool ismax(cell* a){
    if (a->depth % 2 != 0)
        return false;
    return true;
}
vector<pair<int, int>>cunchu(cell* a) {//找到待拓展的节点
    int first = 0, i = 0, j = 0;int newboard[15][15], k = 0, w = 0;
    memset(newboard,0,sizeof(newboard));
    int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
    for (i = 0;i < 15;i++)
        for (j = 0;j < 15;j++)
        {
            if (a->input[i][j] != '0')
            {
                first = 1;
                x1 = max(0, i - ex);
                y1 = max(0, j - ex);
                x2 = min(14, i + ex);
                y2 = min(14, j + ex);
                for (w = x1;w <= x2;w++)
                    for (k = y1;k <= y2;k++) {
                        if (a->input[w][k] == '0') {
                            newboard[w][k] = 1;
                        }
                    }
            }
        }
    vector<pair<int, int>>example;
    if (first == 0) {
        example.emplace_back(7, 7);
        return example;
    }
    for (i = 0;i < 15;i++)
        for (j = 0;j < 15;j++) {
            if (newboard[i][j] == 1)
                example.emplace_back(i, j);
        }
    return example;
}
int expand_pos(cell* a) {//生成子树
    vector<pair<int, int>>example = cunchu(a);
    int i=0;
    for (auto n : example) {
        a->child[i]=creat(a->child[i],a, n.first, n.second);
        pos_insert[tail]=a->child[i];
        tail=(tail+1)%300;
        coun++;
        i++;
    }
    return example.size();
}
char qizi(char& s) {
    if (s == '0')
        return '0';
    if (s == '1')
        return '1';
    return 'w';
}
int evaluate(cell* a) {//对局势进行评估
    int i = 0, j = 0, k = 0;
    for (i = 0;i < 15;i++)
        for (j = 0;j < 15;j++) {
            if (j + 4 < 15) {
                if (a->x[i][j] == 1 )//横向该棋子被访问则不在访问
                    continue;
                string s;
                for (k = 0;k < 5;k++)
                {
                    s += qizi(a->input[i][j + k]);
                    a->x[i][j + k] = 1;
                }
                (a->value) += black(s) - white(s);
            }
            if (i + 4 < 15) {
                if (a->y[i][j] == 1 )
                    continue;
                string s;
                for (k = 0;k < 5;k++)
                {
                    s += qizi(a->input[i + k][j]);
                    a->y[i + k][j] = 1;
                }
                (a->value) += black(s) - white(s);
            }
            if (i + 4 < 15 && j + 4 < 15) {
                if (a->z[i][j] == 1 )
                    continue;
                string s;
                for (k = 0;k < 5;k++)
                {
                    s += qizi(a->input[i + k][j + k]);
                    a->z[i + k][j + k] = 1;
                }
                (a->value) += black(s) - white(s);
            }
            if (i + 4 < 15 && j - 4 >= 0) {
                     if (a->h[i][j] == 1 )
                    continue;
                string s;
                for (k = 0;k < 5;k++)
                {
                    s += qizi(a->input[i + k][j - k]);
                    a->h[i + k][j - k] = 1;
                }
                (a->value) += black(s) - white(s);
            }
        }
    return a->value;
}
int black(string& s) {
    int i = 0;
    for (i = 0;i < 31;i++)
        if (s == black_form[i])
            return score_black[i];
    return 0;
}
int white(string& s) {
    int i = 0;
    for (i = 0;i < 31;i++)
        if (s == white_form[i])
            return score_white[i];
    return 0;
}
//---------------------------------//
int af_bt(cell* a, int val) {
    int af = INT_MIN;
    int bt = INT_MAX;
    if (a->depth == maxdepth)
        return evaluate(a);

    if (ismax(a)) {
        for (int i=0;a->child[i]!=NULL;i++) {
            a->value = af_bt(a->child[i], af);
            if (a->value > af)
                af =a->value;
            if (af > bt)
                return af;
        }
        return af;
    }
    if (!ismax(a)) {
        for (int i=0;a->child[i]!=NULL;i++) {
          a->value = af_bt(a->child[i], bt);
            if (a->value < bt)
                bt = a->value;
            if (af > bt)
                return bt;
        }
        return bt;
    }

}
pair<int, int>game() {
    f();//生成当前的对局
    pos_insert[tail]=root;//根节点入队
    tail=(tail+1)%300;
    coun++;
    while (coun!=0) {
        cell* n = pos_insert[top];//取队头元素
        top=(top+1)%300;
        coun--;//队头出队
        if (n->depth < maxdepth)
            int a = expand_pos(n);//进行拓展
    }
      int i=0;
      root->value=af_bt(root,root->value);
        int ma=0;
      for(i=0;root->child[i]!=NULL;++i)
      {if(root->child[i]->value>root->child[ma]->value)
          ma=i;}
    return pair<int, int>(root->child[ma]->cx,root->child[ma]->cy);
}
int main() {
    memset(board, '0', sizeof(board));
    int x, y, n;
    cin >> n;
    for (int i = 0; i < n - 1; i++) {
        cin >> x >> y; if (x != -1) board[x][y] = 'w';    //对方
        cin >> x >> y; if (x != -1) board[x][y] = '1';    //我方
    }
    cin >> x >> y;
    if (n == 1 && x == -1)
    {
        cout << 7 << " " << 7 << endl;
        return 0;
    }
    board[x][y] = 'w';
    pair<int, int>aa = game();
    cout<<aa.first<<' '<<aa.second<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值