?

/**************************************************************************************/
?* 功能:?棋盘类
?* 描述:?用于描述和计算棋盘上的棋子状态, 气, 子串
?*???提子等判断。
?* 作者:?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;
??}
?}
}

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

  1. 围棋博弈程序的实现与思考(4)——棋盘的数据结构

    UCT算法算是介绍完了,以后主要讲实践. 由于在面向对象的编程语言中,本人只会C++和Objective-C(以后也许会写一些iOS开发相关的博文),出于性能的考虑,选择C++是必然的.记得当初开题答 ...

  2. 学号java_java ---- 定义一个表示学生的类 包括域“学号”、“班号”、“姓名”、“年龄”;...

    1.编写一个JAVA类程序片段,定义一个表示学生的类student,包括域"学号"."班号"."姓名"."年龄":方法& ...

  3. 棋盘类游戏中的栅格地形渲染

    棋盘类游戏中的栅格地形渲染 张嘉华 梁成 李桂清 (华南理工大学计算机科学与工程学院 广东 广州 510640) 摘要:本文提出了适合战棋类游戏的三维栅格地形渲染策略,把Catmull-Clark细分 ...

  4. 计算机技术分队指挥类,公安指挥类包括哪些专业

    公安指挥类包括哪些专业2017-06-24 15:07:02文/梁羽辉 公安指挥类专业包括警察指挥与战术.边防指挥.船艇指挥.通信指挥.消防指挥.参谋业务.抢险救援. 专业名称专业代码 公安指挥类68 ...

  5. 写一个简单的打谱程序(1)

    陪儿子上围棋课时我希望有一个能在freerunner手机上运行的打谱程序,用来记录儿子和同学的对局.我开始以为随便找一个打谱程序,在freerunner手机环境编译一下就可以了.但我找来cgoban. ...

  6. java输入字符串异常_设计一个 Java 程序,自定义异常类,从命令行(键盘)输入一个字符串,如果该字符串值为“XYZ”。。。...

    设计一个 Java 程序,自定义异常类,从命令行(键盘)输入一个字符串,如果该字符串值为"XYZ",则抛出一个异常信息"This is a XYZ",如果从命令 ...

  7. boost::program_options模块一个配置ini文件被解析程序选项库,它包括许多不同的值类型的测试程序

    boost::program_options模块一个配置ini文件被解析程序选项库,它包括许多不同的值类型的测试程序 实现功能 C++实现代码 实现功能 boost::program_options模 ...

  8. C语言输出长方柱的体积,需要求3个长方柱的体积,请编写一个基于对象的程序。数据成员包括length(长)、width(宽)、 height(高)。要求用成员函数实现以下功能...

    需要求3个长方柱的体积,请编写一个基于对象的程序.数据成员包括length(长).width(宽). height(高).要求用成员函数实现以下功能: (1) 由键盘分别输入3个长方柱的长.宽.高: ...

  9. 计算机专业和文秘专业哪个好,文秘类包括哪些专业

    文秘类专业包括文秘.文秘速录. 专业名称专业代码 文秘类670300 文秘670301 文秘速录670302 文秘类专业介绍 一.文秘专业 开设课程 : 秘书理论与实务.档案管理.秘书心理学.秘书英语 ...

最新文章

  1. Apollo创建项目
  2. oracle10g配置失败6,Oracle10g DataGuard中ORA-16026错误解决-入门基础-Oracle频道-中国IT实验室...
  3. C语言获取系统当前时间的两种方式
  4. c mysql导入数据_MySQL 数据导入
  5. Java实现一个会员制度的CD出租销售店,基本的功能有:一是对会员的管理,包括增加会员、删除会员;二是对货品的管理,包括出租、销售CD、进货、统计账目等。
  6. 根据共享文件夹的权限进行自动映射网络驱动器
  7. C盘爆满给Android Studio瘦身将sdk移除C盘
  8. html5初学者小游戏源代码,html5 一个“一笔画”小游戏源码(通关)
  9. matlab数据归一化mapminmax函数
  10. Xshell上传文件到Ubuntu服务器
  11. 计算机基本办公软件应用技能有哪些,办公人员应掌握哪些办公软件技能
  12. 程序员自己的商业模式
  13. Comparing JSON and XML? Stop it!
  14. 基于asp.net的排球赛事网站设计与实现
  15. [BZOJ]1059: [ZJOI2007]矩阵游戏
  16. ArcGIS打开影像图显示全黑色解决办法
  17. DASCTFNepCTF 部分writeup
  18. 【深度探讨】数据存储进化论,区块链才是未来
  19. 《CCNA学习指南:Cisco网络设备互连(ICND2)(第4版)》——1.1节理解VLAN 和VLAN Trunk 及排除相关故障...
  20. Intellij IDEA中快速实现接口方法的快捷键

热门文章

  1. java jdk 是什么_java中的jdk是做什么用的?
  2. 关于springcloud中eureka server端配置的一些总结
  3. 将PPT转化为长图(长截图)【Python方法】
  4. Android设置手机壁纸(WallPaper)
  5. C++ 将当前系统时间转换成标准格式的时间和时间戳
  6. dabs是什么意思_kswl是什么意思 网络用语弹幕KSWL是什么意思含义介绍
  7. android常用控件实验报告,常用控件的编程实验报告
  8. 写C#代码时用到的中文简体字 、繁体字 对应的转化 (收藏吧)
  9. 论文阅读:Hierarchical Attention Transfer Network for Cross-Domain Sentiment Classification
  10. 最新实用Python异步爬虫代理池(开源)