三角点格棋

本文介绍了将三角点格棋从在线判断题转化为控制台程序的过程,包括使用AlphaBeta搜索和UCT算法的两个版本。AlphaBeta搜索版按照后手必胜策略编写,基本无误;而UCT版存在一些问题,需要优化。作者计划重新编写UCT算法的实现。
摘要由CSDN通过智能技术生成

将之前的一道OJ题(我博客里的博弈类有篇文章就是http://blog.csdn.net/qq_38597315/article/details/75007297)改成一款控制台程序,棋的界面是以前某个学长写的,直接套就好(虽然摸索协议挺烦人的。。。)。
这里给出两个版本,一个是使用AlphaBeta搜索版(完成于去年7月集训期间),一个是使用UCT算法版(由于不可抗因素,完成于去年10月份左右),由于三角点格棋已由之前的OJ结果证明后手必胜,所以第一个版本就是按后手必胜写的,基本上没有什么问题,第二个版本是UCT部分写的有问题,很智障。。。同时也没有加任何优化。。。感觉要重写个UCT的板子

先上第一个AlphaBeta版

#define _CRT_SECURE_NO_WARNINGS    
#include<windows.h>
#include<cstring>
#include <cstdio>
#include <cstdlib>
#include<iostream>
#include<string>
using namespace std;

//控制颜色输出  1-红,0-白,2-蓝
int Map[20];//控制18条边
int Tir[10];//控制9个三角形
int Edge_Map[11][11];//标记边是否选过,1-选过,0-未选过

// 保存每条边代表的数字
int StrMap[11][11] = {
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    { 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 },
    { 0, 0, 0, 1, 3, 5, 0, 0, 0, 0, 0 },
    { 0, 2, 1, 0, 0, 6, 8, 0, 0, 0, 0 },
    { 0, 0, 3, 0, 0, 4, 0, 9, 11,0, 0 },
    { 0, 0, 5, 6, 4, 0, 7, 0, 12,14,0 },
    { 0, 0, 0, 8, 0, 7, 0, 0, 0, 15,17 },
    { 0, 0, 0, 0, 9, 0, 0, 0, 10,0, 0 },
    { 0, 0, 0, 0, 11,12,0, 10,0, 13, 0 },
    { 0, 0, 0, 0, 0, 14,15,0, 13, 0, 16 },
    { 0, 0, 0, 0, 0, 0, 17,0, 0, 16,0 },
};
// 保存每个单位三角形代表的数字
int tri[9] = { 7, 56, 98, 448, 3584, 6160, 28672, 49280, 229376 };
int end_state = (1 << 18) - 1; // 终结状态 2^18 - 1 ,即所有边均被填充
int inf = (1 << 20);

int next_state(int cur_state, int edge, int *cnt)
{
    int i;
    int new_state = (cur_state | edge); // 当前局面并上一条边形成新局面
    for (i = 0; i < 9; i++) // 如果新局面能形成一个新的单位三角形,则 cnt++
        if (((cur_state & tri[i]) != tri[i]) && ((new_state & tri[i]) == tri[i]))
            (*cnt)++;
    return new_state;
}

int alpha_beta(int player, int cur_state, int alpha, int beta, int ca, int cb)
{
    int remain;
    // 如 A 得到 5 分以上则 A 赢
    // 如 B 得到 5 分以上则 A 输
    if (ca >= 5) return 1;
    if (cb >= 5) return -1;
    remain = ((~cur_state) & end_state); // 计算剩余可走的边
    if (player) // A 走
    {
        while (remain) // 有可走边
        {
            int move = (remain & (-remain)); // 选择一条可走边
            int ta = ca;
            int val;
            // A 填了边后形成新的局面
            int new_state = next_state(cur_state, move, &ta);
            if (ta > ca) // 如果 A 得分了,则 A 继续填一条边
                val = alpha_beta(player, new_state, alpha, beta, ta, cb);
            else // 否则轮到 B 填
                val = alpha_beta(1 - player, new_state, alpha, beta, ca, cb);
            if (val > alpha)
                alpha = val;
            if (alpha >= beta)
                return alpha;
            remain -= move; // 把边 move 从剩余可选边 remain 中移除
        }
        return alpha;
    }
    else // B 走
    {
        while (remain)
        {
            int move = (remain & (-remain));
            int tb = cb;
            int val;
            int new_state = next_state(cur_state, move, &tb);
            if (tb > cb)
                val = alpha_beta(player, new_state, alpha, beta, ca, tb);
            else
                val = alpha_beta(1 - player, new_state, alpha, beta, ca, cb);
            if (val < beta)
                beta = val;
            if (alpha >= beta)
                return beta;
            remain -= move;
        }
        return beta;
    }
}

void ChingShowColor(int x)
{
    switch (x)
    {
    case 0:SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xf); break;
    case 1:SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED); break;
    case 2:SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE); break;
    default:
        break;
    }
}

