www.pudn.com > 1223456.rar > ChessDlg.cpp


// ChessDlg.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "Chess.h" 
#include "ChessDlg.h" 
#include "NegamaxEngine.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
#define GRILLEWIDTH  39//棋盘上每个格子的宽度 
#define GRILLEHEIGHT 39//棋盘上每个格子的高度 
 
const BYTE InitChessBoard[10][9]= 
{ 
	{B_CAR,B_HORSE,B_ELEPHANT,B_BISHOP,B_KING,B_BISHOP,B_ELEPHANT,B_HORSE,B_CAR}, 
	{NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS}, 
	{NOCHESS,B_CANON,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,B_CANON,NOCHESS}, 
	{B_PAWN,NOCHESS,B_PAWN,NOCHESS,B_PAWN,NOCHESS,B_PAWN,NOCHESS,B_PAWN}, 
	{NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS}, 
	               //楚河                       汉界// 
	{NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS}, 
	{R_PAWN,NOCHESS,R_PAWN,NOCHESS,R_PAWN,NOCHESS,R_PAWN,NOCHESS,R_PAWN}, 
	{NOCHESS,R_CANON,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,R_CANON,NOCHESS}, 
	{NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS}, 
	{R_CAR,R_HORSE,R_ELEPHANT,R_BISHOP,R_KING,R_BISHOP,R_ELEPHANT,R_HORSE,R_CAR} 
}; 
 
///////////////////////////////////////////////////////////////////////////// 
// CAboutDlg dialog used for App About 
 
//电脑思考线程函数 
DWORD WINAPI ThinkProc(LPVOID pParam) 
{ 
	CChessDlg* pDlg=(CChessDlg*)pParam; 
 
	pDlg->Think(); 
 
	return 0; 
} 
 
class CAboutDlg : public CDialog 
{ 
public: 
	CAboutDlg(); 
 
// Dialog Data 
	//{{AFX_DATA(CAboutDlg) 
	enum { IDD = IDD_ABOUTBOX }; 
	CButton	m_btnOk; 
	//}}AFX_DATA 
 
	// ClassWizard generated virtual function overrides 
	//{{AFX_VIRTUAL(CAboutDlg) 
	protected: 
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support 
	//}}AFX_VIRTUAL 
 
// Implementation 
protected: 
	CBitmap m_bitmapOk; 
 
	//{{AFX_MSG(CAboutDlg) 
	virtual BOOL OnInitDialog(); 
	//}}AFX_MSG 
	DECLARE_MESSAGE_MAP() 
}; 
 
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) 
{ 
	//{{AFX_DATA_INIT(CAboutDlg) 
	//}}AFX_DATA_INIT 
	m_bitmapOk.LoadBitmap(IDB_OK); 
} 
 
void CAboutDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CAboutDlg) 
	DDX_Control(pDX, IDOK, m_btnOk); 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 
	//{{AFX_MSG_MAP(CAboutDlg) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CChessDlg dialog 
 
CChessDlg::CChessDlg(CWnd* pParent /*=NULL*/) 
	: CDialog(CChessDlg::IDD, pParent) 
{ 
	//{{AFX_DATA_INIT(CChessDlg) 
	m_strOutputInfo = _T(" 欢迎使用中国象棋      作者:陶善文"); 
	//}}AFX_DATA_INIT 
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
	m_hUndoIcon=AfxGetApp()->LoadIcon(IDI_UNDO); 
	m_hRedoIcon=AfxGetApp()->LoadIcon(IDI_REDO); 
	m_hComputerIcon=AfxGetApp()->LoadIcon(IDI_COMPUTER); 
	m_hStopIcon=AfxGetApp()->LoadIcon(IDI_STOP); 
 
	m_iWhoChess=REDCHESS; 
	m_Status=Chessing; 
	m_bIsGameOver=false; 
	m_nUserChessColor=REDCHESS; 
	m_pMG=new CMoveGenerator;	 
	m_bIsThinking=false; 
	m_nWillChessColor=REDCHESS; 
	m_bIsBegin=false; 
	m_iBout=0; 
	m_strWelcome=" 欢迎使用中国象棋      作者:陶善文"; 
 
	m_pSE=new CNegaMaxEngine;//创建负极大值搜索引擎 
	m_pMG=new CMoveGenerator;//创建走法产生器 
	m_pEvel=new CEveluation; //创建估值核心 
} 
 
void CChessDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CChessDlg) 
	DDX_Control(pDX, IDC_BTN_STOP, m_btnStop); 
	DDX_Control(pDX, IDC_BTNUNDO, m_btnUndo); 
	DDX_Control(pDX, IDC_BTNREDO, m_btnRedo); 
	DDX_Control(pDX, IDC_BTNCOMPUTER, m_btnComputer); 
	DDX_Control(pDX, IDC_LISTCHESSRECORD, m_lstChessRecord); 
	DDX_Control(pDX, IDC_PROGRESSTHINK, m_progressThink); 
	DDX_Control(pDX, IDC_OUTPUTINFO, m_staticTip); 
	DDX_Text(pDX, IDC_OUTPUTINFO, m_strOutputInfo); 
	//}}AFX_DATA_MAP 
} 
 
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() 
 
///////////////////////////////////////////////////////////////////////////// 
// CChessDlg message handlers 
 
BOOL CChessDlg::OnInitDialog() 
{ 
	CDialog::OnInitDialog(); 
 
	// Add "About..." menu item to system menu. 
 
	// IDM_ABOUTBOX must be in the system command range. 
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 
	ASSERT(IDM_ABOUTBOX < 0xF000); 
 
	CMenu* pSysMenu = GetSystemMenu(FALSE); 
	if (pSysMenu != NULL) 
	{ 
		CString strAboutMenu; 
		strAboutMenu.LoadString(IDS_ABOUTBOX); 
		if (!strAboutMenu.IsEmpty()) 
		{ 
			pSysMenu->AppendMenu(MF_SEPARATOR); 
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 
		} 
	} 
 
	// Set the icon for this dialog.  The framework does this automatically 
	//  when the application's main window is not a dialog 
	SetIcon(m_hIcon, TRUE);			// Set big icon 
	SetIcon(m_hIcon, FALSE);		// Set small icon 
	 
	// TODO: Add extra initialization here 
	m_btnComputer.SetIcon(m_hComputerIcon,32,32); 
	m_btnStop.SetIcon(m_hStopIcon,32,32); 
	m_btnUndo.SetIcon(m_hUndoIcon,32,32); 
	m_btnRedo.SetIcon(m_hRedoIcon,32,32); 
 
	//彩色进度条设置 
	m_progressThink.SetStartColor(RGB(0xFF,0xFF,0x00));//黄色 
	m_progressThink.SetEndColor(RGB(0x00,0x93,0x00));  //绿色 
	m_progressThink.SetBkColor(RGB(0xE6,0xE6,0xFA));   //淡紫色 
	m_progressThink.SetTextColor(RGB(0,0,255)); 
	m_progressThink.ShowPercent(1); 
 
	m_tooltip.Create(this); 
	m_tooltip.Activate(1); 
	m_tooltip.AddTool(GetDlgItem(IDC_LISTCHESSRECORD),"单击条目可以预览以前局面,双击条目可以快捷悔棋"); 
 
	m_Chessman.Create(IDB_CHESSMAN,36,14,RGB(0,255,0));//创建含有棋子图形的ImgList,用于绘制棋子 
 
	//下面这段代码取棋盘图形的宽,高 
	BITMAP BitMap; 
	m_BoardBmp.LoadBitmap(IDB_CHESSBOARD); 
	m_BoardBmp.GetBitmap(&BitMap); //取BitMap 对象 
	m_nBoardWidth=BitMap.bmWidth;  //棋盘宽度 
	m_nBoardHeight=BitMap.bmHeight;//棋盘高度 
 
	m_BoardBmp.DeleteObject(); 
 
	memcpy(m_byChessBoard,InitChessBoard,90);//初始化棋盘 
	memcpy(m_byShowChessBoard,InitChessBoard,90); 
	memcpy(m_byBackupChessBoard,InitChessBoard,90); 
 
	m_pSE->SetSearchDepth(3);      //设定搜索层数为3 
	m_pSE->SetMoveGenerator(m_pMG);//给搜索引擎设定走法产生器 
	m_pSE->SetEveluator(m_pEvel);  //给搜索引擎设定估值核心 
	m_pSE->SetUserChessColor(m_nUserChessColor); 
								   //设定用户为黑方或红方 
	m_pSE->SetThinkProgress(&m_progressThink); 
								   //设定进度条 
 
	m_MoveChess.nChessID=NOCHESS;//将移动的棋子清空 
 
	return TRUE;  // return TRUE  unless you set the focus to a control 
} 
 
void CChessDlg::OnSysCommand(UINT nID, LPARAM lParam) 
{ 
	if ((nID & 0xFFF0) == IDM_ABOUTBOX) 
	{ 
		CAboutDlg dlgAbout; 
		dlgAbout.DoModal(); 
	} 
	else 
	{ 
		CDialog::OnSysCommand(nID, lParam); 
	} 
} 
 
// If you add a minimize button to your dialog, you will need the code below 
//  to draw the icon.  For MFC applications using the document/view model, 
//  this is automatically done for you by the framework. 
 
void CChessDlg::OnPaint()  
{ 
	CPaintDC dc(this); 
	CDC MemDC; 
	int i,j; 
	POINT pt; 
	CBitmap* pOldBmp; 
 
	MemDC.CreateCompatibleDC(&dc); 
	m_BoardBmp.LoadBitmap(IDB_CHESSBOARD); 
	pOldBmp=MemDC.SelectObject(&m_BoardBmp); 
	 
	//绘制棋盘上的棋子 
	for(i=0;i<10;i++) 
		for(j=0;j<9;j++) 
		{			 
			if(m_byShowChessBoard[i][j]==NOCHESS) 
				continue; 
 
			pt.x=j*GRILLEHEIGHT+14; 
			pt.y=i*GRILLEWIDTH+15; 
			m_Chessman.Draw(&MemDC,m_byShowChessBoard[i][j]-1,pt,ILD_TRANSPARENT); 
		} 
 
	//绘制用户正在拖动的棋子 
	if(m_MoveChess.nChessID!=NOCHESS) 
		m_Chessman.Draw(&MemDC,m_MoveChess.nChessID-1,m_MoveChess.ptMovePoint,ILD_TRANSPARENT); 
	dc.BitBlt(0,0,m_nBoardWidth,m_nBoardHeight,&MemDC,0,0,SRCCOPY); 
								 //将绘制的内容刷新到屏幕 
	MemDC.SelectObject(&pOldBmp);//恢复内存Dc的原位图	 
	MemDC.DeleteDC();            //释放内存	  
	m_BoardBmp.DeleteObject();   //删除棋盘位图对象 
} 
 
// The system calls this to obtain the cursor to display while the user drags 
//  the minimized window. 
HCURSOR CChessDlg::OnQueryDragIcon() 
{ 
	return (HCURSOR) m_hIcon; 
} 
 
void CChessDlg::OnLButtonDown(UINT nFlags, CPoint point)  
{ 
	// TODO: Add your message handler code here and/or call default 
	if(m_iChessSort==CS_CCCHESS) 
	{ 
		m_staticTip.SetWindowText(m_strWelcome); 
		return; 
	} 
 
	if(m_Status==Previewing) 
	{ 
		m_staticTip.SetWindowText("现在处于预览状态,如要下棋,请弹出右键菜单点 预览完毕"); 
 
		return; 
	} 
 
	if(m_bIsGameOver) 
	{ 
		m_staticTip.SetWindowText("老兄,这盘棋下完了"); 
 
		return; 
	} 
 
	if(m_bIsThinking)//电脑正在想 
		return; 
 
	int x,y; 
 
	//将坐标换算成棋盘上的格子 
	y=(point.y-14)/GRILLEHEIGHT; 
	x=(point.x-15)/GRILLEWIDTH; 
		 
	//判断鼠标是否在棋盘内,并且点中了用户棋子 
	if(y>=0 && y<10 && x>=0 && x<9 && (m_nUserChessColor==REDCHESS?IsRed(m_byChessBoard[y][x]):IsBlack(m_byChessBoard[y][x]))) 
	{ 
		memcpy(m_byBackupChessBoard,m_byChessBoard,90);//备份棋盘 
		 
		//将当前棋子的信息装入,记录移动棋子的结构中 
		m_ptMoveChess.x=x; 
		m_ptMoveChess.y=y; 
		m_MoveChess.nChessID=m_byChessBoard[y][x]; 
		 
		//将该棋子原位置棋子去掉 
		m_byChessBoard[y][x]=NOCHESS; 
		m_byShowChessBoard[y][x]=NOCHESS; 
		 
		//让棋子中点坐标位于鼠标所在点 
		point.x-=18; 
		point.y-=18; 
		m_MoveChess.ptMovePoint=point; 
		//重绘屏幕 
		InvalidateRect(NULL,FALSE); 
		UpdateWindow(); 
		SetCapture();//独占鼠标焦点 
	} 
	else 
		if(m_Status==Chessing) 
			if(y>=0 && y<10 && x>=0 && x<9 && (m_nUserChessColor!=REDCHESS?IsRed(m_byChessBoard[y][x]):IsBlack(m_byChessBoard[y][x]))) 
				m_staticTip.SetWindowText("不好意思,这是我的棋子,请你不要乱动"); 
			else 
				m_staticTip.SetWindowText("老兄,那又没有棋子,你瞎点什么啊"); 
 
	CDialog::OnLButtonDown(nFlags, point); 
} 
 
void CChessDlg::OnLButtonUp(UINT nFlags, CPoint point)  
{ 
	// TODO: Add your message handler code here and/or call default 
	if(m_Status!=Chessing) 
		return; 
 
	if(m_bIsGameOver) 
	{ 
		m_staticTip.SetWindowText("老兄,这盘棋下完了"); 
		return; 
	} 
 
	if(m_bIsThinking || m_Status!=Chessing) 
		return; 
 
	BOOL bTurnSide=FALSE; 
	int x,y; 
	CString str; 
 
    //将坐标换算成棋盘上的格子  
	y=(point.y-14)/GRILLEHEIGHT; 
	x=(point.x-15)/GRILLEWIDTH; 
	 
	//判断是否有移动棋子,并且该棋子的移动是一个合法走法 
//	if(m_MoveChess.nChessID && CMoveGenerator::IsValidMove(m_byBackupChessBoard,m_ptMoveChess.x,m_ptMoveChess.y,x,y,m_nUserChessColor)) 
	if(m_MoveChess.nChessID && m_pMG->IsValidMove(m_byBackupChessBoard,m_ptMoveChess.x,m_ptMoveChess.y,x,y,m_nUserChessColor)) 
	{ 
		//---------将用户走法压栈--------- 
		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); 
		//-------------------------------- 
 
		m_btnUndo.EnableWindow(1);//激活悔棋按钮 
		 
		if(m_nUserChessColor==REDCHESS) 
			m_iBout++; 
		this->AddChessRecord(m_ptMoveChess.x+1,m_ptMoveChess.y+1,x+1,y+1,m_nUserChessColor,m_MoveChess.nChessID); 
		m_byChessBoard[y][x]=m_MoveChess.nChessID; 
		m_byShowChessBoard[y][x]=m_MoveChess.nChessID; 
		bTurnSide=TRUE; 
	} 
	else//否则恢复移动前的棋盘状态 
	{ 
		memcpy(m_byShowChessBoard,m_byBackupChessBoard,90); 
		memcpy(m_byChessBoard,m_byBackupChessBoard,90); 
	} 
     
	m_MoveChess.nChessID=NOCHESS;//将移动的棋子清空 
 
	//重绘屏幕   
	InvalidateRect(NULL,FALSE); 
	UpdateWindow();	 
	ReleaseCapture();//释放鼠标焦点 
 
	if(bTurnSide==TRUE) 
	{ 
		m_btnStop.EnableWindow(1); 
		m_hHandle=::CreateThread(0,0,ThinkProc,this,0,&m_dwThreadID); 
	} 
	else 
		m_staticTip.SetWindowText(m_strWelcome); 
 
	CDialog::OnLButtonUp(nFlags,point); 
} 
 
