www.pudn.com > fivesource.zip > Game.cpp


/* ===================================================================== 
	五子棋分析程序: 
			  1996.4 刘国辉 
  说明: 
  约定: 
	 ‘W' 代表白棋 
	  'B' 代表黑棋 
	  'N' 代表空地 
(1)平分函数: 
  int Dump( int x,int Wf ) 
  X   在一条线上的子数 
  WF    = 1 两边都没有被堵住  例如   NNWWWNB.. 
		= 0 一边被堵住               BWWWNNW.. 
		= 2 跨越式的                 WWWNW.. 
	返回一个分数 
(2)线扫描函数: 
  int SreachLine( char *FLine,int M,int MF ) 
  FLine 线指针,指向一个字符串    NNNWWWBWWWN... 
  M     字符个数 
  WF ='W'或'B'表示对黑或白进行平分 
	返回一个分数 
 (3)面扫描函数: 
 long SreachArea( char *Area[15],int M,char WF ) 
  .... 
===================================================================== */ 
#include "game.h" 
#include  
 
int CFive::WF1_1; 
int CFive::WF1_2; 
int CFive::WF1_3; 
int CFive::WF1_4; 
int CFive::WF0_1; 
int CFive::WF0_2; 
int CFive::WF0_3; 
int CFive::WF0_4; 
int CFive::WF2_3; 
int CFive::WF2_4; 
int CFive::WF5; 
int CFive::DeepMax; 
int CFive::BreadthMax; 
int CFive::Delta; 
int CFive::ThreadDeepMax; 
char CFive::FiveArea[FIVE_MAX_LINE][FIVE_MAX_LINE]; 
CList CFive::StepList; 
CList CFive::TempDeepList; 
 
IMPLEMENT_SERIAL( CFive, CWinThread, 1 ) 
 
CFive::CFive( char side ):EndEvent( FALSE,TRUE ) 
{ 
	int i,j; 
	WF0_1 = 2; 
	WF0_2 = 10; 
	WF0_3 = 500; 
	WF0_4 = 5000; 
	WF1_1 = 1; 
	WF1_2 = 20; 
	WF1_3 = 21; 
	WF1_4 = 500; 
	WF2_3 = 400; 
	WF2_4 = 450; 
	WF5   = 30000; 
 
	CurDeep = DeepMax  = 1; 
	CurBreadth = BreadthMax = 1; 
	CurThreadDeep = ThreadDeepMax = 0; 
	Delta = 0; 
	CurSide = side; 
	for( i = 0;i < FIVE_MAX_LINE;i++ ) 
		for( j = 0;j < FIVE_MAX_LINE;j++ ) 
		     FiveArea[i][j] = 'N'; 
} 
 
CFive::CFive( char side,int deep,int breadth,int threaddeep ):EndEvent( FALSE,TRUE ) 
{ 
	CurDeep       = deep-1; 
	CurThreadDeep = threaddeep-1; 
	CurBreadth    = breadth-Delta; 
	CurSide = (side == 'B'?'W':'B'); 
} 
 
CFive::~CFive() 
{ 
	DeepList.RemoveAll(); 
	CountList.RemoveAll(); 
} 
 
void CFive::WzqInit( char side,BOOL flags ) 
{ 
	int i,j; 
 
	CurSide = side; 
	CurDeep = DeepMax; 
	CurBreadth = BreadthMax; 
	CurThreadDeep = ThreadDeepMax; 
 
	StepList.RemoveAll(); 
	TempDeepList.RemoveAll(); 
	CountList.RemoveAll(); 
	DeepList.RemoveAll(); 
 
	for( i = 0;i < FIVE_MAX_LINE;i++ ) 
		for( j = 0;j < FIVE_MAX_LINE;j++ ) 
		     FiveArea[i][j] = 'N'; 
 
	if( flags == FALSE ) 
	{ 
		int mx,my; 
		mx = FIVE_MAX_LINE/2 -2; 
		my = mx; 
		mx += rand()%4; 
		my += rand()%4; 
		FiveArea[mx][my] = CurSide; 
	} 
} 
 
void CFive::SetParam( int breadth,int deep,int thread,int delta ) 
{ 
	BreadthMax = breadth; 
	DeepMax = deep; 
	ThreadDeepMax = thread; 
	Delta = delta; 
	CurBreadth = breadth; 
	CurThreadDeep = deep; 
	CurDeep = deep; 
} 
 
