五子棋AI循序渐进【1】实现界面和位棋盘
2012-07-11 20:46
686 查看
先把这一个传上来,关于局面评价的72向量和综合比较、超出边界的alpha-beta剪裁如何说明更清楚还得再考虑一下,以免表述的不清楚。因为这两部分的代码是整个代码中最核心最重要也是最长的。仅仅是下一集更新的源码就超过600行。当然了,逻辑是非常非常清晰的,因为很多都是重复的逻辑内容——硬编码模板就这样哎。而超出边界的alpha-beta剪裁,是整个程序中最难理解的部分,说难理解不仅是因为递归,更重要的是这种剪裁的思想。剩余的各个部分都非常好理解,编码也很少了。就像将军延伸和空步剪裁也就十行八行的代码就实现了。而静态搜索只是照着alpha-beta剪裁代码稍微一改而已。好了,不多说闲话。
注:从这一篇开始都会对实现的内容首先进行解释,然后传本集的完整源码,源码都是VB2010编写的。
一、位棋盘
1、为什么用位棋盘
按照通常我们的做法,可以用数组board(224),数据类型可以是byte,integer等,但是我们浪费很多存储空间,当然这还不是主要问题,主要问题是速度太慢。原因很简单,寻址远慢于从integer中取某一位。
2、如何实现位棋盘
我们需要一个225位的数据类型,这种长度的数据类型是没有的,所以可以用integer数组来实现。幸好,VB.NET给我们提供了bitarray类,而这个类的内部实现实际上也是用integer数组的。但是问题也随之而来:1位只能是0或者1,而我们要表示白棋、黑棋、空三种数据,怎么办?其实很好解决,可以用2字代表一个位置,或者使用2个bitarray。我的程序采取第二种办法:
Private wBitArr As BitArray
Private bBitArr As BitArray
3、如何操作位棋盘
直接上代码:
'位棋盘
Public Class mBitBoard
'用bitarray代替byte数组,提高读写速度。(bitarray内部实现是用integer数组,每一个元素是32字节,所以寻址速度要比用byte数组快很多)
'0=白方,1=黑方,2=空
Private wBitArr As BitArray
Private bBitArr As BitArray
'15*15的棋盘。
Sub New()
wBitArr = New BitArray(225)
bBitArr = New BitArray(225)
End Sub
'设置棋子
Sub [Set](index As Integer, value As Integer)
If value = 0 Then
wBitArr.Set(index, True)
ElseIf value = 1 Then
bBitArr.Set(index, True)
Else
bBitArr.Set(index, False)
wBitArr.Set(index, False)
End If
End Sub
'获取棋子
Function [Get](index As Integer) As Integer
If wBitArr.Get(index) Then Return 0
If bBitArr.Get(index) Then Return 1
Return 2
End Function
End Class
很清晰吧。这个类在后来进行了一些小的修改——增加了一个函数。当然这不是我们现在要讨论的问题。好了,现在已经有了棋盘的表示方法,那么我们来实现界面。其实界面简单得不能再简单了:
二、五子棋界面
1、搜索或者自己画棋盘和棋子
2、获取棋子偏移量、棋子大小、棋盘大小
3、根据mBitBoard实例绘制棋子
我实现的时候在窗体上面画了一个panel,命名为pnlBoard。而后写了这样一个函数:
'绘制棋子
Private Sub pnlBoard_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles pnlBoard.Paint
e.Graphics.DrawImage(My.Resources._2064, Point.Empty)
For i As Integer = 0 To 224
If ucpcSquares.Get(i) = 1 Then e.Graphics.DrawImage(bb, New Point((i Mod 15) * cs.Height, (i \ 15) * cs.Height) + co)
If ucpcSquares.Get(i) = 0 Then e.Graphics.DrawImage(bw, New Point((i Mod 15) * cs.Height, (i \ 15) * cs.Height) + co)
Next
End Sub
首先绘制棋盘图像,然后绘制棋子。
下子的代码是这样的:
'下子
Private Sub pnlBoard_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles pnlBoard.MouseDown
Dim sdr = CType(sender, Panel)
'鼠标坐标转棋盘坐标
Dim p As Point = e.Location - co
p.X \= cs.Width
p.Y \= cs.Height
'下一个白子
If e.Button = Windows.Forms.MouseButtons.Left Then
ucpcSquares.Set(p.Y * 15 + p.X, 0)
'更新显示
pnlBoard_Paint(sdr, New PaintEventArgs(sdr.CreateGraphics, sdr.DisplayRectangle))
End If
End Sub
很简单不是吗。
完整的代码如下:
Public Class Form1
'黑白棋子
Private bb As Bitmap
Private bw As Bitmap
'棋子偏移
Private co As Point = New Point(5, 5)
'棋子大小
Private cs As Size = New Size(25, 25)
'位棋盘
Private ucpcSquares As mBitBoard
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
'初始化棋子
Dim resbmp As Bitmap = New Bitmap(My.Resources._7041, cs.Width * 4, cs.Height)
Dim allbmp As Bitmap = New Bitmap(resbmp.Width \ 2, resbmp.Height)
'获取棋子图像
For y As Integer = 0 To allbmp.Height - 1
For x As Integer = 0 To allbmp.Width - 1
If resbmp.GetPixel(x + allbmp.Width, y).ToArgb = Color.Black.ToArgb Then allbmp.SetPixel(x, y, resbmp.GetPixel(x, y))
Next
Next
bb = allbmp.Clone(New Rectangle(0, 0, allbmp.Width / 2, allbmp.Height), allbmp.PixelFormat)
bw = allbmp.Clone(New Rectangle(allbmp.Width / 2, 0, allbmp.Width / 2, allbmp.Height), allbmp.PixelFormat)
'==========================开局棋型可在这里设置==============================
ucpcSquares = New mBitBoard()
ucpcSquares.Set(7 * 15 + 7, 1)
End Sub
'绘制棋子
Private Sub pnlBoard_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles pnlBoard.Paint
e.Graphics.DrawImage(My.Resources._2064, Point.Empty)
For i As Integer = 0 To 224
If ucpcSquares.Get(i) = 1 Then e.Graphics.DrawImage(bb, New Point((i Mod 15) * cs.Height, (i \ 15) * cs.Height) + co)
If ucpcSquares.Get(i) = 0 Then e.Graphics.DrawImage(bw, New Point((i Mod 15) * cs.Height, (i \ 15) * cs.Height) + co)
Next
End Sub
'下子
Private Sub pnlBoard_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles pnlBoard.MouseDown
Dim sdr = CType(sender, Panel)
'鼠标坐标转棋盘坐标
Dim p As Point = e.Location - co
p.X \= cs.Width
p.Y \= cs.Height
'下一个白子
If e.Button = Windows.Forms.MouseButtons.Left Then
ucpcSquares.Set(p.Y * 15 + p.X, 0)
'更新显示
pnlBoard_Paint(sdr, New PaintEventArgs(sdr.CreateGraphics, sdr.DisplayRectangle))
End If
End Sub
End Class
其中2064号资源是棋盘,7041是4个图组成的:黑子、白子、各自的掩码图。我没有使用掩码图,呵呵,用了一个循环。我的懒人原则是,初始化代码,能省事就省事……
完整示例代码:
/Files/zcsor/清月连珠0.1.7z
全部文章和源码整理完成,以后更新也会在下面地址:
http://www.vbdevelopers.org
http://www.softos.org
注:从这一篇开始都会对实现的内容首先进行解释,然后传本集的完整源码,源码都是VB2010编写的。
一、位棋盘
1、为什么用位棋盘
按照通常我们的做法,可以用数组board(224),数据类型可以是byte,integer等,但是我们浪费很多存储空间,当然这还不是主要问题,主要问题是速度太慢。原因很简单,寻址远慢于从integer中取某一位。
2、如何实现位棋盘
我们需要一个225位的数据类型,这种长度的数据类型是没有的,所以可以用integer数组来实现。幸好,VB.NET给我们提供了bitarray类,而这个类的内部实现实际上也是用integer数组的。但是问题也随之而来:1位只能是0或者1,而我们要表示白棋、黑棋、空三种数据,怎么办?其实很好解决,可以用2字代表一个位置,或者使用2个bitarray。我的程序采取第二种办法:
Private wBitArr As BitArray
Private bBitArr As BitArray
3、如何操作位棋盘
直接上代码:
'位棋盘
Public Class mBitBoard
'用bitarray代替byte数组,提高读写速度。(bitarray内部实现是用integer数组,每一个元素是32字节,所以寻址速度要比用byte数组快很多)
'0=白方,1=黑方,2=空
Private wBitArr As BitArray
Private bBitArr As BitArray
'15*15的棋盘。
Sub New()
wBitArr = New BitArray(225)
bBitArr = New BitArray(225)
End Sub
'设置棋子
Sub [Set](index As Integer, value As Integer)
If value = 0 Then
wBitArr.Set(index, True)
ElseIf value = 1 Then
bBitArr.Set(index, True)
Else
bBitArr.Set(index, False)
wBitArr.Set(index, False)
End If
End Sub
'获取棋子
Function [Get](index As Integer) As Integer
If wBitArr.Get(index) Then Return 0
If bBitArr.Get(index) Then Return 1
Return 2
End Function
End Class
很清晰吧。这个类在后来进行了一些小的修改——增加了一个函数。当然这不是我们现在要讨论的问题。好了,现在已经有了棋盘的表示方法,那么我们来实现界面。其实界面简单得不能再简单了:
二、五子棋界面
1、搜索或者自己画棋盘和棋子
2、获取棋子偏移量、棋子大小、棋盘大小
3、根据mBitBoard实例绘制棋子
我实现的时候在窗体上面画了一个panel,命名为pnlBoard。而后写了这样一个函数:
'绘制棋子
Private Sub pnlBoard_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles pnlBoard.Paint
e.Graphics.DrawImage(My.Resources._2064, Point.Empty)
For i As Integer = 0 To 224
If ucpcSquares.Get(i) = 1 Then e.Graphics.DrawImage(bb, New Point((i Mod 15) * cs.Height, (i \ 15) * cs.Height) + co)
If ucpcSquares.Get(i) = 0 Then e.Graphics.DrawImage(bw, New Point((i Mod 15) * cs.Height, (i \ 15) * cs.Height) + co)
Next
End Sub
首先绘制棋盘图像,然后绘制棋子。
下子的代码是这样的:
'下子
Private Sub pnlBoard_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles pnlBoard.MouseDown
Dim sdr = CType(sender, Panel)
'鼠标坐标转棋盘坐标
Dim p As Point = e.Location - co
p.X \= cs.Width
p.Y \= cs.Height
'下一个白子
If e.Button = Windows.Forms.MouseButtons.Left Then
ucpcSquares.Set(p.Y * 15 + p.X, 0)
'更新显示
pnlBoard_Paint(sdr, New PaintEventArgs(sdr.CreateGraphics, sdr.DisplayRectangle))
End If
End Sub
很简单不是吗。
完整的代码如下:
Public Class Form1
'黑白棋子
Private bb As Bitmap
Private bw As Bitmap
'棋子偏移
Private co As Point = New Point(5, 5)
'棋子大小
Private cs As Size = New Size(25, 25)
'位棋盘
Private ucpcSquares As mBitBoard
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
'初始化棋子
Dim resbmp As Bitmap = New Bitmap(My.Resources._7041, cs.Width * 4, cs.Height)
Dim allbmp As Bitmap = New Bitmap(resbmp.Width \ 2, resbmp.Height)
'获取棋子图像
For y As Integer = 0 To allbmp.Height - 1
For x As Integer = 0 To allbmp.Width - 1
If resbmp.GetPixel(x + allbmp.Width, y).ToArgb = Color.Black.ToArgb Then allbmp.SetPixel(x, y, resbmp.GetPixel(x, y))
Next
Next
bb = allbmp.Clone(New Rectangle(0, 0, allbmp.Width / 2, allbmp.Height), allbmp.PixelFormat)
bw = allbmp.Clone(New Rectangle(allbmp.Width / 2, 0, allbmp.Width / 2, allbmp.Height), allbmp.PixelFormat)
'==========================开局棋型可在这里设置==============================
ucpcSquares = New mBitBoard()
ucpcSquares.Set(7 * 15 + 7, 1)
End Sub
'绘制棋子
Private Sub pnlBoard_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles pnlBoard.Paint
e.Graphics.DrawImage(My.Resources._2064, Point.Empty)
For i As Integer = 0 To 224
If ucpcSquares.Get(i) = 1 Then e.Graphics.DrawImage(bb, New Point((i Mod 15) * cs.Height, (i \ 15) * cs.Height) + co)
If ucpcSquares.Get(i) = 0 Then e.Graphics.DrawImage(bw, New Point((i Mod 15) * cs.Height, (i \ 15) * cs.Height) + co)
Next
End Sub
'下子
Private Sub pnlBoard_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles pnlBoard.MouseDown
Dim sdr = CType(sender, Panel)
'鼠标坐标转棋盘坐标
Dim p As Point = e.Location - co
p.X \= cs.Width
p.Y \= cs.Height
'下一个白子
If e.Button = Windows.Forms.MouseButtons.Left Then
ucpcSquares.Set(p.Y * 15 + p.X, 0)
'更新显示
pnlBoard_Paint(sdr, New PaintEventArgs(sdr.CreateGraphics, sdr.DisplayRectangle))
End If
End Sub
End Class
其中2064号资源是棋盘,7041是4个图组成的:黑子、白子、各自的掩码图。我没有使用掩码图,呵呵,用了一个循环。我的懒人原则是,初始化代码,能省事就省事……
完整示例代码:
/Files/zcsor/清月连珠0.1.7z
全部文章和源码整理完成,以后更新也会在下面地址:
http://www.vbdevelopers.org
http://www.softos.org
相关文章推荐
- 网页五子棋的实现--界面和AI实现
- 循序渐进实现仿QQ界面(三):界面调色与控件自绘
- 循序渐进实现仿QQ界面(四):圆形按钮与工具栏自绘
- 五子棋AI循序渐进【5】重点问题重点分析——静态搜索
- 循序渐进实现仿QQ界面(二):贴图按钮的三态模拟
- 循序渐进实现仿QQ界面(四):圆形按钮与工具栏自绘
- (转载)十四步实现拥有强大AI的五子棋游戏
- 【五子棋AI循序渐进】关于VCT,VCF的思考和核心代码
- 循序渐进实现仿QQ界面(五):半透明窗体与不透明控件
- 五子棋AI算法简易实现(一)
- 用cocos2d-x 实现的带ai的五子棋
- 五子棋AI循序渐进【0】引言——认识“引擎”
- canvas实现五子棋界面
- 基于C++实现五子棋AI算法思想
- js实现五子棋(含AI)
- 五子棋AI算法简易实现(三)
- vc循序渐进实现仿QQ界面(一):圆角矩形与双缓冲贴图窗口
- 【五子棋AI循序渐进】发布一个完整的有一定棋力的版本(含源码)
- 循序渐进实现仿QQ界面(四):圆形按钮与工具栏自绘
- 五子棋AI算法简易实现(二)