void CChessDlg::OnMouseMove(UINT nFlags, CPoint point)  
{ 
	// TODO: Add your message handler code here and/or call default 
	if(m_bIsThinking) 
		return; 
 
	if(m_MoveChess.nChessID) 
	{ 
		if(m_Status==Chessing) 
		{ 
			//防止将棋子拖出棋盘 
			if(point.x<15)//左边 
				point.x=15; 
			if(point.y<15)//上边 
				point.y=15; 
			if(point.x>m_nBoardWidth-15)//右边				 
				point.x=m_nBoardWidth-15; 
			if(point.y>m_nBoardHeight-15)//下边				 
				point.y=m_nBoardHeight-15; 
			 
			//让棋子中心位于鼠标所在处 
			point.x-=18; 
			point.y-=18; 
			 
			m_MoveChess.ptMovePoint=point;//保存移动棋子的坐标	 
		} 
		else 
		{ 
			//让棋子中心位于鼠标所在处 
			point.x-=18; 
			point.y-=18; 
			 
			m_MoveChess.ptMovePoint=point;//保存移动棋子的坐标	 
 
			//棋子拖出棋盘时将该棋子删掉 
			if(point.x<15 || point.y<15 || point.x>m_nBoardWidth-15 || point.y>m_nBoardHeight-15) 
				m_byChessBoard[m_ptMoveChess.y][m_ptMoveChess.x]=NOCHESS; 
		} 
 
		InvalidateRect(NULL,FALSE);//刷新窗口 
		UpdateWindow();//立即执行刷新 
	} 
 
	CDialog::OnMouseMove(nFlags, point); 
} 
 
void CChessDlg::OnSetchessboard()  
{ 
	// TODO: Add your command handler code here 
	m_strOutputInfo=" 点击鼠标右键,可以增加棋子和删除棋子"; 
	UpdateData(false); 
	m_Status=SetChessBoarding; 
} 
 
void CChessDlg::OnSet()  
{ 
	// TODO: Add your command handler code here 
	if(m_bIsThinking || m_SetDlg.DoModal()==IDCANCEL) 
		return; 
 
	if(m_pSE) 
		delete m_pSE;//释放旧的搜索引擎 
	 
	if(m_nUserChessColor!=m_SetDlg.GetUserChessColor()) 
		this->InvertChessBoard(m_byChessBoard); 
	m_nUserChessColor=m_SetDlg.GetUserChessColor(); 
	m_iChessSort=m_SetDlg.GetChessSort(); 
	m_iDepthSort=m_SetDlg.GetDepthSort(); 
 
	if(m_iChessSort==CS_PCCHESS || m_iChessSort==CS_PPCHESS) 
		m_btnComputer.EnableWindow(0); 
	else 
		m_btnComputer.EnableWindow(1); 
 
	switch(m_SetDlg.GetSelectedEngine()) 
	{ 
	case 0: 
		m_pSE=new CNegaMaxEngine; 
		break; 
		 
	case 1: 
		m_pSE=new CAlphaBetaEngine;//创建alpha-beta搜索引擎 
		break; 
		 
	case 2: 
		m_pSE=new CFAlphaBetaEngine; 
		break; 
		 
	case 3: 
		m_pSE=new CAspirationSearch; 
		break; 
		 
	case 4: 
		m_pSE=new CPVS_Engine; 
		break; 
		 
	case 5: 
		m_pSE=new CIDAlphabetaEngine; 
		break; 
		 
	case 6: 
		m_pSE=new CAlphaBeta_TTEngine; 
		break; 
		 
	case 7: 
		m_pSE=new CAlphabeta_HHEngine; 
		break; 
		 
	case 8: 
		m_pSE=new CMTD_fEngine; 
		break; 
		 
	default: 
		m_pSE=new CNegaMaxEngine; 
		break; 
	} 
	m_pMG=new CMoveGenerator;//创建走法产生器 
	m_pEvel=new CEveluation; //创建估值核心 
 
	m_pSE->SetSearchDepth(m_SetDlg.GetSelectedPly()); 
	m_pSE->SetUserChessColor(m_nUserChessColor); 
	m_pSE->SetMoveGenerator(m_pMG);//将走法产生器传给搜索引擎 
	m_pSE->SetEveluator(m_pEvel);  //将估值核心传给搜索引擎 
	m_pSE->SetThinkProgress(&m_progressThink); 
								   //设定进度条 
 
	m_pEvel->ClearAccessCount(); 
} 
 
void CChessDlg::OnAbout()  
{ 
	// TODO: Add your command handler code here 
	CAboutDlg dlg; 
 
	dlg.DoModal(); 
} 
 
