?? tic_mfcdlg.cpp
字號:
for (int i=0; i<9; i++)
{
if (Chess[i] == PLAYER)
DrawX (pDC, i);
else if (Chess[i] == COMPUTER)
DrawO (pDC, i);
}
pDC->SelectObject (pOldPen);
}
//********************************************************************************************************
//完成功能:初始化棋盤
//*********************************************************************************************************
void CTic_MFCDlg::Reset()
{
for(int i=0; i<9; i++)
{
Chess[i] = EMPTY;
}
Invalidate ();
}
//********************************************************************************************************
//完成功能:計算機先走
//*********************************************************************************************************
void CTic_MFCDlg::OnStartCom()
{
Reset();
turn = COMPUTER;
UpdateData(true);
SearchDepth = m_dept;
CClientDC dc (this);
int result;
AlphaBeta(Chess,SearchDepth,COMPUTER,-100,100,&result);
Chess[result] = turn;
PutAChess(&dc,result);
}
//********************************************************************************************************
//完成功能:玩家先走
//*********************************************************************************************************
void CTic_MFCDlg::OnStartPly()
{
Reset();
turn = PLAYER;
UpdateData(true);
SearchDepth = m_dept;
}
//********************************************************************************************************
//完成功能:根據輸入棋盤,判斷當前棋盤的結果,COMPUTER勝?PLAYER勝?平局?
//參數: board:待評估棋盤
//返回: -1表示:尚未結束
// 0 表示:平局
// 1 表示:PLAYER勝
// 2 表示:COMPUTER勝
//*********************************************************************************************************
int CTic_MFCDlg::isWin(int curPos)
{
int link;
int i;
int j;
//判斷左上右下斜線是否有三子連線
link = 0;
i = curPos/3;
j = curPos - i*3;
while (i>=0&&j>=0)
{
if( Chess[i*3+j] == Chess[curPos] )
{
link++;
i--;
j--;
}
else
break;
}
i = curPos/3+1;
j = curPos - (curPos/3)*3+1;
while (i<3&&j<3)
{
if( Chess[i*3+j] == Chess[curPos] )
{
link++;
i++;
j++;
}
else
break;
}
if (link >= 3)
return Chess[curPos];
//判斷右上左下斜線是否有三子連線
link = 0;
i = curPos/3;
j = curPos - i*3;
while (i<3&&j>=0)
{
if( Chess[i*3+j] == Chess[curPos] )
{
link++;
i++;
j--;
}
else
break;
}
i = curPos/3-1;
j = curPos - (curPos/3)*3+1;
while (i>=0&&j<3)
{
if( Chess[i*3+j] == Chess[curPos] )
{
link++;
i--;
j++;
}
else
break;
}
if (link >= 3)
return Chess[curPos];
//判斷橫向是否有三子連線
link = 0;
i = curPos/3;
j = curPos - i*3;
while (j>=0)
{
if( Chess[i*3+j] == Chess[curPos] )
{
link++;
j--;
}
else
break;
}
i = curPos/3;
j = curPos - (curPos/3)*3+1;
while (j<3)
{
if( Chess[i*3+j] == Chess[curPos] )
{
link++;
j++;
}
else
break;
}
if (link >= 3)
return Chess[curPos];
//判斷縱向是否有三子連線
link = 0;
i = curPos/3;
j = curPos - i*3;
while (i>=0)
{
if( Chess[i*3+j] == Chess[curPos] )
{
link++;
i--;
}
else
break;
}
i = curPos/3+1;
j = curPos - (curPos/3)*3;
while (i<3)
{
if( Chess[i*3+j] == Chess[curPos] )
{
link++;
i++;
}
else
break;
}
if (link >= 3)
return Chess[curPos];
//檢查是否是平局
for(i = 0;i<9;i++)
{
if(Chess[i]==EMPTY)
break;
}
if(i == 9)
return 0;
return -1;
}
//********************************************************************************************************
//完成功能:放下一個棋子,將turn值在COMPUTER和PLAYER之間交替
//參數: Pos:待放棋子的位置
//*********************************************************************************************************
void CTic_MFCDlg::PutAChess(CDC *pDC,int Pos)
{
//改變turn && 打印棋盤
if (turn == PLAYER)
{
turn = COMPUTER;
DrawX(pDC,Pos);
}
else if (turn == COMPUTER)
{
turn = PLAYER;
DrawO(pDC,Pos);
}
int result = isWin(Pos);
if (result == 0)
{
MessageBox (_T (" 平局! "), _T ("Game Over"),MB_ICONEXCLAMATION | MB_OK);
turn = -1;
}
else if (result == PLAYER)
{
MessageBox (_T (" 玩家勝! "), _T ("Game Over"),MB_ICONEXCLAMATION | MB_OK);
turn = -1;
}
else if (result == COMPUTER)
{
MessageBox (_T (" 電腦勝! "), _T ("Game Over"),MB_ICONEXCLAMATION | MB_OK);
turn = -1;
}
}
//********************************************************************************************************
//完成功能:根據輸入棋盤,判斷當前棋盤的估價值,估價函數為課本P129所講:
// 若是MAX的必勝局,則e = +INFINITY,這里為+60
// 若是MIN的必勝局,則e = -INFINITY,這里為-20,這樣賦值的原因是機器若贏了,則不考慮其它因素。
// 其它情況,棋盤上能使CUMPUTER成三子一線的數目為e1
// 棋盤上能使PLAYER 成三子一線的數目為e2,
// e1-e2作為最終權值
//參數: board:待評估棋盤
//返回: 評估結果
//*********************************************************************************************************
int CTic_MFCDlg::evaluate(int board[])
{
int i,a,b,c;
int result = 0;
for( i=0; i<8; ++i )
{
a = winPattern[i][0];
b = winPattern[i][1];
c = winPattern[i][2];
//機器現三子連珠,賦60作無窮大
if(board[a]==COMPUTER&&board[b]==COMPUTER&&board[c]==COMPUTER)
result+=60;
//否則,權值加1
else if((board[a]==COMPUTER||board[a]==EMPTY)&&(board[b]==COMPUTER||board[b]==EMPTY)&&(board[c]==COMPUTER||board[c]==EMPTY))
result++;
//玩家出現三子連珠,賦-20作無窮小
if(board[a]==PLAYER&&board[b]==PLAYER&&board[c]==PLAYER)
result-=20;
//否則,權值減1
else if((board[a]==PLAYER||board[a]==EMPTY)&&(board[b]==PLAYER||board[b]==EMPTY)&&(board[c]==PLAYER||board[c]==EMPTY))
result--;
}
return result;
}
//********************************************************************************************************
//完成功能:根據輸入棋盤,搜索深度,及其他參數,給出一個相應的最優解,存入result中。
//參數: board :待評估棋盤
// Depth :搜索深度
// turn :當前是機器走(MAX結點)還是玩家走(MIN結點)
// Alpha :alpha值,第一次調用默認-100
// Beta :beta值,第一次調用默認+100
// result:輸出結果
//返回: 若當前點為MAX節點,則返回alpha值;
// 若當前點為MIN節點,則返回beta值
//*********************************************************************************************************
int CTic_MFCDlg::AlphaBeta(int Board[], int Depth, int turn, int Alpha, int Beta, int *result)
{
int score;
if (Depth == 0)
return evaluate(Board); // 葉子節點返回估值
if (turn == PLAYER) // 此句用于判斷當前節點是何種節點
{ // turn=PLAYER表示極小值的節點
for (int i=0;i<9;i++) // 對每一可能的走法m
{
// 生成新節點
if(Board[i] == EMPTY)
{
Board[i] = turn;
score =AlphaBeta(Board, Depth-1, COMPUTER, Alpha, Beta, result); // 遞歸搜索子節點
Board[i] = EMPTY; // 撤銷搜索過的節點
if (score < Beta)
{
Beta = score ; // 取極小值
if (Alpha >= Beta)
return Alpha ; // 剪枝,拋棄后繼節點
}
}
}
return Beta ; // 返回最小值
}
else
{ // 取極大值的節點
for (int i=0;i<9;i++) // 對每一可能的走法m
{
// 生成新節點
if(Board[i] == EMPTY)
{
Board[i] = turn;
score =AlphaBeta(Board, Depth-1, PLAYER, Alpha, Beta, result) ; // 遞歸搜索子節點
Board[i] = EMPTY; // 撤銷搜索過的節點
if (score > Alpha)
{
if (Depth == SearchDepth)
*result = i;
Alpha = score ; // 取極大值
if (Alpha >= Beta)
return Beta ; // 剪枝,拋棄后繼節點
}
}
}
return Alpha ; // 返回最大值
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -