围棋代码(围棋代码java)
admin 发布:2022-12-19 12:24 120
本篇文章给大家谈谈围棋代码,以及围棋代码java对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、如何用javascript实现围棋游戏
- 2、求围棋的VB源代码~
- 3、围棋java源代码
- 4、vb6.0编写围棋源代码
- 5、自学围棋的AlphaGo Zero,你也可以造一个
- 6、急求 用c++编写的人机对弈的围棋的程序代码,最好有注释!谢啦!!
如何用javascript实现围棋游戏
head
meta http-equiv="Content-Type" content="text/html;charset=utf-8" /
title禅棋传说/title
style type="text/css"
div { position: absolute; width: 23px; height: 23px; }
.B0 { background-image: url('B0.gif'); }
.B1 { background-image: url('B1.gif'); }
.B2 { background-image: url('B2.gif'); }
.B3 { background-image: url('B3.gif'); }
.B4 { background-image: url('B4.gif'); }
.B5 { background-image: url('B5.gif'); }
.B6 { background-image: url('B6.gif'); }
.B7 { background-image: url('B7.gif'); }
.B8 { background-image: url('B8.gif'); }
.BX { background-image: url('BX.gif'); }
.D0 { background-image: url('D0.gif'); }
.D1 { background-image: url('D1.gif'); }
.C0 { background-image: url('C0.gif'); }
.C1 { background-image: url('C1.gif'); }
/style
/head
body
script type="text/javascript"
//![CDATA[
Array.prototype.indexOf = function (item) //给数组扩展一个indexOf方法,用来检索是否为"已知元素"
{
for ( var i=0; ithis.length; i++)
if (this[i] == item)
return i;
return -1;
};
var Site = //定义一个棋位类
{
Create: function(x, y) //棋位类的构造函数
{
var me = document.createElement("div"); //建一个div对象,将其扩展并封装成棋位。
document.body.appendChild(me); //附加到DOM树,实现棋位的呈现。
me.x = x; //记录棋位的X坐标
me.y = y; //记录棋位的Y坐标
me.style.left = x * 23 + "px"; //设置棋位水平方向的绝对位置
me.style.top = y * 23 + "px"; //设置棋位垂直方向的绝对位置
// var s = ((x-9)%9?0:(x-9)/9)+1+(((y-9)%9?0:(y-9)/9)+1)*3; //计算背景式样,这个算法有冗余,简化为下面的算法.
var s = parseInt((x-9)/9)+1+(parseInt((y-9)/9)+1)*3; //计算背景式样
// me._backStyle = "B" + ((s==4(x/3)%2==1(y/3)%2==1) ? "X" : s);
me._backStyle = "B" + (((x/3)%2==1(y/3)%2==1) ? "X" : s);
me.Fill = this.Fill; //关联一个填充棋位的方法。
me.Tight = this.Tight; //关联计算紧气方法。
me.Kill = this.Kill; //关联计算死子方法。
me.onclick = this.Play; //绑定onclick事件到Play方法。
me.Fill(); //初始填充空子。
return me; //返回棋位对象,其实是一个封装了的div对象。
},
Fill: function(dot, going) //填充棋子的方法,going~~是否"当前步".
{
if ( dot == undefined )
this.className = this._backStyle //无子,就设置为背景式样。
else
this.className = (going ? "C" : "D") + dot; //有子,区别对待"当前步"
this.dot = dot; //保存棋子状态
},
Play: function() //行棋方法,由onclick事件触发
{
if ( this.dot == undefined ) //落子点必须为无子状态,否则不处理.
{
var deads = this.Kill(current^1); //计算可以杀死的子,current为当前颜色,则current^1为对方颜色
if (deads.length == 1 this == rob) return; //确认的打劫状态后,直接拒绝;如果此步落子可以提不止一子,则不是打劫
for(var i=0; ideads.length; i++)
deads[i].Fill(); //按照死子列清空,one by one
if(i==1)
rob = deads[0] //如果此步只提了一个子,记录被提位置为打劫位置.
else if (i0 || !this.Tight(current)) //这里有一个影响代码效率的判断,对于能产生提子的操做,不需要再判断是否"紧气禁入";此外,如果要引入"变穷为禁"的规则,这里需要改变算法
rob = null //清打劫位,这个条件是判断,如果能够提多子,或者不是禁止着手,则解除"打劫"状态
else return; //这里对应的返回,应该是只有无气禁入点的情况.
sound.play(); //落子有声!
var step = Tracks[Tracks.length-1];
if(step) step.site.Fill(step.site.dot); //更新此前一"步"的子的位图
this.Fill(current, true); //填入当前"步"的子
Tracks.push( new Step(this, deads) );
current ^= 1; //用1来异或,正好反转黑白棋子。
var disline = document.getElementById('list');
disline.value += ((current ? '黑:': '白:')+Tracks[Tracks.length-1].site.x+' '+Tracks[Tracks.length-1].site.y+'\n');
disline.scrollTop = disline.scrollHeight;
};
},
Tight: function (dot) //计算紧气的块,此时如果dot==undefined,则对应提子的遍历,this指向当前点.
{
var life = this.dot == undefined ? this : undefined; //life为"气"的定义;当前位无子则算一口气,对应落子的遍历,当前位置必然无子.
dot = dot == undefined ? this.dot : dot; //这个逻辑是对应提子的遍历
if (dot == undefined) return undefined;
var block = this.dot == undefined ? [] : [this]; //定义的"块",在提子的遍历中,发现子就放入块,再判断有多少"气".
var i = this.dot == undefined ? 0 : 1;
var site = this;
while (true)
{
for(var dx=-1;dx=1;dx++) for(var dy=-1;dy=1;dy++) if(!dx^!dy)
{
link = GetSite(site.x + dx, site.y + dy);
if (link) //判断目标位置的上下左右,有位则继续,"无位"对应棋盘以外的区域.
if (link.dot != undefined) //有子,则判断是否为同色,连"块"
{
if (link.dot == dot block.indexOf(link) 0 )
block.push(link); //此一段为"块"的遍历,条件是找四周的同色子,找到后判断是否为新"知道","新"则放入"块"
}
else if (!life) //无子,则更新"气"
life = link
else if (life != link)
return undefined; //在提子的遍历中,如果发现有两"气"了,则无须再算
};
if ( i = block.length) break; //"块"的遍历结束条件为,列表的最后一个对象没有产生新的相邻子.
site = block[i];
i ++;
};
return block; //返回只有一口气的块,在提子的遍历中,这对应了可能被提掉的子列,再去判断是否为"打劫"
},
Kill: function(dot) //计算杀死的子,目前this指向落子点,dot指向需要判断的死子颜色.
{
var deads = []; //定义死子列
for(var dx=-1;dx=1;dx++) for(var dy=-1;dy=1;dy++) if(!dx^!dy) //异或,有且只有一个为真,可对应到相邻子.
{
var site = GetSite(this.x + dx, this.y + dy);
if (site (site.dot == dot))
{
var block = site.Tight(); //分别对上下左右进行遍历,查找被紧气的"块",然后合并成为"死子列"
if (block) deads = deads.concat(block); //concat 合并操作,此操作并未识别"同项",仅以围棋规则判断,对"打劫没有影响".
//如果需要准确的提子数目统计,这里的算法需要更新.
};
};
return deads; //返回可以提子的死子块
}
}; //棋位类 Site
var Board = new Array(19); //全局的Board数组,表示棋盘。
var Tracks = []; //行棋线索数组,数组元素是Step对象。
var current = 0; //当前要下的子,0表示黑子,1表示白子,交替。
var rob = null; //如果有打劫时,记录打劫位置。
for(var x = 0 ; x 19; x++)
{
Board[x] = new Array(19);
for(var y = 0; y 19; y++)
Board[x][y] = Site.Create(x, y); //按位置创建棋位对象。
};
if (navigator.userAgent.indexOf(' MSIE ') -1) //为IE浏览器构造声音对象
{
var sound = document.body.appendChild(document.createElement("bgsound"));
sound.play = function(){this.src = "play.wav"};
}
else //为Firefox等其他浏览器构造声音对象
{
var sound = document.body.appendChild(document.createElement("span"));
sound.play = function(){this.innerHTML = "bgsound src='play.wav'"};
};
document.body.oncontextmenu = function() //右键驱动悔棋事件
{
var step = Tracks.pop();
if (step)
{
step.site.Fill();
for (var i=0; istep.deads.length; i++)
step.deads[i].Fill(current);
step = Tracks[Tracks.length-1];
if (step) step.site.Fill(current, true)
current ^= 1; //反转黑白棋子。
};
return false; //不弹出菜单。
};
function GetSite(x, y) //从棋盘取棋位的函数,越界不抛出异常。
{
if (x=0 x19 y=0 y19)
return Board[x][y];
};
function Step(site, deads) //棋步类,记录每一步棋的状态
{
this.site = site; //记录棋步的位置
this.deads = deads; //记录被当前棋步杀死的棋子集合
};
function PrintWay() //行棋路线
{
var str='', coler='';
for (var i=0;i Tracks.length;i++)
{
step = Tracks[i];
coler = (i%2) ? "白" : "黑";
str=str+"第"+(i+1)+"步"+coler+"方 X"+step.site.x+" Y"+step.site.y+" \n";
}
alert(str);
}
document.body.ondblclick = PrintWay;
document.onkeypress = function(event)
{
var k = (window.event ? window.event.keyCode : event.which) - 49; //按'1'可以进入自动摆棋操作,'1'=0x31=49
if(k0 || k1) return;
for(var x=0; x19; x++) for(var y=0; y19; y++) Board[x][y].Fill();
Tracks.length = 0;
current = 0;
with(goes[k]) for(var i=0; ilength;i+=3)
Board[charCodeAt(i+1)-65][charCodeAt(i)-65].Fill(charCodeAt(i+2)-48);
};
/body
/html
求围棋的VB源代码~
来~加 我 的QQ405557154 我做了一个,还有一同学做的,还有一是网上的朋友做的呵呵
Private Sub Timer1_Timer()
Dim ms As Boolean
Dim Info, temp As String
Dim p, p1, p2, i As Integer
Dim Ch
' Begin of Time Show Process
If ModemState LOGIN And SocketState CONNECTED Then
'it is not a multiusers game
Exit Sub
Else
If (S_R = 1) And (TURN = BLACKP) Then
Black_Time = Black_Time + Time - Start_Time
TimeB.Caption = CDate(Black_Time / 200)
Else
If (S_R = 1) And (TURN = WHITEP) Then
White_Time = White_Time + Time - Start_Time
TimeW.Caption = CDate(White_Time / 200)
Else
If (S_R = 0) And (TURN = WHITEP) Then
Black_Time = Black_Time + Time - Start_Time
TimeB.Caption = CDate(Black_Time / 200)
Else
If (S_R = 0) And (TURN = BLACKP) Then
White_Time = White_Time + Time - Start_Time
TimeW.Caption = CDate(White_Time / 200)
End If
End If
End If
End If
End If
'End If
' End of Time Show Process
'Begin of winsockt process
If SocketState = CONNECTED And Begin_Flag = 1 Then
ms = Net.Message_Exist
If ms = False Then
Exit Sub
End If
Info = Net.WaitForValue(Chr$(26), 5)
If g_ErrorCode = 1 Then
'Some error such as Timeout occured
Exit Sub
End If
p1 = InStr(Info, "B")
p2 = InStr(Info, "E|;")
If p1 = 0 Or p2 = 0 Then
Exit Sub
End If
temp = Mid$(Info, p1 + 1, p2 - p1 - 1)
ParseLine (temp)
Msg(Msg_No).No = CInt(ParseArray(1))
Msg(Msg_No).Color = CInt(ParseArray(2))
If IsNumeric(ParseArray(3)) Then
Msg(Msg_No).X = CInt(ParseArray(3))
Msg(Msg_No).Y = CInt(ParseArray(4))
Else
Msg(Msg_No).X = ParseArray(3)
Msg(Msg_No).Y = ParseArray(4)
End If
If Msg(Msg_No).Color = GIVEUP Then
Beep
MsgBox ("对方已经认输了")
Net.Winsock1.SendData ("R_O" + Chr$(26))
Pause 3
Call Begin_Click
Exit Sub
End If
If Side = BLACKP Then
p = Draw_Point(Msg(Msg_No).X, Msg(Msg_No).Y, WHITEP)
Record(Step).Color = WHITEP
step_show.Cls
step_show.Print Step
TURN = BLACKP
Else
p = Draw_Point(Msg(Msg_No).X, Msg(Msg_No).Y, BLACKP)
Record(Step).Color = BLACKP
step_show.Cls
step_show.Print Step
TURN = WHITEP
End If
Record(Step).X = Msg(Msg_No).X
Record(Step).Y = Msg(Msg_No).Y
Step = Step + 1
S_R = 1
R_R = 0
p = Count_All_Gas
If (Msg(Msg_No).X 0 And Msg(Msg_No).Y 0 _
And Msg(Msg_No).X 20 And Msg(Msg_No).Y 20) Then
Board(Msg(Msg_No).X, Msg(Msg_No).Y).Current = True
Refresh_Board
Board(Msg(Msg_No).X, Msg(Msg_No).Y).Current = False
End If
Msg_No = Msg_No + 1
Pause 1
Net.Winsock1.SendData ("R_O" + Chr$(26))
Exit Sub
End If
'End of process of winsocket
'Begin of modem process
If ModemState LOGIN Or R_R 1 Then
'It isn't a Inter_Modem Game
Exit Sub
End If
ms = Modem_F.Exist_Msg
If ms = False Then
'IO Port don't have any message
Exit Sub
End If
Info = Modem_F.WaitForValue(Chr$(26), 5)
'Wait a playing message
If g_ErrorCode = 1 Then
'Some error such as Timeout occured
Exit Sub
End If
p1 = InStr(Info, "B")
p2 = InStr(Info, "E|;")
If p1 = 0 Or p2 = 0 Then
Exit Sub
End If
temp = Mid$(Info, p1 + 1, p2 - p1 - 1)
ParseLine (temp)
Msg(Msg_No).No = CInt(ParseArray(1))
Msg(Msg_No).Color = CInt(ParseArray(2))
If IsNumeric(ParseArray(3)) Then
Msg(Msg_No).X = CInt(ParseArray(3))
Msg(Msg_No).Y = CInt(ParseArray(4))
Else
Msg(Msg_No).X = ParseArray(3)
Msg(Msg_No).Y = ParseArray(4)
End If
Modem_F.Comm1.InBufferCount = 0
'Clear Buffer
If Msg(Msg_No).Color = LOGOUT Then
Beep
MsgBox ("对方已经退出了")
Modem_F.Comm1.InBufferCount = 0
Modem_F.Comm1.Output = "R_O" + Chr$(26)
Cls
Step = 0
Start_Time = Time
Black_Time = 0
White_Time = 0
Exit Sub
End If
If Msg(Msg_No).Color = FINISHED Then
Beep
Ch = MsgBox("对方要求结束比赛,可以吗?", vbYesNo)
Modem_F.Comm1.InBufferCount = 0
If Ch = 6 Then
Modem_F.Comm1.Output = "YESR_O" + Chr$(26)
Else
Modem_F.Comm1.Output = "NOR_O" + Chr$(26)
Exit Sub
End If
PlayState = FINISHED
Count_Area.Enabled = True
End If
If Msg(Msg_No).Color = GIVEUP Then
Beep
MsgBox ("对方已经认输了")
Modem_F.Comm1.InBufferCount = 0
Modem_F.Comm1.Output = "R_O" + Chr$(26)
Call Begin_Click
Exit Sub
End If
If Msg(Msg_No).Color = TALK Then
Beep
MsgBox (Modem_F.His_Name.Text "说: " Msg(Msg_No).X)
Modem_F.Comm1.InBufferCount = 0
Modem_F.Comm1.Output = "R_O" + Chr$(26)
Exit Sub
End If
If Msg(Msg_No).Color = UNDO Then
Step = Step - 1
Beep
Modem_F.Comm1.InBufferCount = 0
Modem_F.Comm1.Output = "R_O" + Chr$(26)
Draw_Board
Ini_Board
For i = 1 To Step - 1
Board(Record(i).X, Record(i).Y).Current = False
p = Draw_Point(Record(i).X, Record(i).Y, Record(i).Color)
step_show.Cls
step_show.Print Step
p = Count_All_Gas
Next i
Board(Record(Step - 1).X, Record(Step - 1).Y).Current = True
Refresh_Board
Board(Record(Step - 1).X, Record(Step - 1).Y).Current = False
S_R = 1
R_R = 0
TURN = Side
Exit Sub
End If
Modem_F.Comm1.InBufferCount = 0
Modem_F.Comm1.Output = "R_O" + Chr$(26)
If Side = BLACKP Then
p = Draw_Point(Msg(Msg_No).X, Msg(Msg_No).Y, WHITEP)
Record(Step).Color = WHITEP
step_show.Cls
step_show.Print Step
Else
p = Draw_Point(Msg(Msg_No).X, Msg(Msg_No).Y, BLACKP)
Record(Step).Color = BLACKP
step_show.Cls
step_show.Print Step
End If
Record(Step).X = Msg(Msg_No).X
Record(Step).Y = Msg(Msg_No).Y
Step = Step + 1
S_R = 1
R_R = 0
p = Count_All_Gas
If (Msg(Msg_No).X 0 And Msg(Msg_No).Y 0 _
And Msg(Msg_No).X 20 And Msg(Msg_No).Y 20) Then
Board(Msg(Msg_No).X, Msg(Msg_No).Y).Current = True
Refresh_Board
Board(Msg(Msg_No).X, Msg(Msg_No).Y).Current = False
End If
Msg_No = Msg_No + 1
End Sub
Private Sub Timer2_Timer()
ShowS.Cls
ShowS.Print " :-):-):-):-):-) " + Show_String(C1) + " (:-(:-(:-(:-(:-"
C1 = C1 + 1
If C1 = 10 Then
C1 = 0
End If
Game_Time.Cls
Game_Time.Print " 现在时间: " Time
End Sub
Private Sub Set_Hand(h As Integer)
'设置让子(1-9)
Dim p As Integer
If h = 1 Then
'Not a Handicap game
Exit Sub
End If
部分代码。。
围棋java源代码
就给你一个吧,只不过没有添加棋子,你自己搞吧。import java.applet.*;
import java.awt.*;
import java.awt.event.*;
class ChessPad extends Panel implements MouseListener,ActionListener
{int x=-1,y=-1,棋子颜色=1;
Button button=new Button("重新开局");
TextField text_1=new TextField("请黑棋下子"),
text_2=new TextField();
ChessPad()
{setSize(440,440);
setLayout(null);setBackground(Color.pink);
addMouseListener(this);add(button);button.setBounds(10,5,60,26);
button.addActionListener(this);
add(text_1);text_1.setBounds(90,5,90,24);
add(text_2);text_2.setBounds(290,5,90,24);
text_1.setEditable(false);text_2.setEditable(false);
}
public void paint(Graphics g)
{for(int i=40;i=380;i+=20)
{g.drawLine(40,i,400,i);
}
g.drawLine(40,400,400,400);
for(int j=40;j=380;j+=20)
{g.drawLine(j,40,j,400);
}
g.drawLine(400,40,400,400);
g.fillOval(97,97,6,6);g.fillOval(337,97,6,6);
g.fillOval(97,337,6,6);g.fillOval(337,337,6,6);
g.fillOval(217,217,6,6);
}
public void mousePressed(MouseEvent e)
{if(e.getModifiers()==InputEvent.BUTTON1_MASK)
{x=(int)e.getX();y=(int)e.getY();
ChessPoint_black chesspoint_black=new ChessPoint_black(this);
ChessPoint_white chesspoint_white=new ChessPoint_white(this);
int a=(x+10)/2,b=(y+10)/2;
if(x/202||y/202||x/2019||y/2019)
{}
else
{
if(棋子颜色==1)
{this.add(chesspoint_black);
chesspoint_black.setBounds(a*20-7,b*20-7,16,16);
棋子颜色=棋子颜色*(-1);
text_2.setText("请白棋下子");
text_1.setText("");
}
else if(棋子颜色==-1)
{this.add(chesspoint_white);
chesspoint_white.setBounds(a*20-7,b*20-7,16,16);
棋子颜色=棋子颜色*(-1);
text_1.setText("请黑棋下子");
text_2.setText("");
}
}
}
}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e){}
public void actionPerformed(ActionEvent e)
{this.removeAll();棋子颜色=1;
add(button);button.setBounds(10,5,60,26);
add(text_1);text_1.setBounds(90,5,90,24);
text_2.setText("");text_1.setText("请黑棋下子");
add(text_2);text_2.setBounds(290,5,90,24);
}
}
class ChessPoint_black extends Canvas implements MouseListener
{ChessPad chesspad=null;
ChessPoint_black(ChessPad p)
{setSize(20,20);chesspad=p;addMouseListener(this);
}
public void paint(Graphics g)
{g.setColor(Color.black);g.fillOval(0,0,14,14);
}
public void mousePressed(MouseEvent e)
{if(e.getModifiers()==InputEvent.BUTTON3_MASK)
{chesspad.remove(this);
chesspad.棋子颜色=1;
chesspad.text_2.setText("");chesspad.text_1.setText("请黑棋下子");
}
}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e)
{if(e.getClickCount()=2)
chesspad.remove(this);
}
}
class ChessPoint_white extends Canvas implements MouseListener
{ChessPad chesspad=null;
ChessPoint_white(ChessPad p)
{setSize(20,20);addMouseListener(this);
chesspad=p;
}
public void paint(Graphics g)
{g.setColor(Color.white);g.fillOval(0,0,14,14);
}
public void mousePressed(MouseEvent e)
{if(e.getModifiers()==InputEvent.BUTTON3_MASK)
{chesspad.remove(this);
chesspad.棋子颜色=-1;
chesspad.text_2.setText("请白棋下子");chesspad.text_1.setText("");
}
}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e)
{if(e.getClickCount()=2)
chesspad.remove(this);
}
}
public class Chess extends Frame
{ChessPad chesspad=new ChessPad();
Chess()
{setVisible(true);
setLayout(null);
Label label=new Label("单击左键下子,双击吃子,右击棋子悔棋",Label.CENTER);
add(label);label.setBounds(70,55,440,26);
label.setBackground(Color.orange);
add(chesspad);chesspad.setBounds(70,90,440,440);
addWindowListener(new WindowAdapter()
{public void windowClosing(WindowEvent e)
{System.exit(0);
}
});
pack();setSize(600,550);
}
public static void main (String args[])
{Chess chess=new Chess();
}
}
vb6.0编写围棋源代码
弈城的形势判断可以做评估函数
另,最好使用分割法,将棋盘分割,他走那你选择该分割棋盘内最好的应手(递归)或其他区块最好应手(这个可以先计算好再保存)
自学围棋的AlphaGo Zero,你也可以造一个
01
遥想当年,AlphaGo的Master版本,在完胜柯洁九段之后不久,就被后辈AlphaGo Zero (简称狗零) 击溃了。
从一只完全不懂围棋的AI,到打败Master,狗零只用了21天。
而且,它不需要用人类知识来喂养,成为顶尖棋手全靠自学。
如果能培育这样一只AI,即便自己不会下棋,也可以很骄傲吧。
于是,来自巴黎的少年Dylan Djian (简称小笛) ,就照着狗零的论文去实现了一下。
他给自己的AI棋手起名SuperGo,也提供了代码 (传送门见文底) 。
除此之外,还有教程——
一个身子两个头
智能体分成三个部分:
一是特征提取器 (Feature Extractor) ,二是策略网络 (Policy Network) ,三是价值网络(Value Network) 。
于是,狗零也被亲切地称为“双头怪”。特征提取器是身子,其他两个网络是脑子。
特征提取器
特征提取模型,是个残差网络 (ResNet) ,就是给普通CNN加上了跳层连接 (Skip Connection) , 让梯度的传播更加通畅。
跳跃的样子,写成代码就是:
1class BasicBlock(nn.Module):
2 """
3 Basic residual block with 2 convolutions and a skip connection
4 before the last ReLU activation.
5 """
6
7 def __init__(self, inplanes, planes, stride=1, downsample=None):
8 super(BasicBlock, self).__init__()
9
10 self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=3,
11 stride=stride, padding=1, bias=False)
12 self.bn1 = nn.BatchNorm2d(planes)
13
14 self.conv2 = nn.Conv2d(planes, planes, kernel_size=3,
15 stride=stride, padding=1, bias=False)
16 self.bn2 = nn.BatchNorm2d(planes)
17
18
19 def forward(self, x):
20 residual = x
21
22 out = self.conv1(x)
23 out = F.relu(self.bn1(out))
24
25 out = self.conv2(out)
26 out = self.bn2(out)
27
28 out += residual
29 out = F.relu(out)
30
31 return out
然后,把它加到特征提取模型里面去:
1class Extractor(nn.Module):
2 def __init__(self, inplanes, outplanes):
3 super(Extractor, self).__init__()
4 self.conv1 = nn.Conv2d(inplanes, outplanes, stride=1,
5 kernel_size=3, padding=1, bias=False)
6 self.bn1 = nn.BatchNorm2d(outplanes)
7
8 for block in range(BLOCKS):
9 setattr(self, "res{}".format(block), \
10 BasicBlock(outplanes, outplanes))
11
12
13 def forward(self, x):
14 x = F.relu(self.bn1(self.conv1(x)))
15 for block in range(BLOCKS - 1):
16 x = getattr(self, "res{}".format(block))(x)
17
18 feature_maps = getattr(self, "res{}".format(BLOCKS - 1))(x)
19 return feature_maps
策略网络
策略网络就是普通的CNN了,里面有个批量标准化 (Batch Normalization) ,还有一个全连接层,输出概率分布。
1class PolicyNet(nn.Module):
2 def __init__(self, inplanes, outplanes):
3 super(PolicyNet, self).__init__()
4 self.outplanes = outplanes
5 self.conv = nn.Conv2d(inplanes, 1, kernel_size=1)
6 self.bn = nn.BatchNorm2d(1)
7 self.logsoftmax = nn.LogSoftmax(dim=1)
8 self.fc = nn.Linear(outplanes - 1, outplanes)
9
10
11 def forward(self, x):
12 x = F.relu(self.bn(self.conv(x)))
13 x = x.view(-1, self.outplanes - 1)
14 x = self.fc(x)
15 probas = self.logsoftmax(x).exp()
16
17 return probas
价值网络
这个网络稍微复杂一点。除了标配之外,还要再多加一个全连接层。最后,用双曲正切 (Hyperbolic Tangent) 算出 (-1,1) 之间的数值,来表示当前状态下的赢面多大。
代码长这样——
1class ValueNet(nn.Module):
2 def __init__(self, inplanes, outplanes):
3 super(ValueNet, self).__init__()
4 self.outplanes = outplanes
5 self.conv = nn.Conv2d(inplanes, 1, kernel_size=1)
6 self.bn = nn.BatchNorm2d(1)
7 self.fc1 = nn.Linear(outplanes - 1, 256)
8 self.fc2 = nn.Linear(256, 1)
9
10
11 def forward(self, x):
12 x = F.relu(self.bn(self.conv(x)))
13 x = x.view(-1, self.outplanes - 1)
14 x = F.relu(self.fc1(x))
15 winning = F.tanh(self.fc2(x))
16 return winning
未雨绸缪的树
狗零,还有一个很重要的组成部分,就是蒙特卡洛树搜索 (MCTS) 。
它可以让AI棋手提前找出,胜率最高的落子点。
在模拟器里,模拟对方的下一手,以及再下一手,给出应对之策,所以提前的远不止是一步。
节点 (Node)
树上的每一个节点,都代表一种不同的局势,有不同的统计数据:
每个节点被经过的次数n,总动作值w,经过这一点的先验概率p,平均动作值q (q=w/n) ,还有从别处来到这个节点走的那一步,以及从这个节点出发、所有可能的下一步。
1class Node:
2 def __init__(self, parent=None, proba=None, move=None):
3 self.p = proba
4 self.n = 0
5 self.w = 0
6 self.q = 0
7 self.children = []
8 self.parent = parent
9 self.move = move
部署 (Rollout)
第一步是PUCT (多项式上置信树) 算法,选择能让PUCT函数 (下图) 的某个变体 (Variant) 最大化,的走法。
写成代码的话——
1def select(nodes, c_puct=C_PUCT):
2 " Optimized version of the selection based of the PUCT formula "
3
4 total_count = 0
5 for i in range(nodes.shape[0]):
6 total_count += nodes[i][1]
7
8 action_scores = np.zeros(nodes.shape[0])
9 for i in range(nodes.shape[0]):
10 action_scores[i] = nodes[i][0] + c_puct * nodes[i][2] * \
11 (np.sqrt(total_count) / (1 + nodes[i][1]))
12
13 equals = np.where(action_scores == np.max(action_scores))[0]
14 if equals.shape[0] 0:
15 return np.random.choice(equals)
16 return equals[0]
结束 (Ending)
选择在不停地进行,直至到达一个叶节点 (Leaf Node) ,而这个节点还没有往下生枝。
1def is_leaf(self):
2 """ Check whether a node is a leaf or not """
3
4 return len(self.children) == 0
到了叶节点,那里的一个随机状态就会被评估,得出所有“下一步”的概率。
所有被禁的落子点,概率会变成零,然后重新把总概率归为1。
然后,这个叶节点就会生出枝节 (都是可以落子的位置,概率不为零的那些) 。代码如下——
1def expand(self, probas):
2 self.children = [Node(parent=self, move=idx, proba=probas[idx]) \
3 for idx in range(probas.shape[0]) if probas[idx] 0]
更新一下
枝节生好之后,这个叶节点和它的妈妈们,身上的统计数据都会更新,用的是下面这两串代码。
1def update(self, v):
2 """ Update the node statistics after a rollout """
3
4 self.w = self.w + v
5 self.q = self.w / self.n if self.n 0 else 0
1while current_node.parent:
2 current_node.update(v)
3 current_node = current_node.parent
选择落子点
模拟器搭好了,每个可能的“下一步”,都有了自己的统计数据。
按照这些数据,算法会选择其中一步,真要落子的地方。
选择有两种,一就是选择被模拟的次数最多的点。试用于测试和实战。
另外一种,随机 (Stochastically) 选择,把节点被经过的次数转换成概率分布,用的是以下代码——
1 total = np.sum(action_scores)
2 probas = action_scores / total
3 move = np.random.choice(action_scores.shape[0], p=probas)
后者适用于训练,让AlphaGo探索更多可能的选择。
三位一体的修炼
狗零的修炼分为三个过程,是异步的。
一是自对弈 (Self-Play) ,用来生成数据。
1def self_play():
2 while True:
3 new_player, checkpoint = load_player()
4 if new_player:
5 player = new_player
6
7 ## Create the self-play match queue of processes
8 results = create_matches(player, cores=PARALLEL_SELF_PLAY,
9 match_number=SELF_PLAY_MATCH)
10 for _ in range(SELF_PLAY_MATCH):
11 result = results.get()
12 db.insert({
13 "game": result,
14 "id": game_id
15 })
16 game_id += 1
二是训练 (Training) ,拿新鲜生成的数据,来改进当前的神经网络。
1def train():
2 criterion = AlphaLoss()
3 dataset = SelfPlayDataset()
4 player, checkpoint = load_player(current_time, loaded_version)
5 optimizer = create_optimizer(player, lr,
6 param=checkpoint['optimizer'])
7 best_player = deepcopy(player)
8 dataloader = DataLoader(dataset, collate_fn=collate_fn, \
9 batch_size=BATCH_SIZE, shuffle=True)
10
11 while True:
12 for batch_idx, (state, move, winner) in enumerate(dataloader):
13
14 ## Evaluate a copy of the current network
15 if total_ite % TRAIN_STEPS == 0:
16 pending_player = deepcopy(player)
17 result = evaluate(pending_player, best_player)
18
19 if result:
20 best_player = pending_player
21
22 example = {
23 'state': state,
24 'winner': winner,
25 'move' : move
26 }
27 optimizer.zero_grad()
28 winner, probas = pending_player.predict(example['state'])
29
30 loss = criterion(winner, example['winner'], \
31 probas, example['move'])
32 loss.backward()
33 optimizer.step()
34
35 ## Fetch new games
36 if total_ite % REFRESH_TICK == 0:
37 last_id = fetch_new_games(collection, dataset, last_id)
训练用的损失函数表示如下:
1class AlphaLoss(torch.nn.Module):
2 def __init__(self):
3 super(AlphaLoss, self).__init__()
4
5 def forward(self, pred_winner, winner, pred_probas, probas):
6 value_error = (winner - pred_winner) ** 2
7 policy_error = torch.sum((-probas *
8 (1e-6 + pred_probas).log()), 1)
9 total_error = (value_error.view(-1) + policy_error).mean()
10 return total_error
三是评估 (Evaluation) ,看训练过的智能体,比起正在生成数据的智能体,是不是更优秀了 (最优秀者回到第一步,继续生成数据) 。
1def evaluate(player, new_player):
2 results = play(player, opponent=new_player)
3 black_wins = 0
4 white_wins = 0
5
6 for result in results:
7 if result[0] == 1:
8 white_wins += 1
9 elif result[0] == 0:
10 black_wins += 1
11
12 ## Check if the trained player (black) is better than
13 ## the current best player depending on the threshold
14 if black_wins = EVAL_THRESH * len(results):
15 return True
16 return False
第三部分很重要,要不断选出最优的网络,来不断生成高质量的数据,才能提升AI的棋艺。
三个环节周而复始,才能养成强大的棋手。
有志于AI围棋的各位,也可以试一试这个PyTorch实现。
本来摘自量子位,原作 Dylan Djian。
代码实现传送门:
网页链接
教程原文传送门:
网页链接
AlphaGo Zero论文传送门:
网页链接
急求 用c++编写的人机对弈的围棋的程序代码,最好有注释!谢啦!!
int Count = 600;
AnsiString CaTimer(int Value)
{
AnsiString ss;
ss.printf("%02d:%02d:%02d",Value/(60*60), (Value%(60*60))/60,Value%60);
return ss;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
Count--;
Label1-Caption = CaTimer(Count) ;
}
// 要设置计时器 1秒钟 一次。 Timer1-Interval = 1000; (毫秒)
// 打开关闭 可以设置 Timer1 的属性 Enabled 为true , false
关于围棋代码和围棋代码java的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。
版权说明:如非注明,本站文章均为 AH站长 原创,转载请注明出处和附带本文链接;
- 上一篇:网页制作全屏代码(网页制作全屏代码的软件)
- 下一篇:闹钟代码(闹钟代码安卓)
相关推荐
- 05-09网页代码,网页代码快捷键
- 05-06单页网站的代码(完整的网页代码)[20240506更新]
- 05-06个人主页图片代码(个人主页图片代码怎么弄)[20240506更新]
- 05-06提取微信名片代码(微信名片信息提取)[20240506更新]
- 05-06php后台权限管理代码(php管理员权限)[20240506更新]
- 05-06付费观看代码php(付费观看代码)[20240506更新]
- 05-06在线html执行代码(html怎么运行)[20240506更新]
- 05-06源代码管理资源管理器(资源管理器运行代码)[20240506更新]
- 05-06代码源软件库(程序代码库)[20240506更新]
- 05-06点击弹出密码代码(点击弹出密码代码错误)[20240506更新]
取消回复欢迎 你 发表评论:
- 标签列表
- 最近发表
- 友情链接