void CFive::GetParam( int& breadth,int& deep,int& thread,int& delta ) 
{ 
	breadth = BreadthMax; 
	deep    = DeepMax; 
	thread  = ThreadDeepMax; 
	delta   = Delta; 
} 
 
int CFive::Dump( int x ,int Wf ) 
{  
	if( Wf == 1 ) 
	{ 
		switch(x) 
		{ 
		case 1:return WF0_1; 
		case 2:return WF0_2; 
		case 3:return WF0_3; 
		case 4:return WF0_4; 
		} 
	} 
	else if( Wf == 0 ) 
	{ 
		switch(x) 
		{ 
		case 1:return WF1_1; 
		case 2:return WF1_2; 
		case 3:return WF1_3; 
		case 4:return WF1_4; 
		} 
	} 
	else if( Wf == 2 ) 
	{  
		if( x == 4 ) 
			return WF2_4; 
		if( x == 3 ) 
			return WF2_3; 
	} 
  if( x == 5 ) 
	{ 
		return WF5; 
	} 
  return -1; 
} 
 
int CFive::GetDump( int x,int Wf ) 
{ 
	return Dump( x,Wf ); 
} 
 
void CFive::SetDump( int x ,int Wf,int c ) 
{  
	if( Wf == 1 ) 
	{ 
		switch(x) 
		{ 
		case 1: 
			WF1_1 = c; 
			return; 
		case 2: 
			WF1_2 = c; 
			return; 
		case 3: 
			WF1_3 = c; 
			return; 
		case 4: 
			WF1_4 = c; 
			return; 
		} 
	} 
	else if( Wf == 0 ) 
	{ 
		switch(x) 
		{ 
		case 1: 
			WF0_1 = c; 
			return; 
		case 2: 
			WF0_2 = c; 
			return; 
		case 3: 
			WF0_3 = c; 
			return; 
		case 4: 
			WF0_4 = c; 
			return; 
		} 
	} 
	else if( Wf == 2 ) 
	{  
		if( x == 4 ) 
		{WF2_4 = c; 
		return; 
		} 
		if( x == 3 ) 
		{ 
			WF2_3 = c; 
			return; 
		} 
	} 
 
if( x == 5 ) 
{ 
	WF5 = c; 
	return; 
} 
} 
 
long CFive::SreachLine( char *Fline,int M,char Nf ) 
 {  
	char Wf; 
	int  i = 0; 
	int  j = 0; 
	int  n = 0; 
	int  k = 0; 
	long count = 0; 
 
	if( Nf == 'B' ) 
		Wf = 'W'; 
	else  
		Wf = 'B'; 
 
	while( M - j >= 5 ) 
	{  
		while( Fline[ i+j ] != Wf && i+j < M ) 
			i++; 
		if( i > 4 ) 
		{  
			for( k = 0; k < i; k++ ) 
			{ 
				n = 0; 
			while( Fline[ j+k ] == Nf && k < i ) 
			{  
				n++; 
				k++;  
			} 
			if( n ) 
			{  
				if( n > 4 ) 
					return -1;              //发现5子 
				if( n == k || k == i ) 
					Wf = 0; 
				else 
					Wf = 1; 
				if( n == 2 && Wf == 1 ) 
					if((k+13&&Fline[ j+k-4 ]==Nf)) 
				       {  
					     n++; 
				         Wf = 2; 
				       } 
				if( n == 3 && Wf == 0 ) 
					if((k+14&&Fline[ j+k-5 ]==Nf)) 
				       {  
					     n++; 
						 Wf = 2;  
				       } 
				count = count + Dump( n , Wf ); 
			} 
			} 
		} 
		j = j + i + 1; 
		i = 0; 
	} 
	return count; 
 } 
 
