1. 程式人生 > >象棋人機對戰

象棋人機對戰


象棋主要演算法程式碼

Eveluation.h
Eveluation.cpp
這一對檔案定義並實現了估值核心類。

#if !defined(AFX_EVELUATION_H__2AF7A221_CB28_11D5_AEC7_5254AB2E22C7__INCLUDED_)
#define AFX_EVELUATION_H__2AF7A221_CB28_11D5_AEC7_5254AB2E22C7__INCLUDED_

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


#define BASEVALUE_PAWN 100
#define BASEVALUE_BISHOP 250
#define BASEVALUE_ELEPHANT 250
#define BASEVALUE_CAR 500
#define BASEVALUE_HORSE 350
#define BASEVALUE_CANON 350
#define BASEVALUE_KING 10000

#define FLEXIBILITY_PAWN 15
#define FLEXIBILITY_BISHOP 1
#define FLEXIBILITY_ELEPHANT 1
#define FLEXIBILITY_CAR 6
#define FLEXIBILITY_HORSE 12
#define FLEXIBILITY_CANON 6
#define FLEXIBILITY_KING 0

class CEveluation  
{
public:
	CEveluation();
	virtual ~CEveluation();
	
	virtual int Eveluate(BYTE position[10][9], BOOL bIsRedTurn);

protected:
	int GetRelatePiece(BYTE position[10][9],int j, int i);
	BOOL CanTouch(BYTE position[10][9], int nFromX, int nFromY, int nToX, int nToY);	
    void	AddPoint(int x, int y);
	int GetBingValue(int x, int y, BYTE CurSituation[][9]);
	int m_BaseValue[15];
	int m_FlexValue[15];
	short m_AttackPos[10][9];
	BYTE m_GuardPos[10][9];
	BYTE m_FlexibilityPos[10][9];
	int m_chessValue[10][9];
	int nPosCount;
	POINT RelatePos[20];

};

#endif // !defined(AFX_EVELUATION_H__2AF7A221_CB28_11D5_AEC7_5254AB2E22C7__INCLUDED_)

// Eveluation.cpp: implementation of the CEveluation class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "chess.h"
#include "Eveluation.h"

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

const int BA0[10][9]=
{
	{0,  0,  0,  0,  0,  0,  0,  0,  0},
	{90,90,110,120,120,120,110,90,90},
	{90,90,110,120,120,120,110,90,90},
	{70,90,110,110,110,110,110,90,70},
	{70,70,70, 70, 70,  70, 70,70,70},
	{0,  0,  0,  0,  0,  0,  0,  0,  0},
	{0,  0,  0,  0,  0,  0,  0,  0,  0},
	{0,  0,  0,  0,  0,  0,  0,  0,  0},
	{0,  0,  0,  0,  0,  0,  0,  0,  0},
	{0,  0,  0,  0,  0,  0,  0,  0,  0},
};

const int BA1[10][9]=
{
	{0,  0,  0,  0,  0,  0,  0,  0,  0},
	{0,  0,  0,  0,  0,  0,  0,  0,  0},
	{0,  0,  0,  0,  0,  0,  0,  0,  0},
	{0,  0,  0,  0,  0,  0,  0,  0,  0},
	{0,  0,  0,  0,  0,  0,  0,  0,  0},
	{70,70,70, 70, 70,70, 70,70, 70},
	{70,90,110,110,110,110,110,90,70},
	{90,90,110,120,120,120,110,90,90},
	{90,90,110,120,120,120,110,90,90},
	{0,  0, 0,  0,  0,  0,  0,  0,  0},
};