void ShowTri(int *Map, int *Tir)
{
    int Map_i = 0, Tir_i = 0;
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xf);
    cout << "         01" << endl;//1#
    ChingShowColor(Map[Map_i++]);
    cout << "        /";
    ChingShowColor(Tir[Tir_i++]);
    cout << "▲";
    ChingShowColor(Map[Map_i++]);
    cout << "\\" << endl;//2#
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xf);
    cout << "      02";
    ChingShowColor(Map[Map_i++]);
    cout << "----";
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xf);
    cout << "03" << endl;//3#
    ChingShowColor(Map[Map_i++]);
    cout << "     /";
    ChingShowColor(Tir[Tir_i++]);
    cout << "▲";
    ChingShowColor(Map[Map_i++]);
    cout << "\\";
    ChingShowColor(Tir[Tir_i++]);
    cout << "▼";
    ChingShowColor(Map[Map_i++]);
    cout << "/";
    ChingShowColor(Tir[Tir_i++]);
    cout << "▲";
    ChingShowColor(Map[Map_i++]);
    cout << "\\" << endl;//4#
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xf);
    cout << "   04";
    ChingShowColor(Map[Map_i++]);
    cout << "----";
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xf);
    cout << "05";
    ChingShowColor(Map[Map_i++]);
    cout << "----";
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xf);
    cout << "06" << endl;//5#
    ChingShowColor(Map[Map_i++]);
    cout << "  /";
    ChingShowColor(Tir[Tir_i++]);
    cout << "▲";
    ChingShowColor(Map[Map_i++]);
    cout << "\\";
    ChingShowColor(Tir[Tir_i++]);
    cout << "▼";
    ChingShowColor(Map[Map_i++]);
    cout << "/";
    ChingShowColor(Tir[Tir_i++]);
    cout << "▲";
    ChingShowColor(Map[Map_i++]);
    cout << "\\";
    ChingShowColor(Tir[Tir_i++]);
    cout << "▼";
    ChingShowColor(Map[Map_i++]);
    cout << "/";
    ChingShowColor(Tir[Tir_i++]);
    cout << "▲";
    ChingShowColor(Map[Map_i++]);
    cout << "\\" << endl;//6#
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xf);
    cout << "07";
    ChingShowColor(Map[Map_i++]);
    cout << "----";
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xf);
    cout << "08";
    ChingShowColor(Map[Map_i++]);
    cout << "----";
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xf);
    cout << "09";
    ChingShowColor(Map[Map_i++]);
    cout << "----";
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xf);
    cout << "10" << endl;//7#
}

void ChangeEdge(int u, int v,int player)
{
    int color = 0;
    player ? color = 2: color = 1;
    //1-2边
    if (u == 1 && v == 2)
         Map[0] = color;
    if (u == 2 && v == 1)
        Map[0] = color;
    //1-3边
    if (u == 1 && v == 3)
        Map[1] = color;
    if (u == 3 && v == 1)
        Map[1] = color;
    //2-3边
    if (u == 3 && v == 2)
        Map[2] = color;
    if (u == 2 && v == 3)
        Map[2] = color;
    //2-4边
    if (u == 4 && v == 2)
        Map[3] = color;
    if (u == 2 && v == 4)
        Map[3] = color;
    //2-5边
    if (u == 5 && v == 2)
        Map[4] = color;
    if (u == 2 && v == 5)
        Map[4] = color;
    //3-5边
    if (u == 3 && v == 5)
        Map[5] = color;
    if (u == 5 && v == 3)
        Map[5] = color;
    //3-6边
    if (u == 3 && v == 6)
        Map[6] = color;
    if (u == 6 && v == 3)
        Map[6] = color;
    
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值