修改:
drawPNG(&chessBlackImg, msg.x, msg.y);
drawPNG(&chessBlackImg, msg.x - 0.5 * BLOCK_SIZE, msg.y - 0.5 * BLOCK_SIZE);
看上去,很完美,但是有一个严重的BUG!!
当不在交叉点准确点击时,就会出现以上情况。
解决方案:
需要判断这个点击是否是合法未知的点击,并允许一定的偏差
判断有效的点击定义数据模型因为点击时,要判断是否在已经有棋子的位置上点击(不能在已经落子的位置点击)
所以需要定义一个数据模型,来表示当前的所有棋子数据。
【模块化开发思想】
创建ChessData.h, 并把main.cpp中的与围棋相关的全局数据,剪贴到ChessData.h中
ChessData.h
#pragma once
const float BLOCK_SIZE = 67.4; // 格子的大小
const int BOARD_GRAD_SIZE = 13; //13x13棋盘大小
const int POS_OFFSET = BLOCK_SIZE * 0.4; // 20 鼠标点击的模糊距离上限
struct ChessData {
// 存储当前游戏棋盘和棋子的情况,空白为0,黑子1,白子-1
int chessMap[BOARD_GRAD_SIZE][BOARD_GRAD_SIZE];
// 存储各个点位的评分情况,作为AI下棋依据
int scoreMap[BOARD_GRAD_SIZE][BOARD_GRAD_SIZE];
// 标示下棋方, true:黑棋方 false: AI 白棋方(AI方)
bool playerFlag;
};
在main.cpp中添加围棋数据变量game
#include "ChessData.h"
ChessData game;
初始化数据模型
ChessData.h
void initChessData(ChessData*); // 开始游戏
ChessData.cpp
void initChessData(ChessData *data)
{
if (!data)return;
memset(data->chessMap, 0, sizeof(data->chessMap));
memset(data->scoreMap, 0, sizeof(data->scoreMap));
data->playerFlag = true;
}
main.cpp
void init() {
......
// 初始化游戏模型
initChessData(&game);
}
7.判断有效点击
判断原理
先计算出绿点,然后分别计算出3个黑点位置,计算当前位置离4个点的位置。
如果小于阈值(POS_OFFSET),就认为选择了哪个点。
在main.cpp中添加变量,存储有效点击的位置
int clickPosRow, clickPosCol; // 存储点击的位置
判断是否是有效点击,如果是有效点击,返回true并把结果保存到全局变量clickPosRow、 clickPosCol;
ChessData.h
const int POS_OFFSET = BLOCK_SIZE * 0.4; // 20 鼠标点击的模糊距离上限
bool clickBoard(MOUSEMSG msg) {
int x = msg.x;
int y = msg.y;
int col = (x - margin_x) / BLOCK_SIZE;
int row = (y - margin_y) / BLOCK_SIZE;
int leftTopPosX = margin_x BLOCK_SIZE * col;
int leftTopPosY = margin_y BLOCK_SIZE * row;
int len;
int selectPos = false;
do {
len = sqrt((x - leftTopPosX) * (x - leftTopPosX) (y - leftTopPosY) * (y - leftTopPosY));
if (len < POS_OFFSET) {
clickPosRow = row;
clickPosCol = col;
if (game.chessMap[clickPosRow][clickPosCol] == 0) {
selectPos = true;
}
break;
}
// 距离右上角的距离
len = sqrt((x - leftTopPosX - BLOCK_SIZE) * (x - leftTopPosX - BLOCK_SIZE)
(y - leftTopPosY) * (y - leftTopPosY));
if (len < POS_OFFSET) {
clickPosRow = row;
clickPosCol = col 1;
if (game.chessMap[clickPosRow][clickPosCol] == 0) {
selectPos = true;
}
break;
}
// 距离左下角的距离
len = sqrt((x - leftTopPosX) * (x - leftTopPosX)
(y - leftTopPosY - BLOCK_SIZE) * (y - leftTopPosY - BLOCK_SIZE));
if (len < POS_OFFSET) {
clickPosRow = row 1;
clickPosCol = col;
if (game.chessMap[clickPosRow][clickPosCol] == 0) {
selectPos = true;
}
break;
}
// 距离右下角的距离
len = sqrt((x - leftTopPosX - BLOCK_SIZE) * (x - leftTopPosX - BLOCK_SIZE)
(y - leftTopPosY - BLOCK_SIZE) * (y - leftTopPosY - BLOCK_SIZE));
if (len < POS_OFFSET) {
clickPosRow = row 1;
clickPosCol = col 1;
if (game.chessMap[clickPosRow][clickPosCol] == 0) {
selectPos = true;
}
break;
}
} while (0);
return selectPos;
}
实现有效点击
int main(void) {
init();
while (1) {
MOUSEMSG msg = GetMouseMsg();
if (msg.uMsg == WM_LBUTTONDOWN && clickBoard(msg)) {
//putimage(msg.x, msg.y, &chessBlackImg);
//drawPNG(&chessBlackImg, msg.x - 0.5 * BLOCK_SIZE, msg.y - 0.5 * BLOCK_SIZE);
int x = margin_x clickPosCol * BLOCK_SIZE - 0.5 * BLOCK_SIZE;
int y = margin_y clickPosRow * BLOCK_SIZE - 0.5 * BLOCK_SIZE;
drawPNG(&chessBlackImg, x, y);
}
}
system("pause");
return 0;
}
测试效果: