将之前的一道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;