围棋打谱程序之棋盘类(包括提子,子串搜索,打劫,禁手等判断)

原创 2004年07月04日 06:23:00

?

/**************************************************************************************/
?* 功能:?棋盘类
?* 描述:?用于描述和计算棋盘上的棋子状态, 气, 子串
?*???提子等判断。
?* 作者:?Chen Rong
?* 时间:?2004-6-7 2:24
?*
?* History:
?*???2004-6-7 2:24 :实现了子串的搜索, 串的气判断。 使用了 ArrayList 类, 以后效率
?*???????如果要优化, 可改写成数组。
? **************************************************************************************/

using System;
using System.Collections;
using System.Drawing;

namespace ChenRong.Weiqi
{
?///
?/// Board 的摘要说明。
?///
?public class Board
?{
??public static readonly int Black = -1;
??public static readonly int Empty = 0;
??public static readonly int White = 1;

??// 棋子数组
??private int[,] stones;?
??// 最后一步杀死的棋子数
??public int LastKillCount = 0;

??// 上下左右偏移量数组, 用于判断某位置周围四个点的情况
??private int[,] offsets = new int[4, 2] { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1} };

??// 构造函数(constructor)
??public Board()
??{
???this.stones = new int[19, 19];
???this.SetForNewGame();
??}

??// 复制棋盘
??public Board(Board board)
??{
???this.stones = board.stones;
???this.LastKillCount = board.LastKillCount;
??}

??// 初始化
??public void SetForNewGame()
??{
???for (int i = 0; i < 19; i++)
???{
????for (int j = 0; j < 19; j++)
????{
?????stones[i, j] = Board.Empty;
????}
???}
???this.LastKillCount = 0;
??}

??// 得到棋盘上某个位置的状态
??public int GetPointContent(int row, int col)
??{
???return this.stones[row, col];
??}

??// 判断一个着点是否有效??注: 有待改进, 还需要判断不能自杀, 不能连续提劫等规则限制, 目前先不考虑
??public bool IsValidMove(int color, int row, int col)
??{
???if (this.stones[row, col] != Board.Empty)???
????return false;
???else
???{
????// 复制一个棋盘, 作为备份
????Board board = new Board(this);
????// 在复制的棋盘演练: 试落一子????
????board.stones[row, col] = color;
????ArrayList chuanSelf = board.FindChuan(row, col);

????// 不会自杀, 则返回
????if (board.CountChuanGas(chuanSelf) > 0)??
????{
?????return true;
????}
????// 如果落子会自杀, 判断是否会杀死地方的子, 如果不能则这一手不是有效着点
????// (先不考虑打劫的复杂判断)
????else
????{
?????// 恢复状态, 试落下一子, 看能否提别人的子
?????board.stones[row, col] = Board.Empty;
?????board.MakeMove(color, row, col);
?????if (board.LastKillCount > 0)
??????return true;
?????else
?????{
??????// 必须使用下面这一句把它恢复到空状态, 不加则会出错, 不知道为什么??
??????this.stones[row, col] = Board.Empty;
??????return false;
?????}
????}????
???}???
??}

??// 走一步, 并提去死子
??public void MakeMove(int color, int row, int col)
??{???
???this.stones[row, col] = color;

???ArrayList stonesDead = new ArrayList();??// 死子集合
???ArrayList stonesVisited = new ArrayList();?// 访问过的点的集合

???// 开始判断并提去死子
???int newx, newy;
???for (int i = 0; i < 4; i++)
???{
????newx = row + offsets[i, 0];
????newy = col + offsets[i, 1];????

????if (newx >= 0 && newx < 19 && newy >= 0 && newy < 19)
????{
?????if (this.stones[newx, newy] == (- color))
?????{
??????// 如果目前位置已经在前面某个方向的探索过程中找到, 则不用判断了。
??????// 因为不同方向的棋子可能是属于同一个串的
??????if (! stonesVisited.Contains(new Point(newx, newy)))
??????{
???????// 寻找包含该位置的串
???????ArrayList chuan = this.FindChuan(newx, newy);
???????// 算串的气
???????int chuanGas = this.CountChuanGas(chuan);
???????// 加到已访问的列表
???????stonesVisited.AddRange(chuan);

???????if (chuanGas == 0)
???????{
????????stonesDead.AddRange(chuan);
???????}
??????}
?????}
????}
???}

???// 提掉死子
???for (int i = 1; i <= stonesDead.Count; i++)
???{
????Point p = (Point) stonesDead[i - 1];
????this.stones[p.X, p.Y] = Board.Empty;
???}

???// 更新提子数
???this.LastKillCount = stonesDead.Count;
??}

??// 算气
??public int CountGas(int row, int col)
??{
???int gas = 0;
???int newx, newy;
???for (int i = 0; i < 4; i++)
???{
????newx = row + this.offsets[i, 0];
????newy = col + this.offsets[i, 1];

????if (newx >= 0 && newx < 19 && newy >= 0 && newy < 19)
????{
?????if (this.stones[newx, newy] == Board.Empty)
??????gas++;
????}
???}
???return gas;
??}


??///
??/// 棋子串搜索
??/// 寻找包含该位置的棋子串
??///
??/// <备注>
??///??广度优先的遍历算法
??/// 备注>
??/// 起始点的 X 坐标
??/// 起始点的 Y 坐标
??/// 搜索到的棋子串(没找到则返回 null)?
??public ArrayList FindChuan(int row, int col)
??{
???ArrayList chuan = null;??????
???int color = this.stones[row, col];?// 当前的颜色

???if (this.stones[row, col] == color)
???{
????chuan = new ArrayList();
????// 加入当前点
????chuan.Add(new Point(row, col));
????// 定义两个游标
????int begin = 0;
????int end = 0;
????
????int findCount;?// 发现的邻居数目, 用于循环结束的判断条件
????do
????{
?????findCount = 0;
?????// begin 到 end 之间的一些点表示没有探索过四周的那些点
?????for (int i = begin; i <= end; i++)
?????{
??????// 对左右上下四个方向进行探索
??????for (int j = 0; j < 4; j++)
??????{
???????int newx = ((Point) chuan[i]).X + offsets[j, 0];
???????int newy = ((Point) chuan[i]).Y + offsets[j, 1];
???????
???????// 如果该点在棋盘内, 且颜色相同, 且现有的串中没有, 则加入串
???????if (newx >= 0 && newx < 19 && newy >= 0 && newy < 19
????????&& this.stones[newx, newy] == color
????????&& ! chuan.Contains(new Point(newx, newy)))
???????{
????????chuan.Add(new Point(newx, newy));
????????// 寻找到的邻居计数器加 1
????????findCount += 1;
???????}
??????}
?????}
?????// 设定下一个循环要列举的开始和结束游标
?????begin = end + 1;
?????end = end + findCount;
????}
????// 如果本轮搜索的所有点都没有邻居了, 也就表示串搜索结束了, 跳出循环
????while (findCount > 0);
???}

???// 测试: 返回搜到的字串中棋子数目
???// return chuan.Count;

???return chuan;??
??}

??// 算串的气
??public int CountChuanGas(ArrayList chuan)
??{
???if (chuan == null)
????return 0;
???int gas = 0;
???for (int i = 0; i < chuan.Count; i++)
???{
????gas += this.CountGas(((Point) chuan[i]).X, ((Point) chuan[i]).Y);
???}
???return gas;
??}
?}
}

