1. 程式人生 > >象棋人工智慧演算法的C++實現(三)——注重功能分割槽!!!

象棋人工智慧演算法的C++實現(三)——注重功能分割槽!!!

前言:上一期部落格我們介紹了相對簡單的士、兵、相、馬的走棋演算法,本期部落格將重點介紹比較複雜的車和炮的走棋演算法。

1.車的走棋演算法

車的走棋規則:沿直線行走。

上canMoveCHE函式的原始碼:

bool Board::canMoveCHE(int moveid,int row,int col,int killid)
{
    if(num_of_Stone(moveid,row,col)==0)
        return true;

    return false;
}

演算法解析:看到這裡讀者可能會有點懵圈,咦?不是說車的走棋演算法是比較複雜的嗎?為什麼它的走棋規則那麼短?canMoveCHE函式內容也那麼少?車的走棋規則看似簡單,實則比較複雜。規則上說沿直線行走,那麼車和目標位置之間如果隔了棋子車還能行走嗎?答案顯而易見。函式體之所以那麼簡單,是因為(一)中有了介紹num_of_Stone函式的鋪墊。如果不提前寫好num_of_Stone函式,canMoveCHE函式有多長就可想而知了吧。num_of_Stone函式在(一)中重點介紹過了,這裡需要注意的是,若當前位置和目標位置不在同一行或不在同一列,num_of_Stone函式返回-1,也就是說,num_of_Stone函式不僅判斷了車與目標位置之間隔了幾個棋子,還判斷了車與目標位置在不在同一行或同一列上,一舉兩得。

2.炮的走棋演算法:

炮的走棋規則:沿直線行走。若炮的目標位置上有棋子,則必須要求炮與目標位置之間隔著一個棋子。

上canMovePAO函式的原始碼:

bool Board::canMovePAO(int moveid,int row,int col,int killid)
{
    if((num_of_Stone(moveid,row,col)==1&&killid!=-1)||(num_of_Stone(moveid,row,col)==0&&killid==-1))
        return true;

    return false;
}

演算法解析:炮是不是沿直線行走還是通過num_of_Stone來控制,num_of_Stone函式的返回值若為-1則表示炮的當前位置與目標位置不在一條直線上。炮的行走分兩種情況,一種是吃子,另一種是不吃子。吃子和不吃子通過傳進來的引數killid來判斷,killid即被吃棋子的id,killid=-1表示不吃子,killid的範圍在0~31之間(包括0和31)表示吃子。吃子和不吃子完全要分兩種不同的情況來處理,若不吃子則要求炮的當前位置與目標位置之間不能有棋子,即num_of_Stone函式的返回值為0;若吃子則要求炮的當前位置與目標位置之間只能有一個棋子,即num_of_Stone函式的返回值為1。

炮的行走圖示(炮的原位置即為炮在棋盤上的初始位置):

小結:本期部落格重點想要表達的是,要注重功能分模組(函式)實現,不要一個函式寫一大堆寫完自己都覺得看不懂。功能分模組實現的好處還有可以實現程式碼的複用,比如num_of_Stone這個函式,既在canMoveCHE函式中用到了又在canMovePAO函式中用到了,這樣既讓自己的程式碼變得整潔清晰明瞭,又偷了工減了料,豈不美哉?

這個專案我會連載,後期各種演算法的實現敬請期待!