long CFive::SreachArea( char Area[][FIVE_MAX_LINE],char Nf ) 
 {  
	int i,j,cbak; 
	long count = 0; 
	char Fline[FIVE_MAX_LINE]; 
	 
	for( i = 0; i < FIVE_MAX_LINE; i++ ) 
	{  
		for( j = 0; j < FIVE_MAX_LINE; j++ ) 
			Fline[j] = Area[i][j]; 
		cbak = SreachLine( Fline,FIVE_MAX_LINE,Nf ); 
		if( cbak == -1 ) 
			return -1; 
		else  
			count = count + (long)cbak; 
	} 
 
	 for( i = 0; i < FIVE_MAX_LINE; i++ ) 
	 {  
		 for( j = 0; j < FIVE_MAX_LINE; j++ ) 
			 Fline[j] = Area[j][i]; 
		 cbak = SreachLine( Fline,FIVE_MAX_LINE,Nf ); 
		 if( cbak == -1 ) 
			 return -1; 
		 else  
			 count = count + (long)cbak; 
	 } 
 
	 for( i = 0; i < FIVE_MAX_LINE - 4; i++ ) 
	  {  
		 for( j = 0; j < FIVE_MAX_LINE - i; j++ ) 
			 Fline[j] = Area[i+j][j]; 
		 cbak = SreachLine( Fline, FIVE_MAX_LINE-i, Nf ); 
		 if( cbak == -1 ) 
			 return -1; 
		 else count = count + (long)cbak; 
	 } 
 
	 for( i = FIVE_MAX_LINE-1; i > 3; i-- ) 
	 {  
		 for( j = 0; j < i+1; j++ ) 
			 Fline[j] = Area[i-j][j]; 
		 cbak = SreachLine( Fline, i+1, Nf ); 
		 if( cbak == -1 ) 
			 return -1; 
		 else  
			 count = count + (long)cbak; 
	 } 
 
	 for( i = 0; i < FIVE_MAX_LINE - 5; i++ ) 
	  {  
		 for( j = 0; j < FIVE_MAX_LINE - i; j++ ) 
			 Fline[j] = Area[i+j][FIVE_MAX_LINE-j]; 
		 cbak = SreachLine( Fline, FIVE_MAX_LINE-i, Nf ); 
		 if( cbak == -1 ) 
			 return -1; 
		 else  
			 count = count + (long)cbak; 
	  } 
 
	 for( i = FIVE_MAX_LINE-1; i > 4; i-- ) 
	  {  
		 for( j = 0; j < i+1; j++ ) 
			 Fline[j] = Area[i-j][FIVE_MAX_LINE-j]; 
		 cbak = SreachLine( Fline, i+1, Nf ); 
		 if( cbak == -1 ) 
			 return -1; 
		 else  
			 count = count + (long)cbak; 
	  } 
	 return count; 
 } 
 
int CFive::WzqRun( int &mm, int &nn ) 
{ 
	char     Mf,Nf; 
	int      i,j; 
	double   max; 
	POSITION pos; 
	Count    tempcount,temp_count; 
 
	Nf = CurSide; 
 
	for( i = 0;i pCount[0].count ) 
					{ 
						pCount[0].count     = TempCount; 
						pCount[0].step.side = Nf; 
						pCount[0].step.m    = i; 
						pCount[0].step.n    = j; 
						for( num = 1;num < CurBreadth;num++ ) 
							if( pCount[0].count > pCount[num].count ) 
						      { 
							     temp = pCount[num]; 
								 pCount[num] = pCount[0]; 
								 pCount[0] = temp; 
						      } 
					} 
					Area[i][j] = 'N'; 
				} 
			} 
		} 
		break; 
	case COUNT_SUB: 
		Mcount = SreachArea( Area,Mf ); 
		for( i = 0;i < FIVE_MAX_LINE;i++ ) 
		{ 
			for( j = 0;j < FIVE_MAX_LINE;j++ ) 
			{ 
			    if( Area[i][j] == 'N' ) 
				{ 
					Area[i][j] = Nf; 
					TempCount = Mcount - SreachArea( Area,Mf ); 
					if( TempCount > pCount[0].count ) 
					{ 
						pCount[0].count     = TempCount; 
						pCount[0].step.side = Nf; 
						pCount[0].step.m    = i; 
						pCount[0].step.n    = j; 
						for( num = 1;num < CurBreadth;num++ ) 
							if( pCount[0].count > pCount[num].count ) 
						      { 
							     temp = pCount[num]; 
								 pCount[num] = pCount[0]; 
								 pCount[0] = temp; 
						      } 
					} 
					Area[i][j] = 'N'; 
				} 
			} 
		} 
		break; 
	case COUNT_MID: 
		Mcount = SreachArea( Area,Mf ); 
		Ncount = SreachArea( Area,Nf ); 
		for( i = 0;i < FIVE_MAX_LINE;i++ ) 
		{ 
			for( j = 0;j < FIVE_MAX_LINE;j++ ) 
			{ 
			    if( Area[i][j] == 'N' ) 
				{ 
					Area[i][j] = Nf; 
					wf5temp = SreachArea( Area,Nf ); 
					if( wf5temp == -1 ) 
						wf5temp = Ncount + 2*Dump( 5,10 ); 
					TempCount1 = wf5temp - Ncount; 
					TempCount = Mcount - SreachArea( Area,Mf ); 
					TempCount = TempCount + TempCount1; 
					if( TempCount > pCount[0].count ) 
					{ 
						pCount[0].count     = TempCount; 
						pCount[0].step.side = Nf; 
						pCount[0].step.m    = i; 
						pCount[0].step.n    = j; 
						for( num = 1;num < CurBreadth;num++ ) 
							if( pCount[0].count > pCount[num].count ) 
						      { 
							     temp = pCount[num]; 
								 pCount[num] = pCount[0]; 
								 pCount[0] = temp; 
						      } 
					} 
					Area[i][j] = 'N'; 
				} 
			} 
		} 
		break; 
	} 
 
	for( num = 0;num < CurBreadth;num++ ) 
		if( pCount[num].step.side != 'E' ) 
		    CountList.AddHead( pCount[num] ); 
	delete pCount; 
  }//end if( CurBreadth <= 0 ) 
} 
 