void CChessDlg::OnOpenfile()  
{ 
	// TODO: Add your command handler code here 
	CFileDialog m_OpenDlg(TRUE,NULL,"",0,"棋谱(*.cm)|*.cm||"); 
	 
	if(m_OpenDlg.DoModal()==IDCANCEL)  
		return; 
 
	CString strCMFile; 
	char* pCMFile; 
	FILE* fp; 
	int i,j; 
	int nUserChessColor; 
 
	strCMFile=m_OpenDlg.GetPathName(); 
	pCMFile=(LPSTR)(LPCTSTR)strCMFile; 
 
	fp=fopen(pCMFile,"r"); 
	if(fp==NULL) 
	{ 
		MessageBox("打开文件出错","错误提示",MB_ICONWARNING); 
		return; 
	} 
 
	if(MessageBox("是否覆盖当前棋局?","友情提醒",MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2)==IDNO) 
		return; 
 
	for(i=0;i<10;i++) 
		for(j=0;j<9;j++) 
			fscanf(fp,"%3d",&m_byChessBoard[i][j]); 
 
	fclose(fp); 
 
	for(i=7;i<10;i++) 
		for(j=3;j<6;j++) 
		{ 
			if(m_byChessBoard[i][j]==B_KING) 
			{ 
				nUserChessColor=BLACKCHESS; 
				break; 
			} 
			if(m_byChessBoard[i][j]==R_KING) 
			{ 
				nUserChessColor=REDCHESS; 
				break; 
			} 
		} 
	if(nUserChessColor!=m_nUserChessColor) 
		this->InvertChessBoard(m_byChessBoard); 
 
	m_bIsBegin=false; 
 
	//刷新屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnSavefile()  
{ 
	// TODO: Add your command handler code here 
	CFileDialog m_SaveDlg(false,NULL,"",0,"棋谱(*.cm)|*.cm||"); 
	 
	if(m_SaveDlg.DoModal()==IDCANCEL)  
		return; 
 
	CString strCMFile; 
	char* pCMFile; 
	FILE* fp; 
	int i,j; 
 
	strCMFile=m_SaveDlg.GetPathName(); 
	pCMFile=(LPSTR)(LPCTSTR)strCMFile; 
 
	fp=fopen(pCMFile,"w"); 
	if(fp==NULL) 
	{ 
		MessageBox("打开文件出错","错误提示",MB_ICONWARNING); 
		return; 
	} 
 
	for(i=0;i<10;i++) 
	{ 
		for(j=0;j<9;j++) 
			fprintf(fp,"%-3d",m_byChessBoard[i][j]); 
		fprintf(fp,"\n"); 
	} 
 
	fclose(fp); 
} 
 
void CChessDlg::OnScbover()  
{ 
	// TODO: Add your command handler code here 
	m_Status=Chessing; 
	m_strOutputInfo=m_strWelcome; 
	UpdateData(false); 
} 
 
void CChessDlg::OnRpawn()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	if(IsChessOver(R_PAWN)) 
	{ 
		m_strOutputInfo="兵已用完"; 
		UpdateData(false); 
 
		return; 
	} 
 
	if(((y==6 || y==5) && (x==0 || x==2 || x==4 || x==6 || x==8)) || y<5) 
		m_byChessBoard[y][x]=R_PAWN; 
	else 
	{ 
		m_strOutputInfo="该处不能放兵"; 
		UpdateData(false); 
	} 
 
	//重绘屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnRcanon()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	if(IsChessOver(R_CANON)) 
	{ 
		m_strOutputInfo="炮已用完"; 
		UpdateData(false); 
 
		return; 
	} 
 
	m_byChessBoard[y][x]=R_CANON; 
 
	//重绘屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnRcar()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	if(IsChessOver(R_CAR)) 
	{ 
		m_strOutputInfo="车已用完"; 
		UpdateData(false); 
 
		return; 
	} 
 
	m_byChessBoard[y][x]=R_CAR; 
 
	//重绘屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnRhorse()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	if(IsChessOver(R_HORSE)) 
	{ 
		m_strOutputInfo="马已用完"; 
		UpdateData(false); 
 
		return; 
	} 
 
	m_byChessBoard[y][x]=R_HORSE; 
 
	//重绘屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnRelephant()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	if(IsChessOver(R_ELEPHANT)) 
	{ 
		m_strOutputInfo="相已用完"; 
		UpdateData(false); 
 
		return; 
	} 
 
	if((y==9 && (x==2 || x==6)) || (y==7 && (x==0 || x==8)) || (y==7 && x==4) || (y==5 && (x==2 || x==6))) 
		m_byChessBoard[y][x]=R_ELEPHANT; 
	else 
	{ 
		m_strOutputInfo="该处不能放相"; 
		UpdateData(false); 
	} 
 
	//重绘屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnRbishop()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	if(IsChessOver(R_BISHOP)) 
	{ 
		m_strOutputInfo="士已用完"; 
		UpdateData(false); 
 
		return; 
	} 
 
	if(y>=7 && y<=9 && x>=3 && x<=5) 
		m_byChessBoard[y][x]=R_BISHOP; 
	else 
	{ 
		m_strOutputInfo="该处不能放士"; 
		UpdateData(false); 
	} 
 
	//重绘屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnRking()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	if(IsChessOver(R_KING)) 
	{ 
		m_strOutputInfo="帅已用完"; 
		UpdateData(false); 
 
		return; 
	} 
 
	if(y>=7 && y<=9 && x>=3 && x<=5) 
		m_byChessBoard[y][x]=R_KING; 
	else 
	{ 
		m_strOutputInfo="该处不能放帅"; 
		UpdateData(false); 
	} 
 
	//重绘屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnBpawn()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	if(IsChessOver(B_PAWN)) 
	{ 
		m_strOutputInfo="卒已用完"; 
		UpdateData(false); 
 
		return; 
	} 
 
	if(((y==3 || y==4) && (x==0 || x==2 || x==4 || x==6 || x==8)) || y>4) 
		m_byChessBoard[y][x]=B_PAWN; 
	else 
	{ 
		m_strOutputInfo="该处不能放卒"; 
		UpdateData(false); 
	} 
 
	//重绘屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnBcanon()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
	if(IsChessOver(B_CANON)) 
	{ 
		m_strOutputInfo="炮已用完"; 
		UpdateData(false); 
 
		return; 
	} 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	m_byChessBoard[y][x]=B_CANON; 
 
	//重绘屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnBcar()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	if(IsChessOver(B_CAR)) 
	{ 
		m_strOutputInfo="车已用完"; 
		UpdateData(false); 
 
		return; 
	} 
 
	m_byChessBoard[y][x]=B_CAR; 
 
	//重绘屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnBhorse()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	if(IsChessOver(B_HORSE)) 
	{ 
		m_strOutputInfo="马已用完"; 
		UpdateData(false); 
 
		return; 
	} 
 
	m_byChessBoard[y][x]=B_HORSE; 
 
	//重绘屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnBelephant()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	if(IsChessOver(B_ELEPHANT)) 
	{ 
		m_strOutputInfo="象已用完"; 
		UpdateData(false); 
 
		return; 
	} 
 
	if((y==0 && (x==2 || x==6)) || (y==2 && (x==0 || x==8)) || (y==2 && x==4) || (y==4 && (x==2 || x==6))) 
		m_byChessBoard[y][x]=B_ELEPHANT; 
	else 
	{ 
		m_strOutputInfo="该处不能放象"; 
		UpdateData(false); 
	} 
 
	//重绘屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnBbishop()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	if(IsChessOver(B_BISHOP)) 
	{ 
		m_strOutputInfo="士已用完"; 
		UpdateData(false); 
 
		return; 
	} 
 
	if(y>=0 && y<=2 && x>=3 && x<=5) 
		m_byChessBoard[y][x]=B_BISHOP; 
	else 
	{ 
		m_strOutputInfo="该处不能放士"; 
		UpdateData(false); 
	} 
 
	//重绘屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnBking()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	if(IsChessOver(B_KING)) 
	{ 
		m_strOutputInfo="将已用完"; 
		UpdateData(false); 
 
		return; 
	} 
 
	if(y>=0 && y<=2 && x>=3 && x<=5) 
		m_byChessBoard[y][x]=B_KING; 
	else 
	{ 
		m_strOutputInfo="该处不能放将"; 
		UpdateData(false); 
	} 
 
	//重绘屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnDelete()  
{ 
	// TODO: Add your command handler code here 
	int x,y; 
 
    //将坐标换算成棋盘上的格子  
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
 
	//判断鼠标是否在棋盘内,并且点中了棋子 
	if(m_MousePoint.x>0 && m_MousePoint.y>0 && m_MousePoint.xTrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,point.x,point.y,this); 
 
		return; 
	} 
 
	int x,y; 
 
	this->m_MousePoint=point; 
 
	//将坐标换算成棋盘上的格子 
	y=(m_MousePoint.y-14)/GRILLEHEIGHT; 
	x=(m_MousePoint.x-15)/GRILLEWIDTH; 
	 
	memcpy(m_byBackupChessBoard,m_byChessBoard,90);//备份当前棋盘 
 
	//判断鼠标是否在棋盘内,并且点中了棋子 
	if(point.x>0 && point.y>0 && point.xTrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,point.x,point.y,this);	 
	} 
 
	CDialog::OnRButtonDown(nFlags, point); 
} 
 
void CChessDlg::OnLButtonDblClk(UINT nFlags, CPoint point)  
{ 
	// TODO: Add your message handler code here and/or call default 
	if(m_Status==Chessing) 
	{ 
		OnSet(); 
		return; 
	} 
 
	this->m_MousePoint=point; 
	OnDelete(); 
 
	CDialog::OnLButtonDblClk(nFlags, point); 
} 
 
int CChessDlg::IsGameOver(BYTE position[][9]) 
{ 
	int i,j; 
	BOOL RedLive=FALSE,BlackLive=FALSE; 
 
	//检查红方九宫是否有帅 
	for(i=7;i<10;i++) 
		for(j=3;j<6;j++) 
		{ 
			if(position[i][j]==B_KING) 
				BlackLive=TRUE; 
			if(position[i][j]==R_KING) 
				RedLive=TRUE; 
		} 
 
	//检查黑方九宫是否有将 
	for(i=0;i<3;i++) 
		for(j=3;j<6;j++) 
		{ 
			if(position[i][j]==B_KING) 
				BlackLive=TRUE; 
			if(position[i][j]==R_KING) 
				RedLive=TRUE; 
		} 
 
	if(m_nUserChessColor==REDCHESS) 
	{ 
		if(!RedLive) 
			return 1; 
		 
		if(!BlackLive) 
			return -1; 
	} 
	else 
	{ 
		if(!RedLive) 
			return -1; 
		 
		if(!BlackLive) 
			return 1; 
	} 
 
	return 0; 
} 
 
void CChessDlg::OnClose()  
{ 
	// TODO: Add your message handler code here and/or call default 
	if(MessageBox("你确定要退出吗?","友情提醒",MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2)==IDNO) 
		return; 
 
	CDialog::OnClose(); 
} 
 
void CChessDlg::OnClearcb()  
{ 
	// TODO: Add your command handler code here 
	if(MessageBox("你确定要清空棋盘吗?","友情提醒",MB_ICONQUESTION | MB_DEFBUTTON2 | MB_YESNO)==IDNO) 
		return; 
 
	int i,j; 
 
	for(i=0;i<10;i++) 
		for(j=0;j<9;j++) 
			m_byChessBoard[i][j]=NOCHESS; 
 
	//刷新屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::InvertChessBoard(BYTE cb[][9]) 
{ 
	int i,j; 
	BYTE btTemp; 
 
	for(i=0;i<5;i++) 
		for(j=0;j<9;j++) 
		{ 
			btTemp=cb[i][j]; 
			cb[i][j]=cb[9-i][8-j]; 
			cb[9-i][8-j]=btTemp; 
		} 
 
	//刷新屏幕 
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
//void CChessDlg::OnBtnbegin()  
//{ 
//	// TODO: Add your control notification handler code here 
//	CString sNodeCount; 
//	int timecount; 
// 
//	if(m_nUserChessColor==BLACKCHESS) 
//	{ 
//		m_iBout++; 
//		m_bIsThinking=true; 
//		m_pSE->SearchAGoodMove(m_byChessBoard);//让电脑走下一步	 
//		m_cmBestMove=m_pSE->GetBestMove();   //得到最佳走法 
//		m_umUndoMove=m_pSE->GetUndoMove(); 
//		m_stackUndoMove.push(m_umUndoMove);  //将电脑走法压栈 
//		this->AddChessRecord(m_cmBestMove.From.x+1,m_cmBestMove.From.y+1,m_cmBestMove.To.x+1,m_cmBestMove.To.y+1,m_nUserChessColor,m_cmBestMove.nChessID);		 
//		m_bIsThinking=false; 
// 
//		sNodeCount.Format("共访问%d个节点,花费时间%.3fs",m_pEvel->GetAccessCount(),(GetTickCount()-timecount)/1000.0); 
//		m_staticTip.SetWindowText(sNodeCount); 
// 
//		::FlashWindow(this->GetSafeHwnd(),TRUE); 
//	} 
//	else 
//		m_staticTip.SetWindowText("老兄,你先请"); 
// 
//	//重绘屏幕   
//	InvalidateRect(NULL,FALSE); 
//	UpdateWindow(); 
// 
//	m_bIsBegin=true; 
//} 
 
void CChessDlg::AddChessRecord(int nFromX,int nFromY,int nToX,int nToY,int nUserChessColor,int nSourceID) 
{ 
	CString strChess; 
	CString str; 
 
	if(nUserChessColor==REDCHESS)//用户执红棋 
		str=this->GetMoveStr(nFromX,nFromY,nToX,nToY,nSourceID); 
	else 
	{ 
		InvertChessBoard(m_byChessBoard); 
		str=this->GetMoveStr(10-nFromX,11-nFromY,10-nToX,11-nToY,nSourceID); 
		InvertChessBoard(m_byChessBoard); 
	} 
	str.Format("%d--"+str,m_iBout); 
 
	m_lstChessRecord.AddString(str); 
	m_lstChessRecord.PostMessage(WM_VSCROLL,SB_BOTTOM,0); 
} 
 
CString CChessDlg::ConvertDigit2Chinese(int nNum) 
{ 
	switch(nNum) 
	{ 
	case 1: 
		return "一"; 
		 
	case 2: 
		return "二"; 
		 
	case 3: 
		return "三"; 
		 
	case 4: 
		return "四"; 
		 
	case 5: 
		return "五"; 
		 
	case 6: 
		return "六"; 
		 
	case 7: 
		return "七"; 
		 
	case 8: 
		return "八"; 
		 
	case 9: 
		return "九"; 
 
	default: 
		return ""; 
	} 
} 
 
void CChessDlg::OnNewgame()  
{ 
	// TODO: Add your command handler code here 
	if(MessageBox("你确定要重新来一局吗?","友情提醒",MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2)==IDNO) 
		return; 
 
	memcpy(m_byChessBoard,InitChessBoard,90);    //初始化棋盘 
	memcpy(m_byShowChessBoard,InitChessBoard,90); 
	memcpy(m_byBackupChessBoard,InitChessBoard,90); 
	m_MoveChess.nChessID=NOCHESS;                //清除移动棋子 
	m_bIsGameOver=false; 
 
	if(m_nUserChessColor==BLACKCHESS) 
		this->InvertChessBoard(m_byChessBoard); 
 
	int nCount=m_lstChessRecord.GetCount(); 
	for(int i=0;iUndoChessMove(m_byChessBoard,&m_umUndoMove.cmChessMove,m_umUndoMove.nChessID); 
		memcpy(m_byShowChessBoard,m_byChessBoard,90); 
		memcpy(m_byBackupChessBoard,m_byChessBoard,90); 
		m_stackUndoMove.pop(); 
		m_lstChessRecord.DeleteString(m_lstChessRecord.GetCount()-1); 
		 
		//重绘屏幕   
		InvalidateRect(NULL,FALSE); 
		UpdateWindow(); 
	} 
	m_iBout--; 
 
	if(m_stackUndoMove.empty()) 
	{ 
		m_staticTip.SetWindowText("棋已悔完,无棋可悔了"); 
		m_btnUndo.EnableWindow(0);//冻结悔棋按钮 
	} 
} 
 
void CChessDlg::OnBtnredo()  
{ 
	// TODO: Add your control notification handler code here 
	if(m_stackRedoMove.empty()) 
		return; 
 
	UNDOMOVE umTemp; 
	 
	m_iBout++; 
	m_btnUndo.EnableWindow(1);//激活悔棋按钮 
	for(int i=0;i<2;i++) 
	{ 
		umTemp=m_stackRedoMove.top(); 
		m_pSE->RedoChessMove(m_byChessBoard,&umTemp.cmChessMove); 
		memcpy(m_byShowChessBoard,m_byChessBoard,90); 
		memcpy(m_byBackupChessBoard,m_byChessBoard,90); 
		m_stackUndoMove.push(umTemp); 
		m_stackRedoMove.pop(); 
		this->AddChessRecord(umTemp.cmChessMove.From.x+1,umTemp.cmChessMove.From.y+1,umTemp.cmChessMove.To.x+1,umTemp.cmChessMove.To.y+1,m_nUserChessColor,umTemp.cmChessMove.nChessID); 
 
		//重绘屏幕   
		InvalidateRect(NULL,FALSE); 
		UpdateWindow(); 
	} 
 
	if(m_stackRedoMove.empty()) 
	{ 
		m_staticTip.SetWindowText("棋已还原完,无棋可还原了"); 
		m_btnRedo.EnableWindow(0);//冻结还原按钮 
	} 
 
	switch(IsGameOver(m_byChessBoard)) 
	{ 
	case -1: 
		m_staticTip.SetWindowText("老兄,你好强哦"); 
		break; 
 
	case 1: 
		m_staticTip.SetWindowText("老兄,看来你不是我的对手啊"); 
		break; 
 
	default: 
		return; 
	} 
	 
	m_bIsGameOver=true; 
} 
 
CString CChessDlg::GetMoveStr(int nFromX,int nFromY,int nToX,int nToY,int nSourceID) 
{ 
	CString str; 
	bool bIsAgain; 
	int i; 
	int nCount; 
	int nPos[5]; 
	int j=0; 
 
	switch(nSourceID) 
	{ 
	case B_KING://黑将 
		if(nFromY==nToY) 
		{ 
			str.Format("黑:将%d平%d",nFromX,nToX); 
			break; 
		} 
		 
		if(nFromY>nToY) 
			str.Format("黑:将%d退%d",nFromX,nFromY-nToY); 
		else 
			str.Format("黑:将%d进%d",nFromX,nToY-nFromY); 
		 
		break; 
		 
	case B_CAR://黑车 
		bIsAgain=false; 
		for(i=0;i<10;i++) 
			if(m_byChessBoard[i][nFromX-1]==B_CAR && i!=nFromY-1 && i!=nToY-1) 
			{ 
				bIsAgain=true; 
				break; 
			} 
			 
			if(nFromY>nToY) 
			{ 
				if(bIsAgain) 
				{ 
					if(i>nFromY-1) 
						str.Format("黑:后车进%d",nFromY-nToY); 
					else 
						str.Format("黑:前车进%d",nFromY-nToY); 
				} 
				else 
					str.Format("黑:车%d退%d",nFromX,nFromY-nToY); 
			} 
			else 
				if(nFromYnFromY-1) 
							str.Format("黑:后车进%d",nToY-nFromY); 
						else 
							str.Format("黑:前车进%d",nToY-nFromY); 
					} 
					else 
						str.Format("黑:车%d进%d",nFromX,nToY-nFromY); 
				} 
				else 
				{ 
					if(bIsAgain) 
					{ 
						if(i>nFromY-1) 
							str.Format("黑:后车平%d",nToX); 
						else 
							str.Format("黑:前车平%d",nToX); 
					} 
					else 
						str.Format("黑:车%d平%d",nFromX,nToX); 
					 
					break; 
				} 
				 
				break; 
				 
	case B_HORSE://黑马 
		bIsAgain=false; 
		for(i=0;i<10;i++) 
			if(m_byChessBoard[i][nFromX-1]==B_HORSE && i!=nFromY-1 && i!=nToY-1) 
			{ 
				bIsAgain=true; 
				break; 
			} 
			 
			if(bIsAgain) 
			{ 
				if(i>nFromY-1) 
				{ 
					if(nFromY>nToY) 
						str.Format("黑:后马退%d",nToX); 
					else 
						str.Format("黑:后马进%d",nToX); 
				} 
				else 
				{ 
					if(nFromY>nToY) 
						str.Format("黑:前马退%d",nToX); 
					else 
						str.Format("黑:前马进%d",nToX); 
				} 
			} 
			else 
			{ 
				if(nFromY>nToY) 
					str.Format("黑:马%d退%d",nFromX,nToX); 
				else 
					str.Format("黑:马%d进%d",nFromX,nToX); 
			} 
			 
			break; 
			 
	case B_CANON://黑炮	 
		bIsAgain=false; 
		for(i=0;i<10;i++) 
			if(m_byChessBoard[i][nFromX-1]==B_CANON && i!=nFromY-1 && i!=nToY-1) 
			{ 
				bIsAgain=true; 
				break; 
			} 
			 
			if(nFromY>nToY) 
			{ 
				if(bIsAgain) 
				{ 
					if(i>nFromY-1) 
						str.Format("黑:后炮进%d",nFromY-nToY); 
					else 
						str.Format("黑:前炮进%d",nFromY-nToY); 
				} 
				else 
					str.Format("黑:炮%d退%d",nFromX,nFromY-nToY); 
			} 
			else 
				if(nFromYnFromY-1) 
								str.Format("黑:后炮进%d",nToY-nFromY); 
							else 
								str.Format("黑:前炮进%d",nToY-nFromY); 
						} 
						else 
							str.Format("黑:炮%d进%d",nFromX,nToY-nFromY); 
				} 
				else 
				{ 
					if(bIsAgain) 
					{ 
						if(i>nFromY-1) 
							str.Format("黑:后炮平%d",nToX); 
						else 
							str.Format("黑:前炮平%d",nToX); 
					} 
					else 
						str.Format("黑:炮%d平%d",nFromX,nToX); 
					break; 
				} 
				 
				break; 
				 
	case B_BISHOP://黑士 
		if(nFromY>nToY) 
			str.Format("黑:士%d退%d",nFromX,nToX); 
		else 
			str.Format("黑:士%d进%d",nFromX,nToX); 
		 
		break; 
		 
	case B_ELEPHANT://黑象 
		bIsAgain=false; 
		for(i=0;i<5;i++) 
			if(m_byChessBoard[i][nFromX-1]==B_ELEPHANT && i!=nFromY-1 && i!=nToY-1) 
			{ 
				bIsAgain=true; 
				break; 
			} 
			 
			if(bIsAgain) 
			{ 
				if(i>nFromY-1) 
				{ 
					if(nFromY>nToY) 
						str.Format("黑:后象退%d",nToX); 
					else 
						str.Format("黑:后象进%d",nToX); 
				} 
				else 
				{ 
					if(nFromY>nToY) 
						str.Format("黑:前象退%d",nToX); 
					else 
						str.Format("黑:前象进%d",nToX); 
				} 
			} 
			else 
			{ 
				if(nFromY>nToY) 
					str.Format("黑:象%d退%d",nFromX,nToX); 
				else 
					str.Format("黑:象%d进%d",nFromX,nToX); 
			} 
			 
			break; 
			 
	case B_PAWN://黑卒 
		nCount=0; 
		j=0; 
		for(i=0;i<5;i++) 
			nPos[i]=-1; 
		 
		for(i=0;i<10;i++) 
			if(m_byChessBoard[i][nFromX-1]==B_PAWN && i!=nFromY-1 && i!=nToY-1) 
			{ 
				nPos[j]=i; 
				nCount++; 
			} 
			 
			if(nCount==0) 
			{ 
				if(nFromY==nToY) 
					str.Format("黑:卒%d平%d",nFromX,nToX); 
				else 
					str.Format("黑:卒%d进%d",nFromX,1); 
				 
				break; 
			} 
			if(nCount==1) 
			{ 
				if(nFromY>nPos[0]) 
				{ 
					if(nFromY==nToY) 
						str.Format("黑:前卒平%d",nToX); 
					else 
						str.Format("黑:前卒进%d",1); 
				} 
				else 
				{ 
					if(nFromY==nToY) 
						str.Format("黑:后卒平%d",nToX); 
					else 
						str.Format("黑:后卒进%d",1); 
				} 
				 
				break; 
			} 
			j=0; 
			if(nCount>1) 
			{ 
				for(i=0;i<5;i++) 
					if(nPos[i]==-1) 
						break; 
					else 
						if(nPos[i]>nFromY) 
							break; 
						else 
							j++; 
						 
						if(nFromY==nToY) 
							str.Format("黑:%d卒平%d",j+1,1); 
						else 
							str.Format("黑:%d卒进%d",j+1,1); 
						 
						break; 
			} 
			 
	case R_KING://红帅 
		if(nFromX==nToX) 
		{ 
			if(nFromY>nToY) 
				str="红:帅"+ConvertDigit2Chinese(10-nFromX)+"进"+ConvertDigit2Chinese(nFromY-nToY); 
			else 
				str="红:帅"+ConvertDigit2Chinese(10-nFromX)+"退"+ConvertDigit2Chinese(nToY-nFromY); 
		} 
		else 
			str="红:帅"+ConvertDigit2Chinese(10-nFromX)+"平"+ConvertDigit2Chinese(10-nToX); 
		 
		break; 
		 
	case R_CAR://红车 
		bIsAgain=false; 
		for(i=0;i<10;i++) 
			if(m_byChessBoard[i][nFromX-1]==R_CAR && i!=nFromY-1 && i!=nToY-1) 
			{ 
				bIsAgain=true; 
				break; 
			} 
			 
			if(nFromY>nToY) 
			{ 
				if(bIsAgain) 
				{ 
					if(i>nFromY-1) 
						str="红:前车进"+ConvertDigit2Chinese(nFromY-nToY); 
					else 
						str="红:后车进"+ConvertDigit2Chinese(nFromY-nToY); 
				} 
				else 
					str="红:车"+ConvertDigit2Chinese(10-nFromX)+"进"+ConvertDigit2Chinese(nFromY-nToY); 
			} 
			else 
				if(nFromYnFromY-1) 
							str="红:后车退"+ConvertDigit2Chinese(nToY-nFromY); 
						else 
							str="红:前车退"+ConvertDigit2Chinese(nToY-nFromY); 
					} 
					else 
						str="红:车"+ConvertDigit2Chinese(10-nFromX)+"退"+ConvertDigit2Chinese(nToY-nFromY); 
				} 
				else 
				{ 
					if(bIsAgain) 
					{ 
						if(i>nFromY-1) 
							str="红:后车平"+ConvertDigit2Chinese(nToX); 
						else 
							str="红:前车平"+ConvertDigit2Chinese(nToX); 
					} 
					else 
						str="红:车"+ConvertDigit2Chinese(10-nFromX)+"平"+ConvertDigit2Chinese(10-nToX); 
					 
					break; 
				} 
				 
				break; 
				 
	case R_HORSE://红马 
		bIsAgain=false; 
		for(i=0;i<10;i++) 
			if(m_byChessBoard[i][nFromX-1]==R_HORSE && i!=nFromY-1 && i!=nToY-1) 
			{ 
				bIsAgain=true; 
				break; 
			} 
			 
			if(bIsAgain) 
			{ 
				if(i>nFromY-1) 
				{ 
					if(nFromY>nToY) 
						str="红:前马进"+ConvertDigit2Chinese(10-nToX); 
					else 
						str="红:前马退"+ConvertDigit2Chinese(10-nToX); 
				} 
				else 
				{ 
					if(nFromY>nToY) 
						str="红:前马进"+ConvertDigit2Chinese(10-nToX); 
					else 
						str="红:前马退"+ConvertDigit2Chinese(10-nToX); 
				} 
			} 
			else 
			{ 
				if(nFromY>nToY) 
					str="红:马"+ConvertDigit2Chinese(10-nFromX)+"进"+ConvertDigit2Chinese(10-nToX); 
				else 
					str="红:马"+ConvertDigit2Chinese(10-nFromX)+"退"+ConvertDigit2Chinese(10-nToX); 
			} 
			 
			break; 
			 
	case R_CANON://红炮 
		bIsAgain=false; 
		for(i=0;i<10;i++) 
			if(m_byChessBoard[i][nFromX-1]==R_CANON && i!=nFromY-1 && i!=nToY-1) 
			{ 
				bIsAgain=true; 
				break; 
			}				 
			 
			if(nFromY>nToY) 
			{ 
				if(bIsAgain) 
				{ 
					if(i>nFromY-1) 
						str="红:前炮进"+ConvertDigit2Chinese(nFromY-nToY); 
					else 
						str="红:后炮进"+ConvertDigit2Chinese(nFromY-nToY); 
				} 
				else 
					str="红:炮"+ConvertDigit2Chinese(10-nFromX)+"进"+ConvertDigit2Chinese(nFromY-nToY); 
			} 
			else 
				if(nFromYnFromY-1) 
							str="红:前炮退"+ConvertDigit2Chinese(nToY-nFromY); 
						else 
							str="红:后炮退"+ConvertDigit2Chinese(nToY-nFromY); 
					} 
					else 
						str="红:炮"+ConvertDigit2Chinese(nFromX)+"退"+ConvertDigit2Chinese(nToY-nFromY); 
				} 
				else 
				{ 
					if(bIsAgain) 
					{ 
						if(i>nFromY-1) 
							str="红:前炮平"+ConvertDigit2Chinese(10-nToX); 
						else 
							str="红:后炮平"+ConvertDigit2Chinese(10-nToX); 
					} 
					else 
						str="红:炮"+ConvertDigit2Chinese(10-nFromX)+"平"+ConvertDigit2Chinese(10-nToX); 
				} 
				 
				break; 
				 
	case R_BISHOP://红士 
		if(nFromY>nToY) 
			str="红:士"+ConvertDigit2Chinese(10-nFromX)+"进"+ConvertDigit2Chinese(10-nToX); 
		else 
			str="红:士"+ConvertDigit2Chinese(10-nFromX)+"退"+ConvertDigit2Chinese(10-nToX); 
		 
		break; 
		 
	case R_ELEPHANT://红相 
		bIsAgain=false; 
		for(i=0;i<5;i++) 
			if(m_byChessBoard[i][nFromX-1]==R_ELEPHANT && i!=nFromY-1 && i!=nToY-1) 
			{ 
				bIsAgain=true; 
				break; 
			} 
			 
			if(bIsAgain) 
			{ 
				if(i>nFromY-1) 
				{ 
					if(nFromY>nToY) 
						str="红:前相退"+ConvertDigit2Chinese(10-nToX); 
					else 
						str="红:前相进"+ConvertDigit2Chinese(10-nToX); 
				} 
				else 
				{ 
					if(nFromY>nToY) 
						str="红:后相退"+ConvertDigit2Chinese(10-nToX); 
					else 
						str="红:后相进"+ConvertDigit2Chinese(10-nToX); 
				} 
			} 
			else 
			{ 
				if(nFromY>nToY) 
					str="红:相"+ConvertDigit2Chinese(10-nFromX)+"进"+ConvertDigit2Chinese(10-nToX); 
				else 
					str="红:相"+ConvertDigit2Chinese(10-nFromX)+"退"+ConvertDigit2Chinese(10-nToX); 
			} 
			 
			break; 
			 
	case R_PAWN://红兵 
		nCount=0; 
		j=0; 
		for(i=0;i<5;i++) 
			nPos[i]=-1; 
		 
		for(i=0;i<10;i++) 
			if(m_byChessBoard[i][nFromX-1]==R_PAWN && i!=nFromY-1 && i!=nToY-1) 
			{ 
				nPos[j]=i; 
				nCount++; 
			} 
			 
			if(nCount==0) 
			{ 
				if(nFromY==nToY) 
					str="红:兵"+ConvertDigit2Chinese(10-nFromX)+"平"+ConvertDigit2Chinese(10-nToX); 
				else 
					str="红:兵"+ConvertDigit2Chinese(10-nFromX)+"进"+ConvertDigit2Chinese(1); 
				 
				break; 
			} 
			if(nCount==1) 
			{ 
				if(nFromY-1>nPos[0]) 
				{ 
					if(nFromY==nToY) 
						str="红:前兵平"+ConvertDigit2Chinese(10-nToX); 
					else 
						str="红:前兵进"+ConvertDigit2Chinese(1); 
				} 
				else 
				{ 
					if(nFromY==nToY) 
						str="红:后兵平"+ConvertDigit2Chinese(10-nToX); 
					else 
						str="红:后兵进"+ConvertDigit2Chinese(1); 
				} 
				 
				break; 
			} 
			j=0; 
			if(nCount>1) 
			{ 
				for(i=0;i<5;i++) 
					if(nPos[i]==-1) 
						break; 
					else 
						if(nPos[i]>nFromY-1) 
							break; 
						else 
							j++; 
						if(nFromY==nToY) 
							str="红:"+ConvertDigit2Chinese(j+1)+"兵平"+ConvertDigit2Chinese(nToX); 
						else 
							str="红:"+ConvertDigit2Chinese(j+1)+"兵进"+ConvertDigit2Chinese(1);	 
			} 
			 
			break; 
			 
	default: 
		break; 
	} 
 
	return str; 
} 
void CChessDlg::OnDblclkListchessrecord()  
{ 
	// TODO: Add your control notification handler code here 
	int nSel=m_lstChessRecord.GetCurSel(); 
	int nNum=m_lstChessRecord.GetCount(); 
	int nCount=0; 
 
	while(nCountOnBtnundo(); 
		nCount+=2; 
	} 
} 
 
