#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <ctime>
using namespace std;

int s[5][5] = {}; // 网格上的小盒子 0 无 -1 电脑 +1 玩家 下同
int m[5][5] = {}; // 网格上的中盒子
int l[5][5] = {}; // 网格上的大盒子
int p1[4] = {0, 2, 2, 2}, p2[4] = {0, 2, 2, 2}; // 电脑和玩家的①小②中③大盒个数
int p[5][5] = {}; // 当前网格被谁占据
int px[2][5], py[2][5], bx[3], by[3];
struct node {
    int x, y, h;
} aa[15];

bool cmp(node a, node b) { return a.h > b.h; }

// 输出当前网格
void showSquare()
{
    // 计算当前网格被谁的盒子占据
    int a[5][5] = {}; // 当前网格上的盒子 + - 表示角色 数字表示箱子大小
    for (int i = 1; i <= 3; i++)
    {
        for (int j = 1; j <= 3; j++)
        {
            if (l[i][j] != 0)
            {
                a[i][j] = l[i][j] * 3;
            }
            else if (m[i][j] != 0)
            {
                a[i][j] = m[i][j] * 2;
            }
            else
            {
                a[i][j] = s[i][j] * 1;
            }
        }
    }
    // 绘制网格
    string border[4] = {"", "┌────┬────┬────┐", "├────┼────┼────┤", "├────┼────┼────┤"};
    for (int i = 1; i <= 3; i++)
    {
        cout << border[i] << endl;
        cout << "│";
        for (int j = 1; j <= 3; j++)
        {
            if (a[i][j] > 0)
            {
                cout << " +" << a[i][j] << " │";
            }
            else if (a[i][j] < 0)
            {
                cout << " " << a[i][j] << " │";
            }
            else
            {
                cout << "    │";
            }
        }
        cout << endl;
    }
    cout << "└────┴────┴────┘" << endl;
}

// 对行、列、对角线求和,若和为3则玩家胜利返回1,若和为-3则电脑胜利返回-1,否则返回0继续游戏
int findWinner()
{
    // 计算当前网格被谁占据,只记录角色-1 +1,不记录箱子大小
    int b[5][5] = {}; // 当前网格被谁占据
    for (int i = 1; i <= 3; i++)
    {
        for (int j = 1; j <= 3; j++)
        {
            if (l[i][j] != 0)
            {
                b[i][j] = l[i][j];
            }
            else if (m[i][j] != 0)
            {
                b[i][j] = m[i][j];
            }
            else
            {
                b[i][j] = s[i][j];
            }
        }
    }
    // 检查行
    for (int i = 1; i <= 3; i++)
    {
        int sum = 0;
        for (int j = 1; j <= 3; j++)
        {
            sum += b[i][j];
        }
        if (sum == 3) return 1;
        if (sum == -3) return -1;
    }
    // 检查列
    for (int j = 1; j <= 3; j++)
    {
        int sum = 0;
        for (int i = 1; i <= 3; i++)
        {
            sum += b[i][j];
        }
        if (sum == 3) return 1;
        if (sum == -3) return -1;
    }
    // 检查对角线
    int diag1 = 0, diag2 = 0;
    for (int i = 1; i <= 3; i++)
    {
        diag1 += b[i][i];
        diag2 += b[i][4-i];
    }
    if (diag1 == 3 || diag2 == 3) return 1;
    if (diag1 == -3 || diag2 == -3) return -1;
    return 0;
}

// 角色q把size箱子放到x行y列的位置
bool place(int x, int y, int size, int q)
{
    if (x < 1 || x > 3 || y < 1 || y > 3) return false;
    if (q == -1)
    {
        printf("电脑试图在(%d,%d)下%d\n", x, y, size);
    }
    if (size == 3)
    {
        if (l[x][y] != 0) return false;
        l[x][y] = q;
    }
    if (size == 2)
    {
        if (l[x][y] != 0 || m[x][y] != 0) return false;
        m[x][y] = q;
    }
    if (size == 1)
    {
        if (l[x][y] != 0 || m[x][y] != 0 || s[x][y] != 0) return false;
        s[x][y] = q;
    }
    return true;
}