void CFive::AddDeepList( Step step ) 
{ 
	DeepList.AddTail( step ); 
} 
 
Step CFive::GetLastDeepList() 
{ 
	return DeepList.GetTail(); 
} 
 
double CFive::GetStepCount() 
{ 
	POSITION pos; 
	double   temp; 
	Count    steptemp; 
	temp = 0; 
	pos = DeepList.GetHeadPosition(); 
	while(pos != NULL) 
	{ 
		steptemp = CountList.GetNext(pos); 
        temp = steptemp.count + temp; 
	} 
	return (temp+CurCount); 
} 
 
void CFive::ThreadRun() 
{ 
	if( CurDeep <=0&&CurBreadth <= 0 ) 
	{ 
		EndEvent.SetEvent(); 
		return; 
	} 
 
	if( CurThreadDeep < 0 ) 
	{ 
		POSITION pos,postemp; 
		CFive **pFive; 
		int i,num; 
		i = 0; 
		CalRun( CurSide, COUNT_INC ); 
		num = CountList.GetCount(); 
		pFive = (CFive**)new BYTE[sizeof(CFive*)*num]; 
		pos = CountList.GetHeadPosition(); 
		while(pos) 
		{ 
			pFive[i] = new CFive( CurSide,CurDeep,CurBreadth,CurThreadDeep ); 
			postemp = DeepList.GetHeadPosition(); 
			while( postemp ) 
			{ 
				pFive[i] -> AddDeepList( DeepList.GetNext( postemp )); 
			} 
			pFive[i] -> AddDeepList( CountList.GetNext( pos ).step ); 
			pFive[i] -> CreateThread();  //Create thread 
			i++; 
		} 
		for( i=0;i < num;i++ ) 
		{ 
			CSingleLock event( &pFive[i] -> EndEvent ); 
			event.Lock(); 
			event.Unlock(); 
			CurCount += pFive[i] -> GetStepCount(); 
			if( CurDeep == 1) 
			{ 
				Count count_temp; 
			    count_temp.step  = pFive[i] -> GetLastDeepList(); 
				count_temp.count = pFive[i] -> GetStepCount(); 
				TempDeepList.AddTail( count_temp ); 
			} 
			delete pFive[i]; 
		} 
		delete pFive; 
	} 
	else 
	{ 
		int i,num; 
		POSITION pos,postemp; 
		CalRun( CurSide,COUNT_INC ); 
		num = CountList.GetCount(); 
		pos = CountList.GetHeadPosition(); 
		while( pos ) 
		{ 
			{ 
			postemp = DeepList.GetHeadPosition(); 
			CFive five( CurSide,CurDeep,CurBreadth,CurThreadDeep ); 
			while( postemp ) 
			{ 
				five.AddDeepList( DeepList.GetNext( postemp )); 
			} 
			five.AddDeepList( CountList.GetNext( pos ).step ); 
			i++; 
			five.ThreadRun(); 
			CurCount += five.GetStepCount(); 
			if( CurDeep == 1) 
			{ 
				Count count_temp; 
			    count_temp.step = five.GetLastDeepList(); 
				count_temp.count = five.GetStepCount(); 
				TempDeepList.AddTail( count_temp ); 
			} 
			} 
		} 
	} 
 
EndEvent.SetEvent(); 
} 
 
BOOL CFive::InitInstance() 
{ 
	ThreadRun(); 
	return FALSE; 
}