BOOL CAboutDlg::OnInitDialog()  
{ 
	CDialog::OnInitDialog(); 
	 
	// TODO: Add extra initialization here 
	m_btnOk.SetBitmap(m_bitmapOk); 
 
	return TRUE;  // return TRUE unless you set the focus to a control 
	              // EXCEPTION: OCX Property Pages should return FALSE 
} 
 
void CChessDlg::Think() 
{ 
	int timecount; 
	CString sNodeCount; 
	 
	timecount=GetTickCount();//取初始时间 
	m_staticTip.SetWindowText("我正在思考,请勿打扰..."); 
	 
	if(m_nUserChessColor==BLACKCHESS) 
		m_iBout++; 
	m_bIsThinking=true; 
 
	m_pSE->SearchAGoodMove(m_byChessBoard); 
	memcpy(m_byShowChessBoard,m_byChessBoard,90); 
	memcpy(m_byBackupChessBoard,m_byChessBoard,90); 
	m_cmBestMove=m_pSE->GetBestMove();//得到最佳走法 
	m_umUndoMove=m_pSE->GetUndoMove(); 
	m_stackUndoMove.push(m_umUndoMove);//将电脑走法压栈 
	this->AddChessRecord(m_cmBestMove.From.x+1,m_cmBestMove.From.y+1,m_cmBestMove.To.x+1,m_cmBestMove.To.y+1,m_nUserChessColor,m_cmBestMove.nChessID); 
	m_bIsThinking=false; 
	 
	//重绘屏幕   
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
 
	sNodeCount.Format("共访问%d个节点,花费时间%.3fs",m_pEvel->GetAccessCount(),(GetTickCount()-timecount)/1000.0); 
	m_staticTip.SetWindowText(sNodeCount); 
 
	::FlashWindow(this->GetSafeHwnd(),TRUE); 
	m_btnStop.EnableWindow(0); 
 
	m_pEvel->ClearAccessCount(); 
	 
	switch(IsGameOver(m_byChessBoard)) 
	{ 
	case -1: 
		m_staticTip.SetWindowText("老兄,你好强哦"); 
		break; 
 
	case 1: 
		m_staticTip.SetWindowText("老兄,看来你不是我的对手啊"); 
		break; 
 
	default: 
		return; 
	} 
	 
	m_bIsGameOver=true; 
} 
 
BOOL CChessDlg::PreTranslateMessage(MSG* pMsg)  
{ 
	// TODO: Add your specialized code here and/or call the base class 
	m_tooltip.RelayEvent(pMsg);  
 
	return CDialog::PreTranslateMessage(pMsg); 
} 
 
void CChessDlg::OnBtnStop()  
{ 
	// TODO: Add your control notification handler code here 
	::TerminateThread(m_hHandle,0); 
	::WaitForSingleObject(m_hHandle,INFINITE); 
	::CloseHandle(m_hHandle); 
 
	m_btnStop.EnableWindow(0); 
	m_bIsThinking=0; 
	m_progressThink.SetPos(0); 
	m_staticTip.SetWindowText("我的思绪已被你打断"); 
 
	//撤销用户走法 
	memcpy(m_byShowChessBoard,m_byBackupChessBoard,90); 
	memcpy(m_byChessBoard,m_byBackupChessBoard,90); 
	m_stackUndoMove.pop(); 
	m_lstChessRecord.DeleteString(m_lstChessRecord.GetCount()-1); 
	m_iBout--; 
 
	//重绘屏幕   
	InvalidateRect(NULL,FALSE); 
	UpdateWindow(); 
} 
 
void CChessDlg::OnSelchangeListchessrecord()  
{ 
	// TODO: Add your control notification handler code here 
	if(m_Status!=Previewing) 
	{ 
		m_staticTip.SetWindowText("你要想查看以前的局面的话,请弹出右键菜单点“预览”"); 
		return; 
	} 
 
	int nSel=m_lstChessRecord.GetCurSel(); 
	int nNum=m_lstChessRecord.GetCount(); 
	int nCount=0; 
 
	if(!nNum) 
		return; 
 
	m_btnRedo.EnableWindow(1);//激活还原按钮 
	m_bIsGameOver=false; 
	memcpy(m_byShowChessBoard,m_byChessBoard,90); 
	while(nCountUndoChessMove(m_byShowChessBoard,&m_umUndoMove.cmChessMove,m_umUndoMove.nChessID); 
			memcpy(m_byBackupChessBoard,m_byShowChessBoard,90); 
			m_stackUndoMove.pop(); 
			 
			//重绘屏幕   
			InvalidateRect(NULL,FALSE); 
			UpdateWindow(); 
		} 
 
		nCount+=2; 
	} 
 
	//还原栈m_stackUndoMove和m_stackRedoMove 
	while(nCount) 
	{ 
		for(int i=0;i<2;i++) 
		{ 
			m_stackUndoMove.push(m_stackRedoMove.top()); 
			m_stackRedoMove.pop(); 
		} 
 
		nCount-=2; 
	} 
} 
 
void CChessDlg::OnPreview()  
{ 
	// TODO: Add your command handler code here 
	m_Status=Previewing; 
} 
 
void CChessDlg::OnPreviewover()  
{ 
	// TODO: Add your command handler code here 
	m_Status=Chessing; 
	memcpy(m_byShowChessBoard,m_byChessBoard,90); 
	m_staticTip.SetWindowText("呵呵,进入下棋状态,你可以下咯"); 
 
	//重绘屏幕   
	InvalidateRect(NULL,FALSE); 
	UpdateWindow();	 
} 
 
void CChessDlg::WinHelp(DWORD dwData, UINT nCmd)  
{ 
	// TODO: Add your specialized code here and/or call the base class 
	CHelpDlg dlg; 
	dlg.DoModal(); 
//	CDialog::WinHelp(dwData, nCmd); 
} 
 
void CChessDlg::OnHelp()  
{ 
	// TODO: Add your command handler code here 
	CHelpDlg dlg; 
	dlg.DoModal(); 
} 
 
void CChessDlg::OnInversecb()  
{ 
	// TODO: Add your command handler code here 
	this->InvertChessBoard(m_byShowChessBoard); 
 
	//重绘屏幕   
	InvalidateRect(NULL,FALSE); 
	UpdateWindow();	 
}