//去除边框
this->setWindowFlags(Qt::FramelessWindowHint);
startPoint = QPoint(147,68); //起点坐标
endPoint = QPoint(1003,670); //终点坐标
gridWidth = (endPoint.x() - startPoint.x())/8;
gridHigh = (endPoint.y() - startPoint.y())/8;
initChess();
connect(&timer, &QTimer::timeout, this, &Widget::machinePlay);
}
初始化棋盘,用
chessStatus数组的状态代表棋盘的状态。
void Widget::initChess()
{
whiteFlag = blackFlag = true;//一开始双方都能落子
overFlag = false; //一开始游戏不结束
bNumber = wNumber = 0;
memset(chessStatus,0,sizeof(chessStatus));
//中间四子:两白两黑
chessStatus[3][3] = Black;
chessStatus[4][3] = White;
chessStatus[3][4] = White;
chessStatus[4][4] = Black;
role = White; //默认白子先下
ui->labelWhite->show();
ui->labelBlack->hide();
ui->lcdNumberWhite->display(2);
ui->lcdNumberBlack->display(2);
}
绘制如下:这个项目的重点就是在一开始就把棋盘的起点坐标和方格的大小都知道了,从而当鼠标点击的时候,就会知道点击的是哪个方格。
void Widget::paintEvent(QPaintEvent *)
{
//绘图事件,画棋盘,画棋子
QPainter p(this); //创建画家,指定窗口为画布
//背景图(棋盘)
p.drawPixmap(this->rect(),QPixmap(":/image/chess2.png"));
int startX = 0;
int startY = 0;
//根据棋盘二维数组的状态画棋子
for(int i = 0; i < 8; i++){
for(int j = 0; j < 8; j++){
startX = startPoint.x() + i*(gridWidth+1);
startY = startPoint.y() + j*(gridHigh+1);
if(chessStatus[i][j] == Black){
//画黑子
p.drawPixmap(startX, startY,
gridWidth-7, gridHigh-4, QPixmap(":/image/Black.png"));
}
else if(chessStatus[i][j] == White){
//画白子
p.drawPixmap(startX, startY,
gridWidth-7, gridHigh-4, QPixmap(":/image/White.png"));
}
}
}
}
黑白棋的逻辑如下:
int Widget::judgeRole(int x, int y, ChessFlag currentRole, bool eatChess)
{
//落子的八个方向
int dir[8][2] = {{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1}};
int tmpX = x,tmpY = y; //临时保存棋盘坐标位置
int i = 0, eatNum = 0; //初始化数据
if(chessStatus[tmpX][tmpY] != Empty){//如果此方格中已经有棋子无效操作,直接返回
return 0;
}
//棋盘的8个方向
for(i=0; i<8; i++){
//从鼠标点击点开始
tmpX = x;
tmpY = y;
//确定一个方向:dir[i][0]
tmpX += dir[i][0];
tmpY += dir[i][1];
if(tmpX < GRID_NUMBER && tmpX >= 0 && tmpY < GRID_NUMBER && tmpY >= 0
&& (chessStatus[tmpX][tmpY] != currentRole) && (chessStatus[tmpX][tmpY] != Empty)){
//如果没有出界并且相邻棋子是对方棋子才有可能吃子
tmpX += dir[i][0];
tmpY += dir[i][1];//向前走一步,开始判断该方向还有无自己棋子
while(tmpX < GRID_NUMBER && tmpX >= 0 && tmpY < GRID_NUMBER && tmpY >= 0){
if(chessStatus[tmpX][tmpY] == Empty){
break;//遇到空位跳出循环,外部if最后一个条件也会不满足,则直接判断下一个方向
}
if(chessStatus[tmpX][tmpY] == currentRole){//找到自己的棋子代表可以吃子
//能吃子则点击点标记为自己的棋子,update后是自己的棋子,否则点击处不能落子
(true == eatChess) ? (chessStatus[x][y] = currentRole) : true;
tmpX -= dir[i][0];
tmpY -= dir[i][1];//回退一步开始吃子
//没有回到开始的位置就继续执行
while((tmpX != x) || (tmpY != y)){//没有回退到点击处则继续修改原有棋子状态
//若为true则为落子,修改为自己的棋子,如果为false则为测试,不用修改
(true == eatChess) ? (chessStatus[tmpX][tmpY] = currentRole) : true;
tmpX -= dir[i][0];
tmpY -= dir[i][1];//回退一格,继续
eatNum++; //吃子累计
}
break;//跳出循环,结束该方向的判断
}
//没找到自己的棋子就向前(指定方向)走一步,走到0或GRID_NUMBER边界条件时就结束该层if语句
tmpX += dir[i][0];
tmpY += dir[i][1];
}
}
}
return eatNum;
}
电脑下子时:找到的是最大吃子的位置,而且调用的是
judgeRole同一个方法,
void Widget::machinePlay()
{
timer.stop();//定时器停止
int max = 0, num = 0;
int px = 0, py = 0;
**收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。**


**[如果你需要这些资料,可以戳这里获取](https://gitee.com/vip204888)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人**
**都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**