VC++源码分析 - 中国象棋源码分析

下载自

http://www.newxing.com/Code/VC/game/1750.html

运行界面如下;

看下类图;

资源;

主对话框;

源码说明:

本人机对弈程序采用了多种搜索算法.以下是本程序主要的类说明:

1.CEveluation类:估值类,对给定的棋盘进行估值.

2.CMoveGenerator类:走法产生器,对给定的棋盘局面搜索出所有可能的走法.

3.CSearchEngine类:搜索引擎基类.

4.CNegaMaxEngine类:负极大值法搜索引擎.

5.CAlphaBetaEngine类:采用了Alpha-Beta剪枝技术的搜索引擎.

6.CFAlphaBetaEngine类:fail-softalpha-beta搜索引擎.

7.CHistoryHeuristic类:历史启发类.

8.CAlphabeta_HHEngine类:带历史启发的Alpha-Beta搜索引擎.

9.CAspirationSearch类:渴望搜索引擎.

10.CIDAlphabetaEngine类:迭代深化搜索引擎.

11.CMTD_fEngine类:MTD(f)搜索引擎.

12.CTranspositionTable类:置换表.

13.CAlphaBeta_TTEngine类:加置换表的Alpha-Beta搜索引擎.

14.CPVS_Engine类:极小窗口搜索引擎.

15.CNegaScout_TT_HH类:使用了置换表和历史启发的NegaScout搜索引擎.

本程序还具有悔棋,还原功能,还可以记录走法.

那么该源码可以参照写各类搜索引擎;

下面看下其部分代码;主对话框类;

可以看到最多的函数类别是各种菜单的消息映射函数;如下;

BEGIN_MESSAGE_MAP(CChessDlg, CDialog)
	//{{AFX_MSG_MAP(CChessDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_COMMAND(IDM_SETCHESSBOARD, OnSetchessboard)
	ON_COMMAND(IDM_SET, OnSet)
	ON_COMMAND(IDM_ABOUT, OnAbout)
	ON_COMMAND(IDM_OPENFILE, OnOpenfile)
	ON_COMMAND(IDM_SAVEFILE, OnSavefile)
	ON_COMMAND(IDM_SCBOVER, OnScbover)
	ON_COMMAND(IDM_RPAWN, OnRpawn)
	ON_COMMAND(IDM_RCANON, OnRcanon)
	ON_COMMAND(IDM_RCAR, OnRcar)
	ON_COMMAND(IDM_RHORSE, OnRhorse)
	ON_COMMAND(IDM_RELEPHANT, OnRelephant)
	ON_COMMAND(IDM_RBISHOP, OnRbishop)
	ON_COMMAND(IDM_RKING, OnRking)
	ON_COMMAND(IDM_BPAWN, OnBpawn)
	ON_COMMAND(IDM_BCANON, OnBcanon)
	ON_COMMAND(IDM_BCAR, OnBcar)
	ON_COMMAND(IDM_BHORSE, OnBhorse)
	ON_COMMAND(IDM_BELEPHANT, OnBelephant)
	ON_COMMAND(IDM_BBISHOP, OnBbishop)
	ON_COMMAND(IDM_BKING, OnBking)
	ON_COMMAND(IDM_DELETE, OnDelete)
	ON_WM_RBUTTONDOWN()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_CLOSE()
	ON_COMMAND(IDM_CLEARCB, OnClearcb)
	ON_COMMAND(IDM_NEWGAME, OnNewgame)
	ON_BN_CLICKED(IDC_BTNCOMPUTER, OnBtncomputer)
	ON_BN_CLICKED(IDC_BTNUNDO, OnBtnundo)
	ON_BN_CLICKED(IDC_BTNREDO, OnBtnredo)
	ON_LBN_DBLCLK(IDC_LISTCHESSRECORD, OnDblclkListchessrecord)
	ON_BN_CLICKED(IDC_BTN_STOP, OnBtnStop)
	ON_LBN_SELCHANGE(IDC_LISTCHESSRECORD, OnSelchangeListchessrecord)
	ON_COMMAND(IDM_PREVIEW, OnPreview)
	ON_COMMAND(IDM_PREVIEWOVER, OnPreviewover)
	ON_COMMAND(IDM_HELP, OnHelp)
	ON_COMMAND(IDM_INVERSECB, OnInversecb)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