int CEveluation:: GetBingValue(int x, int y, BYTE CurSituation[][9])
{
	if (CurSituation[y][x] == R_PAWN)
		return BA0[y][x];
	
	if (CurSituation[y][x] == B_PAWN)
		return BA1[y][x];

	return 0;
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CEveluation::CEveluation()
{
	m_BaseValue[B_KING] = BASEVALUE_KING; 
	m_BaseValue[B_CAR] = BASEVALUE_CAR; 
	m_BaseValue[B_HORSE] = BASEVALUE_HORSE; 
	m_BaseValue[B_BISHOP] = BASEVALUE_BISHOP; 
	m_BaseValue[B_ELEPHANT] = BASEVALUE_ELEPHANT; 
	m_BaseValue[B_CANON] = BASEVALUE_CANON; 
	m_BaseValue[B_PAWN] = BASEVALUE_PAWN; 

	m_BaseValue[R_KING] = BASEVALUE_KING; 
	m_BaseValue[R_CAR] = BASEVALUE_CAR; 
	m_BaseValue[R_HORSE] = BASEVALUE_HORSE; 
	m_BaseValue[R_BISHOP] = BASEVALUE_BISHOP; 
	m_BaseValue[R_ELEPHANT] = BASEVALUE_ELEPHANT; 
	m_BaseValue[R_CANON] = BASEVALUE_CANON; 
	m_BaseValue[R_PAWN] = BASEVALUE_PAWN; 

	m_FlexValue[B_KING] = FLEXIBILITY_KING; 
	m_FlexValue[B_CAR] = FLEXIBILITY_CAR; 
	m_FlexValue[B_HORSE] = FLEXIBILITY_HORSE; 
	m_FlexValue[B_BISHOP] = FLEXIBILITY_BISHOP; 
	m_FlexValue[B_ELEPHANT] = FLEXIBILITY_ELEPHANT; 
	m_FlexValue[B_CANON] = FLEXIBILITY_CANON; 
	m_FlexValue[B_PAWN] = FLEXIBILITY_PAWN; 

	m_FlexValue[R_KING] = FLEXIBILITY_KING; 
	m_FlexValue[R_CAR] = FLEXIBILITY_CAR; 
	m_FlexValue[R_HORSE] = FLEXIBILITY_HORSE; 
	m_FlexValue[R_BISHOP] = FLEXIBILITY_BISHOP; 
	m_FlexValue[R_ELEPHANT] = FLEXIBILITY_ELEPHANT; 
	m_FlexValue[R_CANON] = FLEXIBILITY_CANON; 
	m_FlexValue[R_PAWN] = FLEXIBILITY_PAWN; 

}

CEveluation::~CEveluation()
{
}
int count=0;
int CEveluation::Eveluate(BYTE position[10][9], BOOL bIsRedTurn)
{
	int i, j, k;
	int nChessType, nTargetType;
	count++;

	memset(m_chessValue,0, 360);
	memset(m_AttackPos,0, 180); 
	memset(m_GuardPos,0, 90); 
	memset(m_FlexibilityPos, 0, 90);

	for(i = 0; i < 10; i++)
		for(j = 0; j < 9; j++)
		{
			if(position[i][j] != NOCHESS)
			{
				nChessType = position[i][j];
				GetRelatePiece(position, j, i);
				for (k = 0; k < nPosCount; k++)
				{
					nTargetType = position[RelatePos[k].y][RelatePos[k].x];
					if (nTargetType == NOCHESS)
					{
						m_FlexibilityPos[i][j]++;	
					}
					else
					{
						if (IsSameSide(nChessType, nTargetType))
						{
							m_GuardPos[RelatePos[k].y][RelatePos[k].x]++;
						}else
						{
							m_AttackPos[RelatePos[k].y][RelatePos[k].x]++;
							m_FlexibilityPos[i][j]++;	
							switch (nTargetType)
							{
							case R_KING:
								if (!bIsRedTurn)
									return 18888;
								break;
							case B_KING:
								if (bIsRedTurn)
									return 18888;
								break;
							default:
								m_AttackPos[RelatePos[k].y][RelatePos[k].x] += (30 + (m_BaseValue[nTargetType] - m_BaseValue[nChessType])/10)/10;
								break;
							}
						}
					}
				}
			}
		}

	for(i = 0; i < 10; i++)
		for(j = 0; j < 9; j++)
		{
			if(position[i][j] != NOCHESS)
			{
				nChessType = position[i][j];
				m_chessValue[i][j]++;
				m_chessValue[i][j] += m_FlexValue[nChessType] * m_FlexibilityPos[i][j];
				m_chessValue[i][j] += GetBingValue(j, i, position);
			}
		}
	int nHalfvalue;
	for(i = 0; i < 10; i++)
		for(j = 0; j < 9; j++)
		{
			if(position[i][j] != NOCHESS)
			{
				nChessType = position[i][j];
				nHalfvalue = m_BaseValue[nChessType]/16;
				m_chessValue[i][j] += m_BaseValue[nChessType];
				
				if (IsRed(nChessType))
				{
					if (m_AttackPos[i][j])
					{
						if (bIsRedTurn)
						{
							if (nChessType == R_KING)
							{
								m_chessValue[i][j]-= 20;
							}
							else
							{
								m_chessValue[i][j] -= nHalfvalue * 2;
								if (m_GuardPos[i][j])
									m_chessValue[i][j] += nHalfvalue;
							}
						}
						else
						{
							if (nChessType == R_KING)
								return 18888;
							m_chessValue[i][j] -= nHalfvalue*10;
							if (m_GuardPos[i][j])
								m_chessValue[i][j] += nHalfvalue*9;
						}
						m_chessValue[i][j] -= m_AttackPos[i][j];
					}
					else
					{
						if (m_GuardPos[i][j])
							m_chessValue[i][j] += 5;
					}
				}
				else
				{
					if (m_AttackPos[i][j])
					{
						if (!bIsRedTurn)
						{
							if (nChessType == B_KING)									
							{
								m_chessValue[i][j]-= 20;
							}
							else
							{
								m_chessValue[i][j] -= nHalfvalue * 2;
								if (m_GuardPos[i][j])
									m_chessValue[i][j] += nHalfvalue;
							}
						}
						else
						{
							if (nChessType == B_KING)
								return 18888;
							m_chessValue[i][j] -= nHalfvalue*10;
							if (m_GuardPos[i][j])
								m_chessValue[i][j] += nHalfvalue*9;
						}
						m_chessValue[i][j] -= m_AttackPos[i][j];
					}
					else
					{
						if (m_GuardPos[i][j])
							m_chessValue[i][j] += 5;
					}
				}
			}
		}

	int nRedValue = 0; 
	int	nBlackValue = 0;

	for(i = 0; i < 10; i++)
		for(j = 0; j < 9; j++)
		{
			nChessType = position[i][j];
//			if (nChessType == R_KING || nChessType == B_KING)
//				m_chessValue[i][j] = 10000;	
			if (nChessType != NOCHESS)
			{
				if (IsRed(nChessType))
				{
					nRedValue += m_chessValue[i][j];	
				}
				else
				{
					nBlackValue += m_chessValue[i][j];	
				}
			}
		}
		if (bIsRedTurn)
		{
			return nRedValue - nBlackValue;
		}
		else
		{
			return  nBlackValue-nRedValue ;
		}
}





void CEveluation::AddPoint(int  x, int y)
{
	RelatePos[nPosCount].x = x;
	RelatePos[nPosCount].y = y;
	nPosCount++;
}

int CEveluation::GetRelatePiece(BYTE position[10][9], int j, int i)
{
	nPosCount = 0;
	BYTE nChessID;
	BYTE flag;
	int x,y;
	
	nChessID = position[i][j];
	switch(nChessID)
	{
	case R_KING:
	case B_KING:
		
		for (y = 0; y < 3; y++)
			for (x = 3; x < 6; x++)
				if (CanTouch(position, j, i, x, y))
					AddPoint(x, y);
		for (y = 7; y < 10; y++)
			for (x = 3; x < 6; x++)
				if (CanTouch(position, j, i, x, y))
					AddPoint(x, y);
		break;
						
	case R_BISHOP:
		
		for (y = 7; y < 10; y++)
			for (x = 3; x < 6; x++)
				if (CanTouch(position, j, i, x, y))
					AddPoint(x, y);
		break;
				
	case B_BISHOP:
		
		for (y = 0; y < 3; y++)
			for (x = 3; x < 6; x++)
				if (CanTouch(position, j, i, x, y))
					AddPoint(x, y);
		break;
				
	case R_ELEPHANT:
	case B_ELEPHANT:
		
		x=j+2;
		y=i+2;
		if(x < 9 && y < 10  && CanTouch(position, j, i, x, y))
			AddPoint(x, y);
		
		x=j+2;
		y=i-2;
		if(x < 9 && y>=0  &&  CanTouch(position, j, i, x, y))
			AddPoint(x, y);
		
		x=j-2;
		y=i+2;
		if(x>=0 && y < 10  && CanTouch(position, j, i, x, y))
			AddPoint(x, y);
		
		x=j-2;
		y=i-2;
		if(x>=0 && y>=0  && CanTouch(position, j, i, x, y))
			AddPoint(x, y);
		break;
		
		case R_HORSE:		
		case B_HORSE:		
			x=j+2;
			y=i+1;
			if((x < 9 && y < 10) &&CanTouch(position, j, i, x, y))
				AddPoint(x, y);
					
					x=j+2;
					y=i-1;
					if((x < 9 && y >= 0) &&CanTouch(position, j, i, x, y))
						AddPoint(x, y);
					
					x=j-2;
					y=i+1;
					if((x >= 0 && y < 10) &&CanTouch(position, j, i, x, y))
						AddPoint(x, y);
					
					x=j-2;
					y=i-1;
					if((x >= 0 && y >= 0) &&CanTouch(position, j, i, x, y))
						AddPoint(x, y);
					
					x=j+1;
					y=i+2;
					if((x < 9 && y < 10) &&CanTouch(position, j, i, x, y))
						AddPoint(x, y);
					x=j-1;
					y=i+2;
					if((x >= 0 && y < 10) &&CanTouch(position, j, i, x, y))
						AddPoint(x, y);
					x=j+1;
					y=i-2;
					if((x < 9 && y >= 0) &&CanTouch(position, j, i, x, y))
						AddPoint(x, y);
					x=j-1;
					y=i-2;
					if((x >= 0 && y >= 0) &&CanTouch(position, j, i, x, y))
						AddPoint(x, y);
					break;
					
				case R_CAR:
				case B_CAR:
					x=j+1;
					y=i;
					while(x < 9)
					{
						if( NOCHESS == position[y][x] )
							AddPoint(x, y);
						else
						{
							AddPoint(x, y);
							break;
						}
						x++;
					}
					
					x = j-1;
					y = i;
					while(x >= 0)
					{
						if( NOCHESS == position[y][x] )
							AddPoint(x, y);
						else
						{
							AddPoint(x, y);
							break;
						}
						x--;
					}
					
					x=j;
					y=i+1;//
					while(y < 10)
					{
						if( NOCHESS == position[y][x])
							AddPoint(x, y);
						else
						{
							AddPoint(x, y);
							break;
						}
						y++;
					}
					
					x = j;
					y = i-1;//よ
					while(y>=0)
					{
						if( NOCHESS == position[y][x])
							AddPoint(x, y);
						else
						{
							AddPoint(x, y);
							break;
						}
						y--;
					}
					break;
					
				case R_PAWN:
					y = i - 1;
					x = j;
					
					if(y >= 0)
						AddPoint(x, y);
					
					if(i < 5)
					{
						y=i;
						x=j+1;
						if(x < 9 )
							AddPoint(x, y);
						x=j-1;
						if(x >= 0 )
							AddPoint(x, y);
					}
					break;
					
				case B_PAWN:
					y = i + 1;
					x = j;
					
					if(y < 10 )
						AddPoint(x, y);
					
					if(i > 4)
					{
						y=i;
						x=j+1;
						if(x < 9)
							AddPoint(x, y);
						x=j-1;
						if(x >= 0)
							AddPoint(x, y);
					}
					break;
					
				case B_CANON:
				case R_CANON:
					
					x=j+1;		//
					y=i;
					flag=FALSE;
					while(x < 9)		
					{
						if( NOCHESS == position[y][x] )
						{
							if(!flag)
								AddPoint(x, y);
						}
						else
						{
							if(!flag)
								flag=TRUE;
							else 
							{
								AddPoint(x, y);
								break;
							}
						}
						x++;
					}
					
					x=j-1;
					flag=FALSE;	
					while(x>=0)
					{
						if( NOCHESS == position[y][x] )
						{
							if(!flag)
								AddPoint(x, y);
						}
						else
						{
							if(!flag)
								flag=TRUE;
							else 
							{
								AddPoint(x, y);
								break;
							}
						}
						x--;
					}
					x=j;	
					y=i+1;
					flag=FALSE;
					while(y < 10)
					{
						if( NOCHESS == position[y][x] )
						{
							if(!flag)
								AddPoint(x, y);
						}
						else
						{
							if(!flag)
								flag=TRUE;
							else 
							{
								AddPoint(x, y);
								break;
							}
						}
						y++;
					}
					
					y=i-1;	//
					flag=FALSE;	
					while(y>=0)
					{
						if( NOCHESS == position[y][x] )
						{
							if(!flag)
								AddPoint(x, y);
						}
						else
						{
							if(!flag)
								flag=TRUE;
							else 
							{
								AddPoint(x, y);
								break;
							}
						}
						y--;
					}
					break;
					
				default:
					break;
					
				}
				return nPosCount ;				
}

BOOL CEveluation::CanTouch(BYTE position[10][9], int nFromX, int nFromY, int nToX, int nToY)
{
	int i, j;
	int nMoveChessID, nTargetID;
	
	if (nFromY ==  nToY && nFromX == nToX)
		return FALSE;//目的與源相同
	
	nMoveChessID = position[nFromY][nFromX];
	nTargetID = position[nToY][nToX];
	
	switch(nMoveChessID)
	{
	case B_KING:     
		if (nTargetID == R_KING)//老將見面?
		{
			if (nFromX != nToX)
				return FALSE;
			for (i = nFromY + 1; i < nToY; i++)
				if (position[i][nFromX] != NOCHESS)
					return FALSE;
		}
		else
		{
			if (nToY > 2 || nToX > 5 || nToX < 3)
				return FALSE;//目標點在九宮之外
			if(abs(nFromY - nToY) + abs(nToX - nFromX) > 1) 
				return FALSE;//將帥只走一步直線:
		}
		break;
	case R_BISHOP:   
		
		if (nToY < 7 || nToX > 5 || nToX < 3)
			return FALSE;//士出九宮	
		
		if (abs(nFromY - nToY) != 1 || abs(nToX - nFromX) != 1)
			return FALSE;	//士走斜線
		
		break;
		
	case B_BISHOP:   //黑士
		
		if (nToY > 2 || nToX > 5 || nToX < 3)
			return FALSE;//士出九宮	
		
		if (abs(nFromY - nToY) != 1 || abs(nToX - nFromX) != 1)
			return FALSE;	//士走斜線
		
		break;
		
	case R_ELEPHANT://紅象
		
		if(nToY < 5)
			return FALSE;//相不能過河
		
		if(abs(nFromX-nToX) != 2 || abs(nFromY-nToY) != 2)
			return FALSE;//相走田字
		
		if(position[(nFromY + nToY) / 2][(nFromX + nToX) / 2] != NOCHESS)
			return FALSE;//相眼被塞住了
		
		break;
		
	case B_ELEPHANT://黑象 
		
		if(nToY > 4)
			return FALSE;//相不能過河
		
		if(abs(nFromX-nToX) != 2 || abs(nFromY-nToY) != 2)
			return FALSE;//相走田字
		
		if(position[(nFromY + nToY) / 2][(nFromX + nToX) / 2] != NOCHESS)
			return FALSE;//相眼被塞住了
		
		break;
		
	case B_PAWN:     //黑兵
		
		if(nToY < nFromY)
			return FALSE;//兵不回頭
		
		if( nFromY < 5 && nFromY == nToY)
			return FALSE;//兵過河前只能直走
		
		if(nToY - nFromY + abs(nToX - nFromX) > 1)
			return FALSE;//兵只走一步直線:
		
		break;
		
	case R_PAWN:    //紅兵
		
		if(nToY > nFromY)
			return FALSE;//兵不回頭
		
		if( nFromY > 4 && nFromY == nToY)
			return FALSE;//兵過河前只能直走
		
		if(nFromY - nToY + abs(nToX - nFromX) > 1)
			return FALSE;//兵只走一步直線:
		
		break;
		
	case R_KING:     
		if (nTargetID == B_KING)//老將見面?
		{
			if (nFromX != nToX)
				return FALSE;//兩個將不在同一列
			for (i = nFromY - 1; i > nToY; i--)
				if (position[i][nFromX] != NOCHESS)
					return FALSE;//中間有別的子
		}
		else
		{
			if (nToY < 7 || nToX > 5 || nToX < 3)
				return FALSE;//目標點在九宮之外
			if(abs(nFromY - nToY) + abs(nToX - nFromX) > 1) 
				return FALSE;//將帥只走一步直線:
		}
		break;
		
	case B_CAR:      
	case R_CAR:      
		
		if(nFromY != nToY && nFromX != nToX)
			return FALSE;	//車走直線:
		
		if(nFromY == nToY)
		{
			if(nFromX < nToX)
			{
				for(i = nFromX + 1; i < nToX; i++)
					if(position[nFromY][i] != NOCHESS)
						return FALSE;
			}
			else
			{
				for(i = nToX + 1; i < nFromX; i++)
					if(position[nFromY][i] != NOCHESS)
						return FALSE;
			}
		}
		else
		{
			if(nFromY < nToY)
			{
				for(j = nFromY + 1; j < nToY; j++)
					if(position[j][nFromX] != NOCHESS)
						return FALSE;
			}
			else
			{
				for(j= nToY + 1; j < nFromY; j++)
					if(position[j][nFromX] != NOCHESS)
						return FALSE;
			}
		}
		
		break;
		
	case B_HORSE:    
	case R_HORSE:    
		
		if(!((abs(nToX-nFromX)==1 && abs(nToY-nFromY)==2)
			||(abs(nToX-nFromX)==2&&abs(nToY-nFromY)==1)))
			return FALSE;//馬走日字
		
		if	(nToX-nFromX==2)
		{
			i=nFromX+1;
			j=nFromY;
		}
		else if	(nFromX-nToX==2)
		{
			i=nFromX-1;
			j=nFromY;
		}
		else if	(nToY-nFromY==2)
		{
			i=nFromX;
			j=nFromY+1;
		}
		else if	(nFromY-nToY==2)
		{
			i=nFromX;
			j=nFromY-1;
		}
		
		if(position[j][i] != (BYTE)NOCHESS)
			return FALSE;//絆馬腿
		
		break;
	case B_CANON:    
	case R_CANON:    
		
		if(nFromY!=nToY && nFromX!=nToX)
			return FALSE;	//炮走直線:
		
		//炮不吃子時經過的路線中不能有棋子:------------------
		
		if(position[nToY][nToX] == NOCHESS)
		{
			if(nFromY == nToY)
			{
				if(nFromX < nToX)
				{
					for(i = nFromX + 1; i < nToX; i++)
						if(position[nFromY][i] != NOCHESS)
							return FALSE;
				}
				else
				{
					for(i = nToX + 1; i < nFromX; i++)
						if(position[nFromY][i]!=NOCHESS)
							return FALSE;
				}
			}
			else
			{
				if(nFromY < nToY)
				{
					for(j = nFromY + 1; j < nToY; j++)
						if(position[j][nFromX] != NOCHESS)
							return FALSE;
				}
				else
				{
					for(j = nToY + 1; j < nFromY; j++)
						if(position[j][nFromX] != NOCHESS)
							return FALSE;
				}
			}
		}
		//以上是炮不吃子-------------------------------------
		//吃子時:=======================================
		else	
		{
			int nCount=0;
			if(nFromY == nToY)
			{
				if(nFromX < nToX)
				{
					for(i=nFromX+1;i<nToX;i++)
						if(position[nFromY][i]!=NOCHESS)
							nCount++;
						if(nCount != 1)
							return FALSE;
				}
				else
				{
					for(i=nToX+1;i<nFromX;i++)
						if(position[nFromY][i] != NOCHESS)
							nCount++;
						if(nCount!=1)
							return FALSE;
				}
			}
			else
			{
				if(nFromY<nToY)
				{
					for(j=nFromY+1;j<nToY;j++)
						if(position[j][nFromX]!=NOCHESS)
							nCount++;
						if(nCount!=1)
							return FALSE;
				}
				else
				{
					for(j=nToY+1;j<nFromY;j++)
						if(position[j][nFromX] != NOCHESS)
							nCount++;
						if(nCount!=1)
							return FALSE;
				}
			}
		}
		//以上是炮吃子時================================
		break;
	default:
		return FALSE;
	}
	
	return TRUE;
}


MoveGenerator.h
MoveGenerator.cpp
這一對檔案定義並實現了走法產生器。

//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_MOVEGENERATOR_H__54A88FC2_CAFC_11D5_AEC7_5254AB2E22C7__INCLUDED_)
#define AFX_MOVEGENERATOR_H__54A88FC2_CAFC_11D5_AEC7_5254AB2E22C7__INCLUDED_

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

class CMoveGenerator  
{
public:
	CMoveGenerator();
	virtual ~CMoveGenerator();
	static BOOL IsValidMove(BYTE position[10][9], int nFromX, int nFromY, int nToX, int nToY);
	int CreatePossibleMove(BYTE position[10][9], int nPly,int nSide);

	CHESSMOVE m_MoveList[10][80];
protected:

	void Gen_KingMove(BYTE position[10][9], int i, int j, int nPly);
	void Gen_RBishopMove(BYTE position[10][9], int i, int j, int nPly);
	void Gen_BBishopMove(BYTE position[10][9], int i, int j, int nPly);
	void Gen_ElephantMove(BYTE position[10][9], int i, int j, int nPly);
	void Gen_HorseMove(BYTE position[10][9],  int i, int j, int nPly);
	void Gen_CarMove(BYTE position[10][9],  int i, int j, int nPly);
	void Gen_RPawnMove(BYTE position[10][9],  int i, int j, int nPly);
	void Gen_BPawnMove(BYTE position[10][9], int i, int j, int nPly);
	void Gen_CanonMove(BYTE position[10][9], int i, int j, int nPly);

	int AddMove(int nFromX,int nToX, int nFromY, int nToY,int nPly);
	int m_nMoveCount;
};

#endif // !defined(AFX_MOVEGENERATOR_H__54A88FC2_CAFC_11D5_AEC7_5254AB2E22C7__INCLUDED_)



//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "chess.h"
#include "MoveGenerator.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMoveGenerator::CMoveGenerator()
{
	
}

CMoveGenerator::~CMoveGenerator()
{
	
}

int CMoveGenerator::AddMove(int nFromX, int nFromY, int nToX, int nToY,int nPly)
{
	m_MoveList[nPly][m_nMoveCount].From.x = nFromX;
	m_MoveList[nPly][m_nMoveCount].From.y = nFromY;
	m_MoveList[nPly][m_nMoveCount].To.x = nToX;
	m_MoveList[nPly][m_nMoveCount].To.y = nToY;
	m_nMoveCount++;
	return m_nMoveCount;
}

int CMoveGenerator::CreatePossibleMove(BYTE position[10][9], int nPly, int nSide)
{
	int     nChessID;
	int		i,j;
	
	m_nMoveCount = 0;
	for (i = 0; i < 10; i++)
		for (j = 0; j < 9; j++)
		{
			if (position[i][j] != NOCHESS)
			{
				nChessID = position[i][j];
				if (!nSide && IsRed(nChessID))
					continue;
				if (nSide && IsBlack(nChessID))
					continue;
				switch(nChessID)
				{
				case R_KING:
				case B_KING:
					Gen_KingMove(position, i, j, nPly);
					break;
					
				case R_BISHOP:
					Gen_RBishopMove(position, i, j, nPly);
					break;
					
				case B_BISHOP:
					Gen_BBishopMove(position, i, j, nPly);
					break;
					
				case R_ELEPHANT:
				case B_ELEPHANT:
					Gen_ElephantMove(position, i, j, nPly);
					break;
					
				case R_HORSE:		
				case B_HORSE:		
					Gen_HorseMove(position, i, j, nPly);
					break;
					
				case R_CAR:
				case B_CAR:
					Gen_CarMove(position, i, j, nPly);
					break;
					
				case R_PAWN:
					Gen_RPawnMove(position, i, j, nPly);
					break;
					
				case B_PAWN:
					Gen_BPawnMove(position, i, j, nPly);
					break;
					
				case B_CANON:
				case R_CANON:
					Gen_CanonMove(position, i, j, nPly);
					break;
					
				default:
					break;
					
				}
			}
		}
		
		return m_nMoveCount;
}



void CMoveGenerator::Gen_KingMove(BYTE position[10][9], int i, int j, int nPly)
{
	int x,  y;
	for (y = 0; y < 3; y++)
		for (x = 3; x < 6; x++)
			if (IsValidMove(position, j, i, x, y))
				AddMove(j, i, x, y, nPly);

	for (y = 7; y < 10; y++)
		for (x = 3; x < 6; x++)
			if (IsValidMove(position, j, i, x, y))
				AddMove(j, i, x, y, nPly);
}

void CMoveGenerator::Gen_RBishopMove(BYTE position[10][9], int i, int j, int nPly)
{
	int x,  y;
	for (y = 7; y < 10; y++)
		for (x = 3; x < 6; x++)
			if (IsValidMove(position, j, i, x, y))
				AddMove(j, i, x, y, nPly);
}

void CMoveGenerator::Gen_BBishopMove(BYTE position[10][9], int i, int j, int nPly)
{
	int x,  y;
	for (y = 0; y < 3; y++)
		for (x = 3; x < 6; x++)
			if (IsValidMove(position, j, i, x, y))
				AddMove(j, i, x, y, nPly);
}

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))
		AddMove(j, i, x, y, nPly);
	
	x=j+2;
	y=i-2;
	if(x < 9 && y>=0  &&  IsValidMove(position, j, i, x, y))
		AddMove(j, i, x, y, nPly);
	
	x=j-2;
	y=i+2;
	if(x>=0 && y < 10  && IsValidMove(position, j, i, x, y))
		AddMove(j, i, x, y, nPly);
	
	x=j-2;
	y=i-2;
	if(x>=0 && y>=0  && IsValidMove(position, j, i, x, y))
		AddMove(j, i, x, y, nPly);
	
}

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

	x=j+2;
	y=i+1;
	if((x < 9 && y < 10) &&IsValidMove(position, j, i, x, y))
		AddMove(j, i, x, y, nPly);
	
	x=j+2;
	y=i-1;
	if((x < 9 && y >= 0) &&IsValidMove(position, j, i, x, y))
		AddMove(j, i, x, y, nPly);
	
	x=j-2;
	y=i+1;
	if((x >= 0 && y < 10) &&IsValidMove(position, j, i, x, y))
		AddMove(j, i, x, y, nPly);
	
	x=j-2;
	y=i-1;
	if((x >= 0 && y >= 0) &&IsValidMove(position, j, i, x, y))
		AddMove(j, i, x, y, nPly);
	
	x=j+1;
	y=i+2;
	if((x < 9 && y < 10) &&IsValidMove(position, j, i, x, y))
		AddMove(j, i, x, y, nPly);
	x=j-1;
	y=i+2;
	if((x >= 0 && y < 10) &&IsValidMove(position, j, i, x, y))
		AddMove(j, i, x, y, nPly);
	x=j+1;
	y=i-2;
	if((x < 9 && y >= 0) &&IsValidMove(position, j, i, x, y))
		AddMove(j, i, x, y, nPly);
	x=j-1;
	y=i-2;
	if((x >= 0 && y >= 0) &&IsValidMove(position, j, i, x, y))
		AddMove(j, i, x, y, nPly);
	
}

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

	nChessID = position[i][j];

	y = i - 1;
	x = j;
	
	if(y > 0 && !IsSameSide(nChessID, position[y][x]))
		AddMove(j, i, x, y, nPly);
	
	if(i < 5)
	{
		y=i;
		x=j+1;
		if(x < 9 && !IsSameSide(nChessID, position[y][x]))
			AddMove(j, i, x, y, nPly);
		x=j-1;
		if(x >= 0 && !IsSameSide(nChessID, position[y][x]))
			AddMove(j, i, x, y, nPly);
	}
}


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

	nChessID = position[i][j];

	y = i + 1;
	x = j;
	
	if(y < 10 && !IsSameSide(nChessID, position[y][x]))
		AddMove(j, i, x, y, nPly);
	
	if(i > 4)
	{
		y=i;
		x=j+1;
		if(x < 9 && !IsSameSide(nChessID, position[y][x]))
			AddMove(j, i, x, y, nPly);
		x=j-1;
		if(x >= 0 && !IsSameSide(nChessID, position[y][x]))
			AddMove(j, i, x, y, nPly);
	}
	
}

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

	nChessID = position[i][j];
	
	x=j+1;
	y=i;
	while(x < 9)
	{
		if( NOCHESS == position[y][x] )
			AddMove(j, i, x, y, nPly);
		else
		{
			if(!IsSameSide(nChessID, position[y][x]))
				AddMove(j, i, x, y, nPly);
			break;
		}
		x++;
	}
	
	x = j-1;
	y = i;
	while(x >= 0)
	{
		if( NOCHESS == position[y][x] )
			AddMove(j, i, x, y, nPly);
		else
		{
			if(!IsSameSide(nChessID, position[y][x]))
				AddMove(j, i, x, y, nPly);
			break;
		}
		x--;
	}
	
	x=j;
	y=i+1;//
	while(y < 10)
	{
		if( NOCHESS == position[y][x])
			AddMove(j, i, x, y, nPly);
		else
		{
			if(!IsSameSide(nChessID, position[y][x]))
				AddMove(j, i, x, y, nPly);
			break;
		}
		y++;
	}
	
	x = j;
	y = i-1;//
	while(y>=0)
	{
		if( NOCHESS == position[y][x])
			AddMove(j, i, x, y, nPly);
		else
		{
			if(!IsSameSide(nChessID, position[y][x]))
				AddMove(j, i, x, y, nPly);
			break;
		}
		y--;
	}
}

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

	nChessID = position[i][j];
	
	x=j+1;		//
	y=i;
	flag=FALSE;
	while(x < 9)		
	{
		if( NOCHESS == position[y][x] )
		{
			if(!flag)
				AddMove(j, i, x, y, nPly);
		}
		else
		{
			if(!flag)
				flag=TRUE;
			else 
			{
				if(!IsSameSide(nChessID, position[y][x]))
					AddMove(j, i, x, y, nPly);
				break;
			}
		}
		x++;
	}
	
	x=j-1;
	flag=FALSE;	
	while(x>=0)
	{
		if( NOCHESS == position[y][x] )
		{
			if(!flag)
				AddMove(j, i, x, y, nPly);
		}
		else
		{
			if(!flag)
				flag=TRUE;
			else 
			{
				if(!IsSameSide(nChessID, position[y][x]))
					AddMove(j, i, x, y, nPly);
				break;
			}
		}
		x--;
	}
	x=j;	
	y=i+1;
	flag=FALSE;
	while(y < 10)
	{
		if( NOCHESS == position[y][x] )
		{
			if(!flag)
				AddMove(j, i, x, y, nPly);
		}
		else
		{
			if(!flag)
				flag=TRUE;
			else 
			{
				if(!IsSameSide(nChessID, position[y][x]))
					AddMove(j, i, x, y, nPly);
				break;
			}
		}
		y++;
	}
	
	y=i-1;	//
	flag=FALSE;	
	while(y>=0)
	{
		if( NOCHESS == position[y][x] )
		{
			if(!flag)
				AddMove(j, i, x, y, nPly);
		}
		else
		{
			if(!flag)
				flag=TRUE;
			else 
			{
				if(!IsSameSide(nChessID, position[y][x]))
					AddMove(j, i, x, y, nPly);
				break;
			}
		}
		y--;
	}
	
}

BOOL CMoveGenerator::IsValidMove(BYTE position[10][9], int nFromX, int nFromY, int nToX, int nToY)
{
	int i, j;
	int nMoveChessID, nTargetID;
	
	if (nFromY ==  nToY && nFromX == nToX)
		return FALSE;//目的與源相同
	
	nMoveChessID = position[nFromY][nFromX];
	nTargetID = position[nToY][nToX];
	
	if (IsSameSide(nMoveChessID, nTargetID))
		return FALSE;//不能吃自己的棋
	
	switch(nMoveChessID)
	{
	case B_KING:     
		if (nTargetID == R_KING)//老將見面?
		{
			if (nFromX != nToX)
				return FALSE;
			for (i = nFromY + 1; i < nToY; i++)
				if (position[i][nFromX] != NOCHESS)
					return FALSE;
		}
		else
		{
			if (nToY > 2 || nToX > 5 || nToX < 3)
				return FALSE;//目標點在九宮之外
			if(abs(nFromY - nToY) + abs(nToX - nFromX) > 1) 
				return FALSE;//將帥只走一步直線:
		}
		break;
	case R_BISHOP:   
		
		if (nToY < 7 || nToX > 5 || nToX < 3)
			return FALSE;//士出九宮	
		
		if (abs(nFromY - nToY) != 1 || abs(nToX - nFromX) != 1)
			return FALSE;	//士走斜線
		
		break;
		
	case B_BISHOP:   //黑士
		
		if (nToY > 2 || nToX > 5 || nToX < 3)
			return FALSE;//士出九宮	
		
		if (abs(nFromY - nToY) != 1 || abs(nToX - nFromX) != 1)
			return FALSE;	//士走斜線
		
		break;
		
	case R_ELEPHANT://紅象
		
		if(nToY < 5)
			return FALSE;//相不能過河
		
		if(abs(nFromX-nToX) != 2 || abs(nFromY-nToY) != 2)
			return FALSE;//相走田字
		
		if(position[(nFromY + nToY) / 2][(nFromX + nToX) / 2] != NOCHESS)
			return FALSE;//相眼被塞住了
		
		break;
		
	case B_ELEPHANT://黑象 
		
		if(nToY > 4)
			return FALSE;//相不能過河
		
		if(abs(nFromX-nToX) != 2 || abs(nFromY-nToY) != 2)
			return FALSE;//相走田字
		
		if(position[(nFromY + nToY) / 2][(nFromX + nToX) / 2] != NOCHESS)
			return FALSE;//相眼被塞住了
		
		break;
		
	case B_PAWN:     //黑兵
		
		if(nToY < nFromY)
			return FALSE;//兵不回頭
		
		if( nFromY < 5 && nFromY == nToY)
			return FALSE;//兵過河前只能直走
		
		if(nToY - nFromY + abs(nToX - nFromX) > 1)
			return FALSE;//兵只走一步直線:
		
		break;
		
	case R_PAWN:    //紅兵
		
		if(nToY > nFromY)
			return FALSE;//兵不回頭
		
		if( nFromY > 4 && nFromY == nToY)
			return FALSE;//兵過河前只能直走
		
		if(nFromY - nToY + abs(nToX - nFromX) > 1)
			return FALSE;//兵只走一步直線:
		
		break;
		
	case R_KING:     
		if (nTargetID == B_KING)//老將見面?
		{
			if (nFromX != nToX)
				return FALSE;//兩個將不在同一列
			for (i = nFromY - 1; i > nToY; i--)
				if (position[i][nFromX] != NOCHESS)
					return FALSE;//中間有別的子
		}
		else
		{
			if (nToY < 7 || nToX > 5 || nToX < 3)
				return FALSE;//目標點在九宮之外
			if(abs(nFromY - nToY) + abs(nToX - nFromX) > 1) 
				return FALSE;//將帥只走一步直線:
		}
		break;
		
	case B_CAR:      
	case R_CAR:      
		
		if(nFromY != nToY && nFromX != nToX)
			return FALSE;	//車走直線:
		
		if(nFromY == nToY)
		{
			if(nFromX < nToX)
			{
				for(i = nFromX + 1; i < nToX; i++)
					if(position[nFromY][i] != NOCHESS)
						return FALSE;
			}
			else
			{
				for(i = nToX + 1; i < nFromX; i++)
					if(position[nFromY][i] != NOCHESS)
						return FALSE;
			}
		}
		else
		{
			if(nFromY < nToY)
			{
				for(j = nFromY + 1; j < nToY; j++)
					if(position[j][nFromX] != NOCHESS)
						return FALSE;
			}
			else
			{
				for(j= nToY + 1; j < nFromY; j++)
					if(position[j][nFromX] != NOCHESS)
						return FALSE;
			}
		}
		
		break;
		
	case B_HORSE:    
	case R_HORSE:    
		
		if(!((abs(nToX-nFromX)==1 && abs(nToY-nFromY)==2)
			||(abs(nToX-nFromX)==2&&abs(nToY-nFromY)==1)))
			return FALSE;//馬走日字
		
		if	(nToX-nFromX==2)
		{
			i=nFromX+1;
			j=nFromY;
		}
		else if	(nFromX-nToX==2)
		{
			i=nFromX-1;
			j=nFromY;
		}
		else if	(nToY-nFromY==2)
		{
			i=nFromX;
			j=nFromY+1;
		}
		else if	(nFromY-nToY==2)
		{
			i=nFromX;
			j=nFromY-1;
		}
		
		if(position[j][i] != NOCHESS)
			return FALSE;//絆馬腿
		
		break;
	
	case B_CANON:    
	case R_CANON:    
		
		if(nFromY!=nToY && nFromX!=nToX)
			return FALSE;	//炮走直線:
		
		//炮不吃子時經過的路線中不能有棋子
		
		if(position[nToY][nToX] == NOCHESS)
		{
			if(nFromY == nToY)
			{
				if(nFromX < nToX)
				{
					for(i = nFromX + 1; i < nToX; i++)
						if(position[nFromY][i] != NOCHESS)
							return FALSE;
				}
				else
				{
					for(i = nToX + 1; i < nFromX; i++)
						if(position[nFromY][i]!=NOCHESS)
							return FALSE;
				}
			}
			else
			{
				if(nFromY < nToY)
				{
					for(j = nFromY + 1; j < nToY; j++)
						if(position[j][nFromX] != NOCHESS)
							return FALSE;
				}
				else
				{
					for(j = nToY + 1; j < nFromY; j++)
						if(position[j][nFromX] != NOCHESS)
							return FALSE;
				}
			}
		}
		//炮吃子時
		else	
		{
			int count=0;
			if(nFromY == nToY)
			{
				if(nFromX < nToX)
				{
					for(i=nFromX+1;i<nToX;i++)
						if(position[nFromY][i]!=NOCHESS)
							count++;
						if(count != 1)
							return FALSE;
				}
				else
				{
					for(i=nToX+1;i<nFromX;i++)
						if(position[nFromY][i] != NOCHESS)
							count++;
						if(count!=1)
							return FALSE;
				}
			}
			else
			{
				if(nFromY<nToY)
				{
					for(j=nFromY+1;j<nToY;j++)
						if(position[j][nFromX]!=NOCHESS)
							count++;
						if(count!=1)
							return FALSE;
				}
				else
				{
					for(j=nToY+1;j<nFromY;j++)
						if(position[j][nFromX] != NOCHESS)
							count++;
						if(count!=1)
							return FALSE;
				}
			}
		}
		break;
	default:
		return FALSE;
	}
	
	return TRUE;
}

完整原始碼,資源以及執行exe連結http://download.csdn.net/download/zhangxiaoyu_sy/9939114