// 角色q把size箱子从x1行y1列转移到x2行y2列
bool move(int x1, int y1, int x2, int y2, int size, int q)
{
    if (x1 < 1 || x1 > 3 || y1 < 1 || y1 > 3) return false;
    if (x2 < 1 || x2 > 3 || y2 < 1 || y2 > 3) return false;
    if (q == -1)
    {
        cout << "电脑试图将(" << x1 << "," << y1 << ")" << "转移到(" << x2 << "," << y2 << ")" << endl;
    }
    if (size == 3)
    {
        if (l[x1][y1] != q || l[x2][y2] != 0) return false;
        l[x1][y1] = 0;
        l[x2][y2] = q;
    }
    if (size == 2)
    {
        if (l[x1][y1] != 0 || l[x2][y2] != 0 || m[x1][y1] != q || m[x2][y2] != 0) return false;
        m[x1][y1] = 0;
        m[x2][y2] = q;
    }
    if (size == 1)
    {
        if (l[x1][y1] != 0 || l[x2][y2] != 0 || m[x1][y1] != 0 || m[x2][y2] != 0 || s[x1][y1] != q || s[x2][y2] != 0) return false;
        s[x1][y1] = 0;
        s[x2][y2] = q;
    }
    return true;
}
int winning(int x)
{
    // 计算当前网格被谁占据
    for (int i = 1; i <= 3; i++)
    {
        for (int j = 1; j <= 3; j++)
        {
            if (l[i][j] != 0) p[i][j] = l[i][j];
            else if (m[i][j] != 0) p[i][j] = m[i][j];
            else p[i][j] = s[i][j];
        }
    }
    int a = 0;
    if (x == 1) a = 1;
    for (int i = 1; i <= 3; i++)
        px[a][i] = py[a][i] = 0;
    bx[a] = by[a] = 0;
    for (int i = 1; i <= 3; i++)
        for (int j = 1; j <= 3; j++)
            if (p[i][j] == x)
            {
                px[a][i]++;
                py[a][j]++;
                if (i == j) bx[a]++;
                if (i + j == 4) by[a]++;
            }
    int s = bx[a] >= 2;
    s += by[a] >= 2;
    for (int i = 1; i <= 3; i++)
    {
        s += px[a][i] >= 2;
        s += py[a][i] >= 2;
    }
    return s;
}

int fill(int x, int y, int size) //电脑至少用size大小的棋子占领x行y列
{
    // cout << "电脑试图在" <<  x << ',' << y << "下棋" << endl;
    if (l[x][y] == 1) return 0;
    for (int k = size; k <= 3; k++)
        if (p1[k] && place(x, y, k, -1))
        {
            p1[k]--;
            return 1;
        }
    if (s[x][y] == 1) size = max(size, 2);
    if (m[x][y] == 1) size = 3;
    if (size == 1)
    {
        for (int i = 1; i <= 3; i++)
            for (int j = 1; j <= 3; j++)
                if (s[i][j] == -1 && move(i, j, x, y, 1, -1))
                {
                    if (winning(1) == 0)
                        return 1;
                    move(x, y, i, j, 1, -1);
                }
    }
    if (size <= 2)
    {
        for (int i = 1; i <= 3; i++)
            for (int j = 1; j <= 3; j++)
                if (m[i][j] == -1 && move(i, j, x, y, 2, -1))
                {
                    if (winning(1) == 0)
                        return 1;
                    move(x, y, i, j, 2, -1);
                }
    }
    if (size <= 3)
    {
        for (int i = 1; i <= 3; i++)
            for (int j = 1; j <= 3; j++)
                if (l[i][j] == -1 && move(i, j, x, y, 3, -1))
                {
                    if (winning(1) == 0)
                        return 1;
                    move(x, y, i, j, 3, -1);
                }
    }
    return 0;
}
void computer()
{
    if (winning(-1) > 0)
    {
        cout << "电脑认为自己快赢了" << endl;
        for (int i = 1; i <= 3; i++)
            for (int j = 1; j <= 3; j++)
                if (p[i][j] != -1 && (px[0][i] == 2 || py[0][j] == 2))
                {
                    if (fill(i, j, 1))
                        return;
                }
        if (bx[0] == 2)
        {
            for (int i = 1; i <= 3; i++)
                if (p[i][i] != -1 && fill(i, i, 1))
                    return ;
        }
        if (by[0] == 2)
        {
            for (int i = 1; i <= 3; i++)
                if (p[i][4 - i] != -1 && fill(i, 4 - i, 1))
                    return ;
        }
    }
    if (winning(1) > 0)
    {
        cout << "电脑认为你快赢了" << endl;
        int cnt = 0;
        for (int i = 1; i <= 3; i++)
            for (int j = 1; j <= 3; j++)
            {
                int w = (px[1][i] == 2) + (py[1][j] == 2);
                if (i == j && bx[1] == 2) w++;
                if (i + j == 4 && by[1] == 2) w++;
                if (w == 0) continue;
                aa[++cnt].x = i; aa[cnt].y = j; aa[cnt].h = w;
            }
        sort(aa + 1, aa + cnt + 1, cmp);
        for (int i = 1; i <= cnt; i++)
        {
            // printf("电脑想在%d,%d阻止你,w=%d\n",aa[i].x,aa[i].y,aa[i].h);
            if (p2[3] > 0)
            {
                if (fill(aa[i].x, aa[i].y, 3))
                    return ;
                else continue;
            }
            if (p2[2] > 0)
            {
                if (fill(aa[i].x, aa[i].y, 2))
                    return ;
                else continue;
            }
            if (p2[1] > 0)
            {
                if (fill(aa[i].x, aa[i].y, 1))
                    return ;
                else continue;
            }
        }
    }
    if (l[2][2] == 0)
    {
        cout << "电脑决定占领中心" << endl;
        if (p1[3] > 0) {
            p1[3]--;
            place(2, 2, 3, -1);
            return;
        }
        if (fill(2, 2, 3)) return ;
        if (fill(2, 2, 2)) return ;
    }
    int cnt = 0;
    for (int i = 1; i <= 3; i++)
        for (int j = 1; j <= 3; j++)
            if (p[i][j] != -1)
            {
                if (l[i][j] > 0) continue;
                int t = p[i][j];
                p[i][j] = -1;
                aa[++cnt].x = i;
                aa[cnt].y = j;
                aa[cnt].h = winning(-1);
                p[i][j] = t;
            }
    sort(aa + 1, aa + cnt + 1, cmp);
    int j = 1;
    for (int i = 1; i <= cnt; i++)
    {
        if (aa[i].h == aa[j].h)
            j = i;
        else break;
    }
    j = rand() % j + 1;
    if (fill(aa[j].x, aa[j].y, 1))
        return;
    for (int i = 1; i <= cnt; i++)
        if (fill(aa[i].x, aa[i].y, 1))
            return;
}
int game()
{
    srand((unsigned int)time(NULL));
    while (true)
    {
        cout << "请选择 ① 放一个盒子 还是 ② 移动一个盒子 (输入数字)" << endl;
        int choice, size, x1, y1, x2, y2;
        cin >> choice;
        if (choice == 1)
        {
            cout << "你现在有盒子 小:" << p2[1] << " 中:" << p2[2] << " 大:" << p2[3] << endl;
            cout << "请选择盒子的大小 ① 小 ② 中 ③ 大 (输入数字)" << endl;
            cin >> size;
            if (size > 3 || size < 1) {cout << "非法输入" << endl; continue;}
            if (p2[size] <= 0) {cout << "盒子没了" << endl; continue;}
            cout << "请输入放置的位置(输入两个整数,如:1 1)" << endl;
            cin >> x1 >> y1;
            if (!place(x1, y1, size, 1)) {cout << "放置失败" << endl; continue;}
            cout << "放置成功" << endl;
            p2[size]--;
            showSquare();
        }
        else if (choice == 2)
        {
            cout << "请输入移走的位置(输入两个整数,如:1 1)" << endl;
            cin >> x1 >> y1;
            cout << "请输入放置的位置(输入两个整数,如:1 1)" << endl;
            cin >> x2 >> y2;
            // 判断移动的箱子
            if (l[x1][y1] == 1) size = 3;
            else if (m[x1][y1] == 1 && l[x1][y1] == 0) size = 2;
            else if (s[x1][y1] == 1 && l[x1][y1] == 0 && m[x1][y1] == 0) size = 1;
            else {cout << "没有可以移动的盒子" << endl; continue;}
            if (!move(x1, y1, x2, y2, size, 1)) {cout << "移动失败" << endl; continue;}
            showSquare();
        }
        else continue;
        int winner = findWinner();
        if (winner != 0)
        {
            return winner;
        }
        computer();
        cout << "电脑下棋" << endl;
        showSquare();
        winner = findWinner();
        if (winner != 0)
        {
            return winner;
        }
    }
}

void showWinner(int winner)
{
    if (winner == 1)
    {
        cout << "玩家胜利" << endl;
    }
    else
    {
        cout << "电脑胜利" << endl;
    }
}

void intro()
{
    cout << "玩家和电脑各拥有大中小号盒子各2个," << endl;
    cout << "双方轮流在九宫格的棋盘中放入或移动一个盒子,每个盒子都可盖住任意比他小的盒子。" << endl;
    cout << "若你方团队的盒子率先在棋盘上连成一条直线则挑战成功,否则挑战失败。" << endl;
    cout << "用正数表示玩家的盒子,负数表示电脑的盒子,1、2、3表示盒子的小中大。" << endl;
    cout << "开始吧!" << endl;
    showSquare();
}

int main()
{
    intro();
    int winner = game();
    showWinner(winner);
    return 0;
}