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()
如上;棋盤是一個位圖;
在對話框構造函數中創建三個重要的用于思考的對象:
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是一個棧;
走法產生器;
根據不同的子判斷落點是否符合中國象棋規則;例如象,往四個方向走田字:
搜索引擎基類;其他搜索引擎繼承此類; //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/ // CCoolButtonCCoolButton::CCoolButton() { #ifdef XS_FLAT_BUTTONm_MouseOnButton=FALSE; #endifm_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 handlersvoid CCoolButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) {// TODO: Add your code to draw the specified itemCDC * 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_BUTTONif(IsFocused){CBrush br(RGB(0,0,0));pDC->FrameRect(&itemRect,&br);itemRect.DeflateRect(1,1);} #endif//Fill with bkcolorCBrush 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); #elseCBrush 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_BUTTONif(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);} #elsepDC->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 defaultCWnd* 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 hereif(m_MouseOnButton==TRUE){m_MouseOnButton=FALSE;Invalidate();UpdateWindow();} } #endifvoid 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算法是基于搜索的博弈算法的基礎。該算法是一種零總和算法,即一方要在可選的選項中選擇將其優勢最大化的選擇,而另一方則選擇令對手優勢最小化的方法。
總結
以上是生活随笔為你收集整理的VC++源码分析 - 中国象棋源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux DMA 驱动学习总结
- 下一篇: SQL Server 入门复习(2008