华为机试—围棋吃子(下围棋)判决(高级题160分:深度优先遍历)(图文吐血整理)

题目: 围棋中,一个棋子在棋盘上,与它直接紧邻的空点是这个棋子的“气”,棋子直接紧邻的点上,如果有同色妻子存在,则它们便相互组成一个不可分割的整体,它们的“气”也应一并计算。如果一个或一片棋子的“气...
  • wtyvhreal
  • wtyvhreal
  • 2015年01月12日 00:14
  • 17890

游戏开发(三)——WIN32 黑白棋(一)——棋局逻辑的设计

今天以黑白棋为例,开始给一个win32的小游戏设计, 这里打算分3部分介绍 1、棋局的现实 2、AI的现实 3、游戏画面的现实 提供一下完整项目下载 其中第一部分为黑白棋游戏的主要逻辑: 1、棋...
  • zilaishuichina
  • zilaishuichina
  • 2014年07月28日 20:14
  • 2210

五子棋AI算法第六篇-迭代加深

前面讲到了算杀,其实在算杀之前应该讲一下迭代加深。因为这些文章是我边做边写的一些笔记,所以顺序上可能不是那么严谨。AI没有找到最优解按照前面的所有算法实现之后(当然不包括算杀),会发现一个比较严重的问...
  • lihongxun945
  • lihongxun945
  • 2016年02月29日 11:16
  • 3385

简单的围棋棋盘打谱设计C#实现

博主接触围棋一段时间了,也挺有意思的,于是想用C#做一下围棋的软件,结果发现好多功能的算法不会啊。。。现在只做了基本的功能,嗯,可以自己打谱练习。后面博主还要研究一下数目和形势判断的算法,也请各位大侠...
  • wf824284257
  • wf824284257
  • 2017年01月31日 03:23
  • 1047

新浪围棋棋谱打谱程序V1.0

  • 2009年12月07日 08:53
  • 41KB
  • 下载

网页版开源围棋打谱工具源代码(含windowsPC版、Linux版及示例)

  • 2018年01月10日 11:25
  • 1.07MB
  • 下载

围棋打谱

  • 2006年03月16日 00:00
  • 141KB
  • 下载

围棋打谱工具

  • 2015年08月13日 12:27
  • 932KB
  • 下载

gogame 围棋 对弈 局域网 打谱

  • 2007年11月30日 20:17
  • 1.01MB
  • 下载

用OpenCV编程计算围棋棋盘黑白子总数

今天柯洁开始对战AlphaGo,虽然对围棋一窍不通,但这种大事我也在关注,知道胜负与最后棋盘上黑白子的数量有关。当我看到结局的棋盘时,黑白棋子那么多,一时也看不出来谁多谁少,就想着编个程序来计算一下。...
  • sinat_28309919
  • sinat_28309919
  • 2017年05月23日 15:05
  • 999
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:围棋打谱程序之棋盘类(包括提子,子串搜索,打劫,禁手等判断)
举报原因:
原因补充:

(最多只允许输入30个字)