?? _gamer.cpp
字號:
/* 下面這個語句段用來對FarWin和NearWin進行判斷和改變,以達到在不同情況下采取不同的搜索方法之目的*/
//-----------------------開始----------------------------------
for(i=0;i<10;i++) // 搜尋是否有走到目的節點的棋子
{
if( tNodes[ 120-MyChessman[i] ].Chessman == type )
data[0].Score += ReachAim; // 若本方有,則給評估函數值加ReachAim(10*27)
else if( tNodes[ MyChessman[i] ].Chessman == enemy )
data[1].Score += ReachAim; // 若對手有,則給評估函數值加ReachAim(10*27)
}
if( FarWin == 1 ) // 若雙方棋子還沒有交鋒,則FarWin為真(非零值)
{
if( MyChessman[0] == 0 ) // 若游戲者原來占據棋盤的正上方,則Pos[0][9]是最
if( Pos[0][9] > Pos[1][0] ) // 前端的棋子,Pos[1][0]是對手最前端的棋子
FarWin = 0; // 交鋒,則FarWin為假(零值)
else if( Pos[0][0] < Pos[1][9] ) // 若游戲者原來占據棋盤的正下方,則Pos[0][0]是最
// 前端的棋子,Pos[1][9]是對手最前端的棋子
FarWin = 0; // 交鋒,則FarWin為假(零值)
}
else // 若雙方棋子已經交鋒
if( NearWin!=1)
{
if( data[0].Score > 8*ReachAim ) // 若已有至少8個棋子到達目的地,即馬上要結束
NearWin = 1; // 則NearWin 為真(非零值)
if( MyChessman[0] == 0 ) // 若游戲者原來占據棋盤的正上方,則Pos[0][0]是最
if( Pos[0][0] > Pos[1][9] ) // 后端的棋子,Pos[1][9]是對手最后端的棋子
NearWin = 1; // 雙方的棋子已經離開,則NearWin 為真(非零值)
else if( Pos[0][9] < Pos[1][0] ) // 若游戲者原來占據棋盤的正下方,則Pos[0][9]是最
// 后端的棋子,Pos[1][0]是對手最后端的棋子
NearWin = 1; // 雙方的棋子已經離開,則NearWin 為真(非零值)
}
if( data[0].Score == 10*ReachAim ) // 若10個棋子全部到達目的地,則將評估值置為最大
{ // 返回
data[0].Score = 20000;
return data[0];
}
data[0].Score = data[1].Score = 0 ; // 最后將評估函數值重置為零,下面開始真正的評估
//-----------------------------結束-----------------------------------------------------
// 開始評估
_Coodinate cood[2],iCood;
k = 120-MyChessman[0]; // k為目的地中的最遠節點的序號
cood[0] = tNodes[k].cood; // cood[0]存放最遠目的節點的坐標
cood[1] = tNodes[ MyChessman[0] ].cood; // cood[1]存放本方初始最后面節點的坐標
int t,m;
for( j = 0;j<2;j++)
{
for(i=Sumdis=0;i<10;i++) // 一次循環完成所有節點(本方或對手)與最遠
{ // 目的節點(或本方初始最后面節點)的距離評估值
iCood = tNodes[ Pos[j][i] ].cood;
t = abs(cood[j].x-iCood.x); // 每個節點與最遠目的節點(本方初始最后面節點)
// 的橫坐標之差的絕對值
m = abs(cood[j].y-iCood.y); // 每個節點與最遠目的節點(本方初始最后面節點)
// 的縱坐標之差的絕對值
m *= 1.15; // 將縱坐標之差的絕對值乘1.15
m += t; // 將兩個值相加
m = m/10; // 將這個和除以10
Sumdis += m*m; // 將上面得到的結果平方和累積
}
if( cood[j].y > 100 ) // 若本方原來占據了正上方,則t=0
t = 0;
else t = 5; // 若本方原來占據了正下方,則t=5
for(i = t;i < t+4;i++) // 若走后邊的棋子則有加分
if( (h = tNodes[ Pos[j][i+1] ].cood.y - tNodes[ Pos[j][i] ].cood.y ) > 50 )
Sumdis += (h-1)*150/27;
data[j].Score += DisStep*( 20000 - Sumdis ) ; // 得到該游戲者的評估值
}
if( NearWin == 0 && FarWin == 0 ) // 若處于中盤階段則需要從本方的評估值中
// 減掉對手的評估值與權重的乘積
data[0].Score -= data[1].Score*EnemyScoreQuotiety;
return data[0];
}
//---------------------------------------------------------------------------------------------
void _Robot::GetAllMyPath(_Path *AllPath,_Nodes *tNodes,int type)
{ // 取得所有可走路徑的函數,參數分別為指向存放所有
// 可走位置數組的指針,指向棋盤的指針,游戲者序號
// 將結果記錄在第一個參數中
int n,i,k,j;
int chess[10]; // 記錄當前10個棋子位置的數組
for(i=k=0;i<121;i++) // 搜索10個指定棋子的位置
{
if( tNodes[i].Chessman == type )
chess[k++] = i;
tNodes[i].visited = 0; // 所有的棋子目前都沒有被訪問
}
_Nodes Node;
for(i=0;i<10;i++) // 對10個棋子進行循環
{
n=0;
AllPath[i].count = 0; // 第i個棋子可走的位置有0個
AllPath[i].start =chess[i]; // 記錄第i個棋子起始點序號
Node=tNodes[AllPath[i].start]; // 當前是棋盤上的第i個棋子的起始點
for(j=0;j<6;j++) // 判斷相鄰的位置是否可以走棋,若是,則記為可走節點
if( Node.pointers[j] != 0 )
if(Node.pointers[j]->Chessman == 0)
Node.pointers[j]->visited =1;
DFS2(AllPath[i].start,tNodes); // 判斷其他的位置是否能夠走棋
for(k=0;k<121;k++) // 記錄所有可以走棋的位置于Allpath數組中
if(tNodes[k].visited ==1)
{
AllPath[i].path[n++]=k;
tNodes[k].visited = 0;
}
AllPath[i].count=n; // 所有可走的位置的總數
}
}
//---------------------------------------------------------------------------------------------
_EvalueData _Robot::Search(_Nodes *tNodes,int Depth) // 全搜索法,參數分別為指向棋盤的指針和搜索深度
{
int i,j,Enemy;
_EvalueData MaxData,NowData; // 存放最大評估值和當前評估值的評估結構體
_Path AllPath[10]; // 存放十個棋子的可走位置
MaxData.Score = -1000; // 最大評估值初始化為-1000
_GamerQuen *tQuen; // 游戲者順序的鏈表
Depth--; // 深度減1many !turns!
GetAllMyPath(AllPath,tNodes,gamerID); // 取得所有可以走的位置
if( gamerID == 1 ) // 確定對手的序號
Enemy = 2;
else Enemy = 1;
for(i=j=0;i<10;i++) // 對10個棋子進行循環
for(j=0;j<AllPath[i].count;j++) // 對該棋子的所有可走節點進行循環
{
// 走到某個節點
tNodes[ AllPath[i].path[j] ].Chessman = tNodes[ AllPath[i].start ].Chessman;
tNodes[ AllPath[i].start ].Chessman = 0;
if(Depth == 0) // 若搜索深度為0,評估當前的棋局
NowData = Evalue(tNodes,gamerID,Enemy);
else // 若搜索深度不為0,則遞歸調用Search
NowData = Search(tNodes,Depth);
if( NowData.Score > MaxData.Score ) // 若當前的棋局比較好,則替換最大評估函數值
{
MaxData.Score = NowData.Score;
MaxData.start = AllPath[i].start ;
MaxData.end = AllPath[i].path[j];
}
// 將這一步走回去,回到原來的狀態
tNodes[ AllPath[i].start ].Chessman = tNodes[ AllPath[i].path[j] ].Chessman;
tNodes[ AllPath[i].path[j] ].Chessman = 0;
}
return MaxData; // 返回最大的評估值
}
//---------------------------------------------------------------------------------------------
_EvalueData _Robot::aBSearch(_Nodes *tNodes,int Depth,int ParentScore)
{ // 剪枝搜索法,參數分別為指向棋盤的指針,
// 搜索深度,上一層的評估值
int i,j,Enemy;
_EvalueData MaxData,NowData; // 存放最優評估值和當前評估值的評估結構體
_Path AllPath[10]; // 存放10個棋子可走位置的數組
_GamerQuen *tQuen; // 指向游戲者順序的鏈表
Depth--; // 搜索深度減1
if( GamerQuen->GamerId == gamerID) // 根據當前節點的歸屬決定它的初值
MaxData.Score = -20000;
else
MaxData.Score = 20000;
GetAllMyPath(AllPath,tNodes,GamerQuen->GamerId); // 取得所有可以走的位置
for(i=j=0;i<10;i++) // 對10個棋子進行循環
for(j=0;j<AllPath[i].count;j++) // 對每個可走的位置進行循環
{
// 走到某個可走的位置
tNodes[ AllPath[i].path[j] ].Chessman = tNodes[ AllPath[i].start ].Chessman;
tNodes[ AllPath[i].start ].Chessman = 0;
// 轉到下一個游戲者
tQuen = GamerQuen,GamerQuen = GamerQuen->Next;
if(Depth == 0) // 若搜索的深度已經為0
{ // 確定對手的序號
if( GamerQuen->GamerId == gamerID)
Enemy = GamerQuen->EnemyId ;
else Enemy = GamerQuen->GamerId ;
// 評估當前的棋局
NowData = Evalue(tNodes,gamerID,Enemy);
}
else // 若搜索的深度不為0,則遞歸搜索
NowData = aBSearch(tNodes,Depth,MaxData.Score);
if( GamerQuen->GamerId == gamerID ) // 若當前游戲者正是原來的游戲者
{
if( NowData.Score <= ParentScore )
{ // 若當前評估函數值小于初值,則減掉這一支
// 將初值賦給最優評估值
MaxData.Score = ParentScore;
// 將這一步再走回去
tNodes[ AllPath[i].start ].Chessman = tNodes[ AllPath[i].path[j] ].Chessman;
tNodes[ AllPath[i].path[j] ].Chessman = 0;
GamerQuen = tQuen; // 將游戲者轉回去
return MaxData;
}
else if( NowData.Score < MaxData.Score )
{ // 若當前評估函數值優于(大于等于)初值,保留
// 將當前值賦給最優評估值
MaxData.Score = NowData.Score;
MaxData.start = AllPath[i].start ;
MaxData.end = AllPath[i].path[j];
}
}
else // 若當前的游戲者已經是原來游戲者的對手
{
if( NowData.Score >= ParentScore )
{ // 若當前的評估值大于等于初值,則減掉這一支
// 將初值賦給最優評估值
MaxData.Score = ParentScore;
tNodes[ AllPath[i].start ].Chessman = tNodes[ AllPath[i].path[j] ].Chessman;
tNodes[ AllPath[i].path[j] ].Chessman = 0;
GamerQuen = tQuen; // 將游戲者轉回去
return MaxData;
}
else if( NowData.Score > MaxData.Score )
{ // 若當前評估值優于(小于)初值,保留
// 將當前值賦給最優評估值
MaxData.Score = NowData.Score;
MaxData.start = AllPath[i].start ;
MaxData.end = AllPath[i].path[j];
}
}
// 將這一步走回去,得到最初的狀態
tNodes[ AllPath[i].start ].Chessman = tNodes[ AllPath[i].path[j] ].Chessman;
tNodes[ AllPath[i].path[j] ].Chessman = 0;
GamerQuen = tQuen; // 將游戲者轉回去
}
return MaxData; // 返回最優的評估值結構體
}
void _Robot::DFS2(int start,_Nodes *tNodes)
{
_Nodes *pNode=NULL;
for(int i=0;i<6;i++) //遍歷一個節點的周圍六個節點
{
pNode=tNodes[start].pointers[i];
if( pNode!=NULL )
if( pNode->pointers[i]!=NULL )
if(pNode->Chessman!=0&&pNode->pointers[i]->Chessman==0&&pNode->pointers[i]->visited==0)
{
pNode->pointers[i]->visited = 1;
DFS2(pNode->pointers[i]->index,tNodes);
}
}
}
//---------------------------------------------------------------------------------------------
void _Robot::GetCondition(int **ids,int count) //_Robot初始化中將會用到
{
_GamerQuen *t; // 指向游戲者鏈表的指針
int i;
GamerQuen = new _GamerQuen(); // 創建新的游戲者列表
GamerQuen->GamerId = ids[0][0]; // 賦值第一個游戲者
if( GamerQuen->GamerId % 2 == 0 ) // 若游戲者序號為奇數,則該游戲者對手序號為本序號+1
GamerQuen->EnemyId = GamerQuen->GamerId - 1;
else // 若游戲者序號為偶數,則該游戲者對手序號為本話號-1
GamerQuen->EnemyId = GamerQuen->GamerId + 1;
t = GamerQuen; // t指向游戲者列表的第一個游戲者
for( i=1;i<count;i++) // 將游戲者的順序輸入到列表中
{
GamerQuen->Next = new _GamerQuen(); // 創建新的游戲者鏈表元素
GamerQuen = GamerQuen->Next; // 為新的游戲者鏈表元素賦值
GamerQuen->GamerId = ids[i][0]; // 確定這個元素的對手是誰
if( GamerQuen->GamerId % 2 == 0 )
GamerQuen->EnemyId = GamerQuen->GamerId - 1;
else GamerQuen->EnemyId = GamerQuen->GamerId + 1;
}
GamerQuen->Next = t; // 將最后一個鏈表元素next指針指向第一個元素
for( i=0;i<count;i++) // 使gamerquen指向當前游戲者
if(GamerQuen->GamerId == gamerID)
break;
else GamerQuen = GamerQuen->Next;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -