Qt開發之中國象棋篇(四) 棋子移動(上)

2021-09-03 07:20:11 字數 3892 閱讀 7260

有了前兩篇的象棋棋盤和象棋棋子的鋪墊,那麼基本的象棋的雛形就出來,接下來要完善各個棋子行走的規則就可以讓棋子移動起來,在貼**之前,讓我們回想一下象棋棋子的行走規則吧!在象棋中:士走斜線,象走田字格,馬走日子格,車和炮都能直接移動,兵只能前進,不能後退,過河不能左右移動,過河後可以移動,將只能在規定的方格中行走。這是象棋棋子行走規則的基本規則,下面看看詳細的移動步驟實現。

// 判斷一顆棋子能不能移動

bool canmove(int moveid, int killid, int x, int y);

// 判斷士能不能移動

bool canmoveshi(int moveid,int killid, int x,int y);

// 判斷兵能不能移動

bool canmovebing(int moveid, int killid, int x, int y);

// 判斷象能不能移動

bool canmovexiang(int moveid, int killid, int x, int y);

// 判斷馬能不能移動

bool canmovema(int moveid, int killid, int x, int y);

// 判斷車能不能移動

bool canmoveche(int moveid, int killid, int x, int y);

// 判斷炮能不能移動

bool canmovepao(int moveid, int killid, int x, int y);

// 判斷將能不能移動

bool canmovejiang(int moveid, int killid, int x, int y);

// 輸入行列座標判斷該座標上有沒有棋子

bool bechess(int row, int col);

// 輸入行列座標獲取棋子的id

int getchessid(int row, int col);

// 計算即將行走的棋子與某一座標之間有幾顆棋子

int numchess(int moveid, int x, int y);

// 判斷兩個棋子是否是同一方的

bool samecolor(int id1, int id2);

接著在 chessarea.cpp 中實現具體的方法描述:

// 輸入行列座標判斷該座標上有沒有棋子

bool chessarea::bechess(int row, int col)

// 計算即將行走的棋子與某一座標之間有幾顆棋子

int chessarea::numchess(int moveid, int x, int y)

}return sum;

}else if(mychess[moveid].col == y)

}return sum;

}//兩個棋子不在一條直線上

return -1;

}

numchess 函式的實現要依賴bechess函式,bechess函式實現就是檢查一遍輸入引數的橫縱座標和棋子的橫縱座標是否相同。numchess函式借用bechess函式,在同一直線上,計算移動前和移動後的橫縱座標差值,再根據差值檢測該位置上面是否存在棋子,如果存在棋子那麼sum就自加,如果沒有,那麼兩個棋子就不在同一根直線,則返回-1。numchess函式在後面的車和炮行走規則中起關鍵作用,下面開始實現各個棋子的行走規則。

士的走法:

bool chessarea::canmoveshi(int moveid, int killid, int x, int y)

else

// 判斷是否為沿著對角線斜著行走

int dx = mychess[moveid].row - x;

int dy = mychess[moveid].col - y;

if(abs(dx)==1 && abs(dy)==1)

return true;

return false;

}

要想讓士沿著對角線斜著走,那麼就要讓士移動前後的橫座標差的絕對值和縱座標差的絕對值都為1,否則士不能移動。

兵的走法:

bool chessarea::canmovebing(int moveid, int killid, int x, int y)

else /* 過河後 */

else return false;}}

else /* 黑棋 */

else /* 過河後 */

else return false;}}

return false;

}

兵的走法比士的走法複雜,考慮的細節也較多。首先無論兵有沒有過河都不能回頭走,過河後,兵才能向左右走。根據這個規則**可以分為紅方和黑方的兵過河前和過河後四個方面進行處理,這樣子邏輯比較容易理解。

馬的走法:

bool chessarea::canmovema(int moveid, int killid, int x, int y)

else if(abs(dy)==2)

}return false;

}

馬的走法是走日字格,那麼就有兩種情況,一種是橫座標絕對值差為2,縱座標絕對值差為 1,還有一種是縱座標絕對值差為2,橫座標絕對值差為 1。除了這樣之後,還要注意別馬腳判斷,那麼依靠橫縱座標差的中值座標可以獲取到中值座標,根據這個座標值,呼叫bechess函式判斷在該位置是否有棋子別馬腳,如果有棋子那麼不能走。

象的走法:

bool chessarea::canmovexiang(int moveid, int killid, int x, int y)

else/* 黑象 */

//走田字格

int dx = mychess[moveid].row - x;

int dy = mychess[moveid].col - y;

int medium_x = (mychess[moveid].row + x)/2;

int medium_y = (mychess[moveid].col + y)/2;

if(abs(dx)==2 && abs(dy)==2)

return false;

}

如果懂了前面馬的走法,那麼象的走法就比較簡單了,基本相似。注意象也是需要做別象腳檢測。

車的走法:

bool chessarea::canmoveche(int moveid, int killid, int x, int y)

車的走法有了前面numchess的鋪墊,那麼就可以變得很簡潔。

炮的走法:

bool chessarea::canmovepao(int moveid, int killid, int x, int y)

炮的走法和車的很相似,能走沿著直線走,但炮和車唯一的不同就是:炮是隔著乙個棋子才能吃棋子。

將的走法:

bool chessarea::canmovejiang(int moveid, int killid, int x, int y)

// 在田字格裡面行走

if(y<=9 && y>=7 && step==1)

return true;

}//黑棋

else

//在田字格裡面行走

if(y>=0 && y<=2 && step==1)

return true;

}return false;

}

棋子將的走法只能在公尺字格裡面走,每次只能走乙個步長,另外注意,當雙方的將在同一直線上,而且沒有隔著任何棋子時,那麼將就可以吃掉對方的將。

Qt中國象棋之棋子規則

中國象棋中各棋子的規則 此棋子是中國象棋中棋力最強的棋子,每行一步棋可以上 下直線行走 進 退 左 右橫走 中間不隔棋子 且行棋步數不限,但不可以走對角線。不過車吃棋的話沒有其他條件限制,只要在他的行走範圍之內就可以被他吃掉。車能否移動到目標位置 座標 bool chessboard canmove...

(二)QT實現中國象棋(棋子實現)

簡介 第二部份主要功能是在棋盤上畫棋子,使用到幾個重要函式把陣列下標轉換為畫素等。1 工程中新增主要檔案如下所示 short num short x,short y,short size 將畫素轉化為陣列下標 else n 0 return n short posx short n,short si...

Qt版本中國象棋開發(三)

實現功能 棋子初始化及走棋規則 棋子類 1 ifndef stone h 2 define stone h 34 include 5 6class stone7 1314 int row 棋子所在行 15int col 棋子所在列 16 type type 棋子型別 jiang,che.1718 1...