分析
在滑鼠左鍵點選時,我們不能讓新棋子在已有棋子的位置落下,同時我們還要讓棋子在規定位置落下——棋盤線的交點處。
功能實作
建立資料類型
- 建立頭檔案chessData.h和源檔案chessData.cpp
- 在chessData.cpp和main.cpp中分别引用頭檔案chessData.h
- 将之前在main.cpp中寫的棋盤資料剪貼到chessData.h中
const float BLOCKSIZE = 67.4;
const int BLOCK_GRAD_SIZE = 13;
- 在chessData.h中定義常量 POS_OFFSET,即滑鼠有效點選距離上限
- 在chessData.h定義結構體 ChessData
struct ChessData{
//儲存目前遊戲棋盤的情況,空白為0,黑棋為1,白棋為-1
int chessMap[BLOCK_GRAD_SIZE][BLOCK_GRAD_SIZE];
//儲存各點的評分情況,用于之後的AI走棋
int scoreMap[BLOCK_GRAD_SIZE][BLOCK_GRAD_SIZE];
bool playFlag; //表示下棋放,true黑棋,false白棋(AI)
};
- 在main.cpp中添加全局變量game
初始化資料類型
- 在chessData.h中添加函數聲明
- 在chessData.cpp
void initChessData(ChessData *data){
if(!data) return;
memset(data->chessMap,0,sizeof(data->chessMap));
memset(data->scoreMap,0,sizeof(data->scoreMap));
data->playFlag = true;
}
判斷有效點選
算法原理

實作
- 在main.cpp中添加全局變量
- 定義函數clickBoard()
//有效點選傳回true,無效點選傳回false
//MOUSEMSG為滑鼠資訊類型
bool clickBoard(MOUSEMSG msg){
//(滑鼠點選坐标 - 邊界長度)/ 格寬 = 行(列)數
//計算列數并取整
int col = (msg.x - MARGIN_X) / BLOCKSIZE;
//計算行數取整
int row = (msg.y - MARGIN_Y) / BLOCKSIZE;
//計算棋子正确坐标,即格子左上角棋子應在的棋盤格線交點處坐标
int leftTopPosX = MARGIN_X + BLOCKSIZE * col;
int leftTopPosY = MARGIN_Y + BLOCKSIZE * row;
}
- 在檔案最上方引用頭檔案math.h用于後期計算
- 之後要判斷棋子應在四個交點中具體哪一點上,這裡我們用一個do-while循環。繼續添加**clickBoard()**函數的定義
int len; //用于計算兩點見的距離(根據中學所學兩點間距離公式)
int selectPos = false; //作為傳回值
do{
//左上角
len = sqrt((msg.x - leftTopPosX)*(msg.x - leftTopPosX) + (y - leftTopPosY)*(msg.y - leftTopPosY));
if(len < POS_OFFSET){
clickPosRow = row;
clickPosCol = col;
if ( game.chessMap[clickPosRow][clickPosCol] == 0 ){
selectPos = true;
}
break;
}
//右上角
len = sqrt((msg.x - leftTopPosX - BLOCKSIZE)*(msg.x - leftTopPosX - BLOCKSIZE) + (y - leftTopPosY)*(msg.y - leftTopPosY));
if(len < POS_OFFSET){
clickPosRow = row;
clickPosCol = col + 1;
if ( game.chessMap[clickPosRow][clickPosCol] == 0 ){
selectPos = true;
}
break;
}
//左下角
len = sqrt((msg.x - leftTopPosX)*(msg.x - leftTopPosX) + (y - leftTopPosY - BLOCKSIZE)*(msg.y - leftTopPosY - BLOCKSIZE));
if(len < POS_OFFSET){
clickPosRow = row + 1;
clickPosCol = col;
if ( game.chessMap[clickPosRow][clickPosCol] == 0 ){
selectPos = true;
}
break;
}
//右下角
len = sqrt((msg.x - leftTopPosX - BLOCKSIZE)*(msg.x - leftTopPosX - BLOCKSIZE) + (y - leftTopPosY - BLOCKSIZE)*(msg.y - leftTopPosY - BLOCKSIZE));
if(len < POS_OFFSET){
clickPosRow = row + 1;
clickPosCol = col + 1;
if ( game.chessMap[clickPosRow][clickPosCol] == 0 ){
selectPos = true;
}
break;
}
}while(0);
return selectPos;
更新底層資料
- chessData.h
- chessData.cpp
void updateGameMap(ChessData* data, int row, int col){
if(!data) return;
if(data->playFlag){
data->chessMap[row][col] = 1;
}else{
data->chessMap[row][col] = -1;
}
data->playFlag = !data->playFlag; //換下棋方
}
- main.cpp
//玩家走棋
void manGo(){
chessDown(clickPosRow,clickPosCol,CHESS_BLACK);
updateGameMap(&game, clickPosRow, clickPosCol);
}