C++围棋程序实现报告.docx
- 文档编号:25250319
- 上传时间:2023-06-06
- 格式:DOCX
- 页数:32
- 大小:120.77KB
C++围棋程序实现报告.docx
《C++围棋程序实现报告.docx》由会员分享,可在线阅读,更多相关《C++围棋程序实现报告.docx(32页珍藏版)》请在冰豆网上搜索。
C++围棋程序实现报告
一、软件背景介绍
围棋是一项广有裨益的智力竞技运动,它集休闲娱乐、陶冶性情、修心养性于一身,是中华文化的瑰宝,是人类智慧的最高象征之一。
围棋经历了数千年,久盛不衰,且至今还在不断发展。
现在的人工智能科学研究在它面前显得很是稚嫩,因而值得将它作为重要的研究对象。
在人工智能领域内,博弈是很重要的一个研究分支。
通过对博弈的研究,可以解决很多实际问题,使计算机智能向人类智能迈进。
计算机国际象棋和计算机围棋一直是人工智能的热门课题,而围棋程序的编制被称作人工智能的“试金石”,是人工智能技术的一大难题,它将会在今后相当长的时期内哺育着人工智能科学的成长。
计算机围棋是计算机博弈研究的一个重要分支,是当前人工智能研究的热点之一,一直以来吸引着大量的研究人员,产生了较大的社会影响和学术影响。
由于围棋变化复杂、棋理深奥,是一种高智能的活动,因而围棋的计算机博弈设计难度较大,同时计算机围棋热点问题的研究为人工智能带来了崭新的方法和理论。
计算机围棋的研究和实现需要多门学科的知识交叉,至少会涉及到围棋、计算机、数学、生物、逻辑学、军事学、教育、心理学乃至哲学等领域,因此其发展具有重要的研究价值和应用价值。
本系统是基于C++编程语言的立足于“人―人”围棋对弈系统的设计与实现,具有围棋记谱、打谱、查看定式、最终评分等功能,是一个适宜在计算机上联网的“人―人”的对弈系统。
围棋胜负判断与局面分析功能子系统是围棋对弈系统的重要组成部分。
围棋胜负自动判断是一个实用的围棋对弈系统所应具有的功能。
在现实的围棋胜负判断中,往往需要一个裁判员通过做棋来判断棋局最终的胜负。
如果有一个客观、准确的围棋自动判断胜负系统,一方面可以省时省力,一方面可以做到客观公正。
但实现一个具有人(裁判员)一样的判断能力的胜负判断系统,存在着许多困难和挑战。
本系统通过建立棋局的记录来判断棋盘上每一点的归属,从而确定棋局中双方地域,故能够对提掉死子后的终局棋盘用中国规则判断胜负;通过建立棋子的影响模型、力学模型以及度量公式,将棋子向棋盘其它部分辐射的影响量化,从而判断对弈双方的影响领域。
论文主要介绍了围棋对弈系统中胜负判断与局面分析功能子系统具有的功能,论述了子系统的开发和实现的过程。
该围棋游戏的主界面如图1。
图1围棋主界面
二、核心算法思想
该围棋软件主要是由以下三种算法组成的:
1、使每个棋子周围产生某种影响,这种影响随着距离的增加而减少,用一定的公式计算叠加种影响,以判断形势和估计着点的价值。
这与围棋的棋理相通,即对于每个棋子可估算其“势力”。
此中就有著名的“气位”理论。
2、建立模式库,贮存了大量模式(定式、棋形等),以供匹配。
这其实涉及到围棋的许多棋谚与棋理。
如“二子头必扳”、“镇以飞应”、“断从一边长”、三子正中、点方等等。
这些都是根据围棋的具体情况而设计的。
3、对目标明确的局部,用人工智能中的搜索法探求其结果。
(一)围棋局面分析功能的实现
这里定义了Stone的数据结构,用于记录每一点与棋盘上已落棋子的距离和受到的影响值,定义如下:
PublicTypeStone
ValueAsInteger
DistanceAsInteger
EndType
需要定义显示地域时的棋谱PublicMap(1To19,1To19)AsStone,用于记录最后的累加影响。
其中Map上每一点Map(i,j)的Distance与value的关系为:
Value=2的(6-Distance)次方。
Map(i,j)的最终影响要通过计算影响模型,递减定律以及反射定律,经过度量公式计算,大于定值A的点显示为黑棋地域,小于-A的点显示为白棋地域。
(二)影响模型
由于棋盘上的每个棋子都要对盘面发出影响,设黑棋影响为正,白棋影响为负。
棋盘上的每一点要受到多个棋子的累加影响,其中,受到该点最近的棋子影响最大,依次递减。
设这影响在棋子的紧邻(距离为1)为最大值32,并随距离增加而按比例衰减,衰减因子为1/2。
就是距离每增加1时影响值减半。
此时一黑子对其周围辐射的影响如图2。
1
121
12421
1248421
1248168421
12481632168421
124816326432168421
12481632168421
1248168421
1248421
12421
121
1
图2系统使用的影响模型
影响模型的实现,采用循环嵌套,对一已落的棋子(i,j),计算其对周边的影响,定义变量row,column,对于满足i-6<=row<=i+6,i-6<=column<=i+6的点,(row,column)的距离distance为︱row-i︱+︱column-j︱,并记录到显示棋谱Map(19,19)中。
(三)力学模型
棋盘上的每一个棋子,都向周围四个方向发出影响,通过这种影响实现对空点的占领和棋子之间的相互作用,这种影响可以被视为一种控制力,沿四个方向大小相等,而黑白棋子产生的控制力符号相反。
控制力产生后,沿它的方向向前传播,其传播方式遵守如下规律:
1、递减规律
控制力遇到一个点后,力的大小被减弱,符号方向不变地继续向前传播。
如果遇到空点,减弱后的控制力变为原来的一个常数倍(取1/2),该常数被称为传播率;如果遇到有子点,沿原方向的控制力消减。
棋子(i,j)在传播过程中,如遇到另一棋子(m,n),则同方向的距离distance+2,即受到的影响值减1/4倍。
2、反射定律
由于在围棋中边角更容易受到棋子的影响,有“金角银边”之称。
故在实现时设计了反射定律。
控制力到达棋盘边缘后,会被反射回来,该反射力与原控制力方向相反,符号相同,大小为原控制力的一个常数倍,该常数被称为反射率。
实现时,棋子(i,j)在传播过程中,利用row,column双重循环,如遇到row=1或19,则同方向的距离distance-︱row-i︱;如遇到column=1或19,则同方向的距离distance-︱column-j︱。
每一个点都受到四个方向的控制力的作用,任一方向的控制力的大小是这个点所受这个方向所有控制力的代数和。
在实际计算时,取:
(1)任意棋子产生的初始控制力的大小为64;
(2)黑子的影响为正、白子的影响为负;
(3)传播率为1/2;
(4)反射率为1;
3、度量公式
在得到任一棋盘状态下个空点影响的分布图后,可以由这些影响值经过计算得到一些棋盘状态的深层信息,一些常用的度量公式如下。
设一个点受到的四个控制力大小为:
向上F0,向右F1,向下F2,向左F3。
总力:
F=F0+F1+F2+F3表示一个点受到某一方影响的度量。
F﹥0:
受黑的影响强一些;
F﹤0:
受白的影响强一些;
F=0:
双方的影响基本平衡。
4、判定双方的势力范围
对于每一点,它受到的总控制力F=F0+F1+F2+F3,当|F|大于某一数值n时,将其显示为地域。
当F﹥0时受黑的影响强一些,该点能被黑方所控制,作为黑方实地,显示为黑方地域,反之,为白棋的势力范围。
在显示中规定:
如果该点所受四个方向的力均大于0,且F大于20,则该点为黑方势力范围。
对于白方的势力范围有类似的判断规则。
(四)围棋胜负的判断方法
双方下子完毕的棋局,计算胜负采用数子法。
先将双方死子全部清理出盘外,然后对一方的活棋(包括活棋围住的点)以子为单位进行计数。
双方活棋之间的空点各得一半,一个点即为一子。
胜负的基准以棋局总点数的一半180又1/2点为归本数。
凡一方活棋与所属空点的总和大于此数者为胜,小于此数者为负,等于此数者为和。
三、核心算法流程图
(一)判定双方的势力范围
对于每一点,它受到的总控制力F=F0+F1+F2+F3,当|F|大于某一数值n时,将其显示为地域。
当F﹥0时受黑的影响强一些,该点能被黑方所控制,作为黑方实地,显示为黑方地域,反之为白棋的势力范围。
在显示中规定:
如果该点所受四个方向的力均大于0,且F大于20,则该点为黑方势力范围。
对于白方的势力范围有类似的判断规则。
双方的势力范围的实现流程图如图3。
是否
否
否
是
图3局面分析实现流程图
(二)判断围棋输赢
这里定义了Item的数据结构,用于记录每一枚棋子的颜色及搜索的状态:
PublicTypeItems
ValueAsInteger
CheckedAsBoolean
EndType
定义终局棋谱数组:
Publicm_GameOverMap(1To19,1To19)AsItems,终局的每一结点存储为Item结构,记录每一点的归属。
对待盘棋局(用m_Map(19,19)记录)上每一点用循环扫描,记录每一点是哪一方的领域。
下图为判断围棋胜负的流程图。
判断胜负
总数加1
帖子计算
总数减1
显示胜负
白
总数减1
填入白子
行数〈=19
列数〈=19
结束
被同色棋子围
计为单官
计为单官
确定该点颜色
总数加1
填入黑子
单官为奇数
该黑方落子
是
判断胜负
行数<=19
列数<=19
被同色棋包围
否
否
是
是
黑
否
否
是
图4胜负判断实现流程图
四、源代码
下面给出的是实现联网对战游戏的源代码:
#include"MyStack.h"
#include"MyList.h"
#include"MyOutFunction.h"
#pragmaonce
#include
usingnamespacestd;
#if_MSC_VER>1000
#pragmaonce
#endif//_MSC_VER>1000
structpoint
{
intp_x;//x坐标,1-19间的整数
intp_y;//y坐标,1-19间的整数
intcolor;//所放棋子颜色,1为黑,2为白
};
struct_node
{
pointdata;
_node*next;
_node*pre;
};
classCChessPos
{
public:
BOOLvisit_for_DeadOrLive;//访问标识,用于递归算法
BOOLvisit_for_DeleteDead;
CRectchessman(CPointpoint);//该位置所在矩形区域
intnFlag;//该位置状态标识
CPointpoint;//该位置坐标
CChessPos*pLeft;//指向该位置的四个邻接点
CChessPos*pRight;
CChessPos*pTop;
CChessPos*pBottom;
CChessPos();
virtual~CChessPos();
};
#include"mscomm.h"
#include"SelectComm.h"
#include"ChessPos.h"
#if_MSC_VER>1000
#pragmaonce
#endif//_MSC_VER>1000
constintDIE=0;//表示空位或死棋
constintBLACK=1;//黑棋
constintWHITE=2;//白棋
constintEDGE=3;//边界以外
classMyList
{
public:
voidinit();
MyList();
virtual~MyList();
_node*head;
_node*now;
_node*tail;
intsize;
voidadd(_node*newNode);
voidadd(intx,inty,intcolor);
boolisEmpty();
voidprintList();//根据函数format定义的格式遍历链表,step记录结点遍历到了第几个结点
voidprintList(void(*format)(void*e,void*steptag),intstep);
voiddel();//删除链表最后一个元素
voidclearList();//清空链表
boolsearchele(intx,inty);//遍历链表
};
struct_state
//保存棋盘中每个格子的临时状态,以判别处于该位置的棋子是否能存活
{
intx;//在棋盘中的横坐标
inty;//在棋盘中的纵坐标
intfangxiang;
intcolor;
intfootprint;
intdead;//处于此格子的棋子可能死亡
};
struct_statenode
{
_states;
_statenode*next;
};
classMyStack
{
public:
_statenode*head;
intsize;//堆栈大小
MyStack();
virtual~MyStack();
voidinit();//初始化
voidpush(_state*s);//入栈
_state*pop();//出栈
boolisEmpty();//判断是否为空
voidprint();//输出
};
};
ON_COMMAND(ID_APP_ABOUT,OnAppAbout)//ClassWizard将添加和删除映射宏。
//DONOTEDITwhatyouseeintheseblocksofgeneratedcode!
//}}AFX_MSG_MAP//基于标准的文件文档的命令
ON_COMMAND(ID_FILE_NEW,CWinApp:
:
OnFileNew)
ON_COMMAND(ID_FILE_OPEN,CWinApp:
:
OnFileOpen)//标准的打印设置命令
ON_COMMAND(ID_FILE_PRINT_SETUP,CWinApp:
:
OnFilePrintSetup)
END_MESSAGE_MAP()
public:
CAboutDlg();
//DialogData
//{{AFX_DATA(CAboutDlg)
enum{IDD=IDD_ABOUTBOX};
}}
//Attributes
public:
CPointpointBegin;//左上角坐标
intnDistance;//每格间距
intnRadium;//点的半径
intr;//围棋半径
intnCount;//下的数目
CRectm_rectEllipse[19][19];//当前围棋子所在矩形
intnSign[21][21];//点标志
intnOldSign[21][21];//吃掉前的标志
intnChainRow[19][20];//存放水平方向的点标志之间的关系
intnChainCol[20][19];//存放竖直方向的点标志之间的关系
intnBorder;//棋盘边界宽度
intnBackSign[21][21];//前次位置标志备份
intnBackTwoTimesBeforeSign[21][21];//前两次位置标志备份
intnBackThreeTimesBeforeSign[21][21];//前两次位置标志备份
intnBackOldSign[21][21];
intnBackChainRow[19][20];
intnBackChainCol[20][19];
intnBackCount;
intnBackCountTwoTimesBefore;//前两次统计备份
CPointpointForGoPrompt;//下子提示点
CPointpointForRegret;//悔棋按钮
CPointpointForWhiteCalculate;//显示统计时白棋标志的位置
CPointpointForBlackCalculate;
CPointpointForIllegal;//非法提示
intnCalculateWhite;//白子统计
intnCalculateBlack;//黑子统计
intnBackCalculateWhite;//白子统计备份
intnBackCalculateBlack;//黑子统计备份
BOOLfIllegal;//非法走步标志
BOOLfRegretOnlyOnce;//只许悔棋一次
//===============================================//
//位图有关定时器有关
//===============================================//
CBitmapm_BitmapToRight;
CRectm_rectBitmapToRight;
intm_nBitmapToRightHeight;
intm_nBitmapToRightWidth;
CBitmapm_BitmapToLeft;
CRectm_rectBitmapToLeft;
intm_nBitmapToLeftHeight;
intm_nBitmapToLeftWidth;
struct_statenode
{
_states;
_statenode*next;
};
classMyStack
{
public:
_statenode*head;
intsize;//堆栈大小
MyStack();
virtual~MyStack();
UINTm_timer;//计时器标志
BOOLm_fAlternate;
BOOLm_fClear;
//Operations
public:
virtualBOOLOnNewDocument();
virtualvoidSerialize(CArchive&ar);
};
CAboutDlg:
:
CAboutDlg():
CDialog(CAboutDlg:
:
IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
voidCAboutDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
classCWQDoc:
publicCDocument
{
protected:
//createfromserializationonly
CWQDoc();
DECLARE_DYNCREATE(CWQDoc)
public:
virtualBOOLOnNewDocument();
virtualvoidSerialize(CArchive&ar);
public:
BOOLm_bGameStartEnable;//"开始游戏"是否有效
BOOLInitialization();//新建文档初始化函数
BOOLm_bEnable;//判断是否可以落子
UINTnGameMode;//游戏模式
UINTnComNum;//所选择的串口号
CMSCommm_MSComm;//定义串口对象m_MSComm
BOOLreback;//悔棋enable标识
intbackup_scene[19][19];//备份前次场景
intcur_scene[19][19];//当前场景
intpre_scene[19][19];//前次场景
intlast_scene[19][19];//上次场景
#ifdef_DEBUG
virtualvoidAssertValid()const;
virtualvoidDump(CDumpContext&dc)const;
#endif
MyList();
virtual~MyList();
_node*head;
_node*now;
_node*tail;
intsize;
voidadd(_node*newNode);
voidadd(intx,inty,intcolor);
boolisEmpty();
voidprintList();//根据函数format定义的格式遍历链表,step记录结点遍历到了第几个结点
voidprintList(void(*format)(void*e,void*steptag),intstep);
voiddel();//删除链表最后一个元素
voidclearList();
boolsearchele(intx,inty);
};
#include"PublicStruct.h"
classCWeiQi
{
public:
CWeiQi();
virtual~CWeiQi();
public:
BOOLTiZi(intx,inty);
shortGetPointType(intx,inty);
voidClearNodes();
voidInit();
voidInit2();//小棋盘
voidClearBoardFlag();
protected:
classCWeiQ1_0View:
publicCView
{
protected:
CWeiQ1_0View();
DECLARE_DYNCREATE(CWeiQ1_0View)
private:
voidDrawChessboard(CDC*pDC,CPointtop_left,COLORREFbkcolor,intspace,intradius);
};
protected:
//{{AFX_MSG(CW
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C+ 围棋 程序 实现 报告