在对话框初始化函数中载入棋盘;

	BITMAP BitMap;
	m_BoardBmp.LoadBitmap(IDB_CHESSBOARD);
	m_BoardBmp.GetBitmap(&BitMap); //取BitMap 对象
	m_nBoardWidth=BitMap.bmWidth;  //棋盘宽度
	m_nBoardHeight=BitMap.bmHeight;//棋盘高度

如上;棋盘是一个位图;

在对话框构造函数中创建三个重要的用于思考的对象:

	m_pSE=new CNegaMaxEngine;//创建负极大值搜索引擎
	m_pMG=new CMoveGenerator;//创建走法产生器
	m_pEvel=new CEveluation; //创建估值核心

鼠标左键弹起时将用户走法压栈;也就是说用户走法用栈存储;

//---------将用户走法压栈---------
		m_cmBestMove.From.x=m_ptMoveChess.x;
		m_cmBestMove.From.y=m_ptMoveChess.y;
		m_cmBestMove.To.x=x;
		m_cmBestMove.To.y=y;
		m_cmBestMove.nChessID=m_MoveChess.nChessID;
		m_umUndoMove.cmChessMove=m_cmBestMove;
		m_umUndoMove.nChessID=m_byChessBoard[y][x];
		m_stackUndoMove.push(m_umUndoMove);
		//--------------------------------

......

typedef struct

{

short nChessID;  //表明是什么棋子

CHESSMANPOS From;//起始位置

CHESSMANPOS To;  //走到什么位置

int Score;       //走法的分数

}CHESSMOVE;

......

CHESSMOVE m_cmBestMove;

CHESSMOVE是一个结构体;

......

stack<UNDOMOVE> m_stackUndoMove;//记录走法的栈,便于悔棋

......

m_stackUndoMove是一个栈;

走法产生器;

根据不同的子判断落点是否符合中国象棋规则;例如象,往四个方向走田字:

void CMoveGenerator::Gen_ElephantMove(BYTE position[10][9],int i,int j,int nPly)
{
	int x,y;

	//插入右下方的有效走法
	x=j+2;
	y=i+2;
	if(x<9 && y<10 && IsValidMove(position,j,i,x,y,m_nUserChessColor))
		AddMove(j,i,x,y,nPly,position[i][j]);

	//插入右上方的有效走法
	x=j+2;
	y=i-2;
	if(x<9 && y>=0 && IsValidMove(position,j,i,x,y,m_nUserChessColor))
		AddMove(j,i,x,y,nPly,position[i][j]);

	//插入左下方的有效走法
	x=j-2;
	y=i+2;
	if(x>=0 && y<10 && IsValidMove(position,j,i,x,y,m_nUserChessColor))
		AddMove(j,i,x,y,nPly,position[i][j]);

	//插入左上方的有效走法
	x=j-2;
	y=i-2;
	if(x>=0 && y>=0 && IsValidMove(position,j,i,x,y,m_nUserChessColor))
		AddMove(j,i,x,y,nPly,position[i][j]);
}

搜索引擎基类;其他搜索引擎继承此类;

//Download by http://www.NewXing.com
// SearchEngine.h: interface for the CSearchEngine class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_SEARCHENGINE_H__7A7237B9_0908_45D8_B102_94E342B174A5__INCLUDED_)
#define AFX_SEARCHENGINE_H__7A7237B9_0908_45D8_B102_94E342B174A5__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "Eveluation.h"
#include "MoveGenerator.h"
#include "GradientProgressCtrl.h"

//搜索引擎的基类
class CSearchEngine
{
public:
	CSearchEngine();
	virtual ~CSearchEngine();

public:
	virtual SearchAGoodMove(BYTE position[10][9])=0;        //走下一步
	CHESSMOVE GetBestMove(){return m_cmBestMove;};			//得到最佳走法
	UNDOMOVE GetUndoMove(){return m_umUndoMove;};			//得到悔棋走法
	void SetSearchDepth(int nDepth){m_nSearchDepth=nDepth;};//设定最大搜索深度
	void SetEveluator(CEveluation* pEval){m_pEval=pEval;};  //设定估值引擎
	void SetMoveGenerator(CMoveGenerator* pMG){m_pMG =pMG;};//设定走法产生器
	void SetThinkProgress(CGradientProgressCtrl* pThinkProgress){m_pThinkProgress=pThinkProgress;};
															//设定显示思考进度的进度条
	void SetUserChessColor(int nUserChessColor){m_nUserChessColor=nUserChessColor;};
															//设定用户为黑方或红方

	void UndoChessMove(BYTE position[10][9],CHESSMOVE* move,BYTE nChessID);//悔棋
	void RedoChessMove(BYTE position[10][9],CHESSMOVE* move);              //还原

protected:
	int IsGameOver(BYTE position[10][9],int nDepth);//判断是否已分胜负
	BYTE MakeMove(CHESSMOVE* move);				    //根据某一走法产生走了之后的棋盘
	void UnMakeMove(CHESSMOVE* move,BYTE nChessID); //恢复为走过之前的棋盘	

public:
	int m_nUserChessColor;

protected:
	CGradientProgressCtrl* m_pThinkProgress;
								    //用以显示思考进度的进度条指针
	BYTE CurPosition[10][9];		//搜索时用于记录当前节点棋盘状态的数组
	CHESSMOVE m_cmBestMove;			//记录最佳走法
	UNDOMOVE m_umUndoMove;
	CMoveGenerator* m_pMG;			//走法产生器
	CEveluation* m_pEval;			//估值核心
	int m_nSearchDepth;				//最大搜索深度
	int m_nMaxDepth;				//当前搜索的最大搜索深度
};

#endif // !defined(AFX_SEARCHENGINE_H__7A7237B9_0908_45D8_B102_94E342B174A5__INCLUDED_)

CoolButton类;用于绘制主界面左下角的四个按钮;可以参照写自己的cool 按钮类;

//Download by http://www.NewXing.com
// CoolButton.cpp : implementation file
//

#include "stdafx.h"
#include "CoolButton.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CCoolButton

CCoolButton::CCoolButton()
{
#ifdef XS_FLAT_BUTTON
	m_MouseOnButton=FALSE;
#endif

	m_hIcon=NULL;
	m_cyIcon=0;
	m_cxIcon=0;
}

CCoolButton::~CCoolButton()
{
}

BEGIN_MESSAGE_MAP(CCoolButton, CButton)
	//{{AFX_MSG_MAP(CCoolButton)
	ON_WM_MOUSEMOVE()
	ON_WM_KILLFOCUS()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCoolButton message handlers

void CCoolButton::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
	// TODO: Add your code to draw the specified item
	CDC * pDC=CDC::FromHandle(lpDIS->hDC);

	unsigned int  IsPressed =(lpDIS->itemState&ODS_SELECTED);
	unsigned int  IsFocused =(lpDIS->itemState&ODS_FOCUS);
	unsigned int  IsDisabled =(lpDIS->itemState&ODS_DISABLED);

	CRect itemRect = lpDIS->rcItem;

#ifndef XS_FLAT_BUTTON
	if(IsFocused)
	{
		CBrush br(RGB(0,0,0));
		pDC->FrameRect(&itemRect,&br);
		itemRect.DeflateRect(1,1);
	}
