1。在《leela-zero-next》包中有一个
从人类游戏训练的(较弱的)网络的权重文件(https://sjeng.org/zero/best_v1.txt.zip)(6残差块,128通道)
2。并在《easyx吧》百度贴吧下了一个双人对战的五子棋+围棋的游戏(去掉其中的五子棋部分)。
把这两个合成一个人机对战围棋。
虽然leela-zero也是C++写的,但是我也看不懂,这里只使用其权重,还是按前面的方法生成推演网络。
难点在
(1)围棋界面的部分的数组数据--->转换成网络输入
(2)网络输出--->转换界面落子位
界面部分
流程:
载入一张背景图,在其上画19x19棋盘。
然后在鼠标点位下子(黑白轮流下)(鼠标左键)(任何时都可以双方交换子)
把其中的一方由网络代替
提子要手工提(鼠标右键)
一些变量:
int player_exchange = 0;//玩家轮流下棋
int arr[19][19] = { 0 };//棋盘数组
char str[5];//outtextxy转换字符中间容器
int a, b;//全局变量,记录交叉点位置
int a1, b1, a2, b2;//记录落子时落在数组的什么位置
int x, y;//全局变量,记录交叉点坐标
int record_now_player_exchange;//记录刚读档的exchange值,此后exchange就会++
int play_weiqi = 0;//是否选择围棋
//-------------------------------------
//人机对战
int jibw=0;//机器选黑白子 白:0,黑:1
vector 顺序黑;//黑方下子序号(在网络图中的序号(也是下子顺序),连接界面和网络用)
vector 顺序白;//白方下子序号
画棋盘:
// 画棋盘
void 画棋盘()
{
int i;
int j;
BeginBatchDraw();
IMAGE bk;
loadimage(&bk, "围棋背景.jpg", 1100, 1000);
//五子棋背景图片
putimage(0, 0, 20 * 25 + 130, 121 * 25 - 20, &bk, 0, 0);
setlinecolor(BLACK);
setlinestyle(PS_SOLID, 1);
for (j = 1; j <= 19; j++)
{
line(1 * 25, j * 25, 19 * 25, j * 25);
}
for (i = 1; i <= 19; i++)
{
line(i * 25, 1 * 25, i * 25, 19 * 25);
}
//写入下标数字
for (i = 1; i <= 19; i++)
{
for (j = 1; j <= 19; j++)
{
setbkmode(0);
settextstyle(16, 0, _T("宋体"));
settextcolor(BLACK);
outtextxy(i * 25 - 6, 19 * 25 + 8, change(i));
outtextxy(1 * 25 - 24, j * 25 - 9, change(j));
}
}
//画边框
setlinestyle(PS_SOLID, 2);
line(1 * 25, 1 * 25, 19 * 25, 1 * 25);
line(1 * 25, 19 * 25, 19 * 25, 19 * 25);
line(1 * 25, 1 * 25, 1 * 25, 19 * 25);
line(19 * 25, 1 * 25, 19 * 25, 19 * 25);
setfillcolor(BLACK);
//画四个点
fillcircle(4 * 25, 4 * 25, 3);
fillcircle(16 * 25, 4 * 25, 3);
fillcircle(4 * 25, 16 * 25, 3);
fillcircle(16 * 25, 16 * 25, 3);
fillcircle(10 * 25, 10 * 25, 3);
fillcircle(10 * 25, 4 * 25, 3);
fillcircle(16 * 25, 10 * 25, 3);
fillcircle(10 * 25, 16 * 25, 3);
fillcircle(4 * 25, 10 * 25, 3);
setbkmode(0);
settextstyle(16, 0, _T("宋体"));
settextcolor(BLACK);
outtextxy(510, 40, "棋子坐标为:");
//outtextxy(520, 60, " 行 列");
outtextxy(520, 60, " 列 行");
outtextxy(510, 100, "该:");
outtextxy(510, 130, "白棋步数:");
outtextxy(510, 160, "黑棋步数:");
outtextxy(510, 190, "围棋规则:");
outtextxy(510, 210, "·右键摘子");
outtextxy(510, 230, "·玩家判断输赢");
//outtextxy(510, 260, "五子棋规则:");
outtextxy(510, 280, "按下a:对换子");
//outtextxy(510, 350, "按下1:暂停:");
//outtextxy(510, 380, "按下2:存档:");
//outtextxy(510, 410, "按下3:退出:");
//outtextxy(510, 440, "按下4:悔棋:");
EndBatchDraw();
}
画好的棋盘:
入口:
int main()
{
initNet();//载入网络权重
initgame();//画棋盘
system ("title 围棋");
player_down();//游戏循环(人机下子)
closegraph();
return 0;
}
游戏循环:
//玩家落子 游戏循环
void player_down()
{
int i;
int j;
MOUSEMSG m;//定义一个鼠标变量m
hwnd = GetHWnd();
while (1)
{
m = GetMouseMsg();
//让棋子下在交叉点
for (i = 1; i <= 19; i++)
{
for (j = 1; j <= 19; j++)
{
if ((abs(m.x - i * 25)<12) && (abs(m.y - j * 25)<12))
{
//记录下交叉点的位置
a = i;
b = j;
x = i * 25;
y = j * 25;
}
}
}
if(player_exchange % 2 ==jibw)
{
if(机器下子())
落子();
}
else
{
//玩家下子
if (m.uMsg == WM_LBUTTONDOWN)
{
huiqi_just_one = 1;//赋值为1,允许悔棋
if (arr[a - 1][b - 1] != 0)
{
//MessageBox(hwnd, TEXT("此地已有子,请另择他地!"), "提示:", MB_OK);
continue;
}
cout<<"玩家:"<
机器下子:
bool 机器下子()
{
//黑白子下子顺序到后面
//生成最近8步棋数据
//走子方8步棋
//非走子方8步棋
//当前行棋方-----------这些到网络部分 netgo 生成
//输入网络
//返回落子位
bool lu=false;//选点成功吗,不成功可能要当机了(可以加大,5个不够)
vector 前5序号;
netgo(顺序黑, 顺序白,前5序号);//去网络部分
//返回下子序号生成棋盘位置
for(int i=0;i<前5序号.size();i++)
{
int xy=前5序号[i];
int b0=xy/19;
int a0=xy%19;
if(arr[a0][b0]== 0)
{
b=b0+1;
a=a0+1;
cout<<"机:"<
落子并生成下棋顺序:
//落子并生成下棋顺序
void 落子()
{
if (player_exchange % 2 == 0)
{
setfillcolor(WHITE);
solidcircle(x, y, 8);
//此时的a,b就是交叉点的位置
a1 = a - 1; b1 = b - 1;
arr[a1][b1] = 1;
number_white++;
//设置图片遮盖字体
setfillcolor(YELLOW);
solidrectangle(580, 130, 595, 147);//步数
solidrectangle(580, 100, 595, 120);//黑,白字
solidrectangle(519, 60, 534, 77);//棋子坐标
solidrectangle(551, 60, 566, 77);//坐标
//setcolor(BLACK);
setlinecolor(BLACK);
outtextxy(580, 130, change(number_white));
outtextxy(564, 100, ":黑");
outtextxy(519, 60,change(a1+1));
outtextxy(551, 60, change(b1+1));
顺序白.push_back(a1+b1*19);
}
else
{
setfillcolor(BLACK);
solidcircle(x, y, 8);
//将黑棋的点的值都设置成为2
a2 = a - 1; b2 = b - 1;
arr[a2][b2] = 2;
number_black++;
//设置图片遮盖字体
setfillcolor(YELLOW);
solidrectangle(580, 160, 595, 177);
solidrectangle(580, 100, 595, 120);
solidrectangle(519, 60, 534, 77);//坐标
solidrectangle(551, 60, 566, 77);//坐标
//setcolor(BLACK);
setlinecolor(BLACK);
outtextxy(580, 160, change(number_black));
outtextxy(564, 100, ":白");
outtextxy(519, 60, change(a2+1));
outtextxy(551, 60, change(b2+1));
顺序黑.push_back(a2+b2*19);
}
player_exchange++;
}
界面部分不都是我写的(我修改了一部分代码,,加了一部分,部分原创),有兴趣的朋友可以去贴吧下载原始代码。
下了几步图:
界面部分暂时结束。