#endif
	//Fill with bkcolor
	CBrush br(GetSysColor(COLOR_BTNFACE));
	pDC->FillRect(&itemRect,&br);

	//Is pressed?
	if(IsPressed)
	{
#ifdef XS_FLAT_BUTTON
		//浅边界笔
		CPen penBtnHiLight(PS_SOLID,0,GetSysColor(COLOR_BTNHILIGHT));
		//阴影笔
		CPen penBtnShadow(PS_SOLID,0,GetSysColor(COLOR_BTNSHADOW));

		//绘边界阴影
		pDC->SelectObject(penBtnShadow);
		pDC->MoveTo(itemRect.left,itemRect.bottom-1);
		pDC->LineTo(itemRect.left,itemRect.top);
		pDC->LineTo(itemRect.right,itemRect.top);
		//绘浅边界
		pDC->SelectObject(penBtnHiLight);
		pDC->MoveTo(itemRect.left,itemRect.bottom-1);
		pDC->LineTo(itemRect.right-1,itemRect.bottom-1);
		pDC->LineTo(itemRect.right-1,itemRect.top-1);
#else
		CBrush brBtnShadow(GetSysColor(COLOR_BTNSHADOW));
		pDC->FrameRect(&itemRect,&brBtnShadow);
#endif
	}
	else//没按下
	{
		CPen penBtnHiLight(PS_SOLID,0,GetSysColor(COLOR_BTNHILIGHT));
		CPen pen3DLight(PS_SOLID,0,GetSysColor(COLOR_3DLIGHT));
		CPen penBtnShadow(PS_SOLID,0,GetSysColor(COLOR_BTNSHADOW));
		CPen pen3DDKShadow(PS_SOLID,0,GetSysColor(COLOR_3DDKSHADOW));

#ifdef XS_FLAT_BUTTON
		if(m_MouseOnButton==TRUE)
		{
			pDC->SelectObject(penBtnHiLight);
			pDC->MoveTo(itemRect.left,itemRect.bottom-1);
			pDC->LineTo(itemRect.left,itemRect.top);
			pDC->LineTo(itemRect.right,itemRect.top);
			//
			pDC->SelectObject(penBtnShadow);
			pDC->MoveTo(itemRect.left,itemRect.bottom-1);
			pDC->LineTo(itemRect.right-1,itemRect.bottom-1);
			pDC->LineTo(itemRect.right-1,itemRect.top-1);
		}
#else
		pDC->SelectObject(penBtnHiLight);
		pDC->MoveTo(itemRect.left,itemRect.bottom-1);
		pDC->LineTo(itemRect.left,itemRect.top);
		pDC->LineTo(itemRect.right,itemRect.top);

		pDC->SelectObject(pen3DLight);
		pDC->MoveTo(itemRect.left+1,itemRect.bottom-1);
		pDC->LineTo(itemRect.left+1,itemRect.top+1);
		pDC->LineTo(itemRect.right,itemRect.top+1);

		pDC->SelectObject(pen3DDKShadow);
		pDC->MoveTo(itemRect.left,itemRect.bottom-1);
		pDC->LineTo(itemRect.right-1,itemRect.bottom-1);
		pDC->LineTo(itemRect.right-1,itemRect.top-1);

		pDC->SelectObject(penBtnShadow);
		pDC->MoveTo(itemRect.left+1,itemRect.bottom-2);
		pDC->LineTo(itemRect.right-2,itemRect.bottom-2);
		pDC->LineTo(itemRect.right-2,itemRect.top);
#endif
	}

#ifndef XS_FLAT_BUTTON
	//
	if(IsFocused)
	{
		CRect focusRect = itemRect;
		focusRect.DeflateRect(3,3);
		pDC->DrawFocusRect(&focusRect);
	}
#endif

	//获取文本
	CString title;
	GetWindowText(title);

	//绘制图标
	if(m_hIcon!=NULL)
	{
		CRect iconRect = lpDIS->rcItem;
		//根据标题是否存在来设置不同的图标位置
		if(title.IsEmpty()==TRUE)
		{
			iconRect.left+=((iconRect.Width()-m_cxIcon)/2);
		}
		else
		{
			iconRect.left+=6;
		}
		iconRect.top+=((iconRect.Height()-m_cyIcon)/2);

		if(IsPressed)iconRect.OffsetRect(1,1);

		pDC->DrawIcon(iconRect.TopLeft(),m_hIcon);
	}
	//绘标题
	CRect captionRect = lpDIS->rcItem;
	captionRect.left+=m_cxIcon;

	if(title.IsEmpty()==FALSE)
	{
		pDC->SetBkMode(TRANSPARENT);
		captionRect.OffsetRect(0,-1);

		if(IsPressed)
			captionRect.OffsetRect(1,1);

		if(IsDisabled)
		{
			captionRect.OffsetRect(1,1);
			pDC->SetTextColor(GetSysColor(COLOR_BTNHILIGHT));
			pDC->DrawText(title,-1,captionRect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
			captionRect.OffsetRect(-1,-1);
			pDC->SetTextColor(GetSysColor(COLOR_BTNSHADOW));
			pDC->DrawText(title,-1,captionRect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
		}
		else
		{
			pDC->DrawText(title,-1,captionRect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
		}
	}
}

#ifdef XS_FLAT_BUTTON
void CCoolButton::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default

	CWnd* pWnd;
	CWnd* pParent;

	CButton::OnMouseMove(nFlags, point);

	pWnd=GetActiveWindow();
	pParent=GetOwner();
	if((m_MouseOnButton==FALSE)&&(GetCapture()!=this)&&
		((pWnd!=NULL)&&(pWnd->m_hWnd==pParent->m_hWnd)))
	{
		SetCapture();
		SetFocus();
		m_MouseOnButton=TRUE;
		Invalidate();
		UpdateWindow();
	}
	else
	{
		CRect rc;
		GetClientRect(&rc);
		if(!rc.PtInRect(point))
		{
			m_MouseOnButton=FALSE;
			Invalidate();
			UpdateWindow();
			ReleaseCapture();
		}
	}
}
#endif

#ifdef XS_FLAT_BUTTON
void CCoolButton::OnKillFocus(CWnd* pNewWnd)
{
	CButton::OnKillFocus(pNewWnd);

	// TODO: Add your message handler code here
	if(m_MouseOnButton==TRUE)
	{
		m_MouseOnButton=FALSE;
		Invalidate();
		UpdateWindow();
	}
}
#endif

void CCoolButton::SetIcon(HICON hIcon, BYTE cx, BYTE cy)
{
	m_hIcon  = hIcon;
	m_cxIcon = cx;
	m_cyIcon = cy;
}

BOOL CCoolButton::SubclassDlgItem(UINT nID, CWnd *pParent)
{
	BOOL retValue=CButton::SubclassDlgItem(nID,pParent);

	LONG bs=::GetWindowLong(m_hWnd,GWL_STYLE);
	bs|=BS_OWNERDRAW;
	::SetWindowLong(m_hWnd,GWL_STYLE,bs);

	return retValue;
}

余下的有空再分析吧;

搜索算法是利用计算机的高性能来有目的的穷举一个问题解空间的部分或所有的可能情况,从而求出问题的解的一种方法。

搜索算法实际上是根据初始条件和扩展规则构造一棵“解答树”并寻找符合目标状态的节点的过程。

Minimax算法又名极小化极大算法,是一种找出失败的最大可能性中的最小值的算法。Minimax算法常用于棋类等由两方较量的游戏和程序,这类程序由两个游戏者轮流,每次执行一个步骤。我们众所周知的五子棋、象棋等都属于这类程序,所以说Minimax算法是基于搜索的博弈算法的基础。该算法是一种零总和算法,即一方要在可选的选项中选择将其优势最大化的选择,而另一方则选择令对手优势最小化的方法。

时间: 2024-10-16 00:51:49

VC++源码分析 - 中国象棋源码分析的相关文章

C#中国象棋+游戏大厅 服务器 + 客户端源码

来源:www.ajerp.com/bbs C#中国象棋+游戏大厅 服务器 + 客户端源码 源码开源 C#版中国象棋(附游戏大厅) 基于前人大虾的修改版 主要用委托实现 服务器支持在线人数,大厅桌数的设置 游戏互不干扰 这个象棋大厅程序完全可以当做是C#委托事件的教程,而且游戏大厅功能也很多,服务器还可设置人数和桌数,大厅客户端也实时更新相关数据. 源码下载地址:http://www.ajerp.com/bbs/forum.php?mod=viewthread&tid=29&extra=pa

android 在线升级借助开源中国App源码

http://www.cnblogs.com/luomingui/p/3949429.html android 在线升级借助开源中国App源码分析如下: 1: checkAppUpdate 检查是或需要升级 // 网络连接判断         if (appContext.isNetworkConnected()) {             // 检查新版本             if (appContext.isCheckUp()) {                    UpdateM

Tomcat源码分析之—具体启动流程分析

从Tomcat启动调用栈可知,Bootstrap类的main方法为整个Tomcat的入口,在init初始化Bootstrap类的时候为设置Catalina的工作路径也就是Catalina_HOME信息.Catalina.base信息,在initClassLoaders方法中初始化类加载器,然后通过反射初始化org.apache.catalina.startup.Catalina作为catalina守护进程: 一.load Bootstrap中load流程: 反射调用Catalina的load方法

【E2LSH源码分析】E2LSH源码综述及主要数据结构

上一小节,我们对p稳定分布LSH的基本原理进行了介绍(http://blog.csdn.net/jasonding1354/article/details/38237353),在接下来的博文中,我将以E2LSH开源代码为基础,对E2LSH的源码进行注解学习,从而为掌握LSH的基本原理以及未来对相似性搜索的扩展学习打下基础. 1.代码概况 E2LSH的核心代码可以分为3部分: LocalitySensitiveHashing.cpp--主要包含基于LSH的RNN(R-near neighbor)数

cocos2d-x 源码分析 : control 源码分析 ( 控制类组件 controlButton)

源码版本来自3.1rc 转载请注明 cocos2d-x源码分析总目录 http://blog.csdn.net/u011225840/article/details/31743129 1.继承结构 control的设计整体感觉挺美的,在父类control定义了整个控制事件的基础以及管理,虽然其继承了Layer,但其本身和UI组件的实现并没有关联.在子类(controlButton,controlSwitch,controlStepper等中实现不同的UI组件).下面通过源码来分析control与

8、SpringMVC源码分析(3):分析ModelAndView的形成过程

首先,我们还是从DispatcherServlet.doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception方法开始,看看这个牛逼的ModelAndView是怎么开始的,又是怎么结束的: 1 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Except

Solr4.8.0源码分析(5)之查询流程分析总述

Solr4.8.0源码分析(5)之查询流程分析总述 前面已经写到,solr查询是通过http发送命令,solr servlet接受并进行处理.所以solr的查询流程从SolrDispatchsFilter的dofilter开始.dofilter包含了对http的各个请求的操作.Solr的查询方式有很多,比如q,fq等,本章只关注select和q.页面下发的查询请求如下:http://localhost:8080/solr/test/select?q=code%3A%E8%BE%BD*+AND+l

C++、VC++、MFC网页自动注册、登陆、发帖、留言,QQ注册、QQ申请器源码、注册邮箱源码、自动发帖源码

C++.VC++.MFC网页自动注册.登陆.发帖.留言,QQ注册.QQ申请器源码.注册邮箱源码.自动发帖源码 参考资料: 自动登录yahoo邮箱http://blog.csdn.net/suisuibianbian/archive/2005/12/12/550260.aspx VC采集网页所有表单域http://blog.csdn.net/fjssharpsword/archive/2010/12/17/6081689.aspx 说说这类软件最常见的使用方式吧. 也许你经常看到有人发布了以下这类

cocos2d-x 源码分析 之 CCTableView源码分析(附使用方法讨论)

cocos2d-x源码总目录 http://blog.csdn.net/u011225840/article/details/31743129 源码来自2.x,转载请注明 1.继承结构 首先来看下CCTableView的继承结构 从继承结构上看,CCTableView是一种CCScrollView,所以为了研究CCTableView的源码,清先去了解CCScrollView的源码http://blog.csdn.net/u011225840/article/details/30033501. 其