第18篇 Qt实现简单五子棋游戏(二)算法说明

第18篇 Qt实现简单五子棋游戏(二)算法说明

5.算法说明

5.1.画棋盘: void drawChessboard();

绘制棋盘横线、竖线。
因为在绘制之前,我们已经初始化了棋盘,即我们可以知道棋盘的起点在哪,有多少行多少列,且线与线之间的距离多大,数据都有,获取之后可进行绘制。

竖线,获取一条线的x = this->chessBoard->getStart_x(),若其还在范围之内,则进行绘制,起点和终点的横坐标都为x,起点纵坐标为this->chessBoard->getStart_y(),终点纵坐标为his->chessBoard->getStart_y() + linespace * (row – 1);

横线,竖线,获取一条线的y = this->chessBoard->getStart_y(),若其还在范围之内,则进行绘制,起点和终点的纵坐标都为y,起点横坐标为this->chessBoard->getStart_x(),终点横坐标为his->chessBoard->getStart_x() + linespace * (col – 1);

5.2.画棋子:void drawChess();

绘制棋子。
遍历表示棋盘的数组(标记位置是否落子),计算其对应界面棋盘的位置(注意横坐标在上层循环计算,避免不必要的计算),若该位置有棋子,则绘制对应颜色的棋子。

5.3.鼠标点击响应:void mousePressEvent(QMouseEvent* mevent);

获取点击位置,计算最近的落子点,判断是否可落子,可落子则落入棋子,否则退出,若为人机模式,且玩家已经落子,则获取人机落子位置,每次落子后判断输赢。

首先判断是否在可点击的范围内,若不在范围内则不作任何响应,即点击的是棋盘才会响应。

在点击范围则先判断是否有棋子已经赢了,若赢了则提示,不执行之后的操作,退出当前函数。

没有以上情况则计算离点击位置最近的落子位,若该位置没有落子,则落子。

若为人机模式,则获取电脑落子位置,落子。

5.4.处理棋子:void handleChess(int current_x,int current_y);

把棋子添加到指定数组中,并标记棋盘对应位置为已经落子。

获取当前棋方颜色,标记当前位置已经落子。改变this->isblack的值。保存当前棋子,重绘界面,判断输赢。

5.5.判断是否赢了:bool isWin(int x,int y,int chesscolor);

从四个方向判断是否有五子连串,即以当前位置为出发点,若南-北、东-西、西北-东南、西南-东北,这四个方向有一个或多个存在五子连串,则判为赢。

因为原理和拦截的一样,所以使用拦截涉及到的函数去判断即可。

5.6.获取电脑落子位置:bool getLocation(int& x,int& y,int chesscolor);

按优先级获取最佳落子位置。
//优先级1--------五缺一
//优先级2--------对手五缺一
//优先级3--------四缺一
//优先级4--------对手四缺一
//优先级5--------三角阵
//优先级6--------对手三角阵
//优先级7--------三缺一
//优先级8--------九宫格
//优先级9-------随机

5.7.拦截:bool centreIntercept(int& x,int& y,int max,int color);

拦截头部或尾部或者中间位置,用于阻止或者进攻。

遍历棋盘数组,若当前位置没有落子,则对其进行四个方向的检索,若存在五子连珠的情况,则记录当前位置,并返回真。否则返回假。

5.8.判断是否拦截:bool interceptJudgment(int max);

因为在电脑落子位置获取时,可以检索是否为5,4,3子连珠,因此需进行一定的判断,若果是五子连珠,则直接返回真,若是四子,则判断头部或尾部没有落子,才可返回真,否则返回假,若是三子,则头部和尾部都为真才行。

南北走向检索:bool centreIntercept_SN(int x,int y,int max,int color);
先以当前位置向北检索,若存在当前颜色的棋子,则统计count++,若不存在则退出循环,以当前位置向南检索,若存在当前颜色的棋子,则统计count++,若不存在则退出循环,若count>=max(max是你想要检索的值,判断输赢时传进来的是4,因为判断输赢时当前位置是已经有一颗棋子了,只要以它为中心找出4子即可)。

以下三个都是差不多。

东西走向检索:bool centreIntercept_EW(int x,int y,int max,int color);
西南东北走向检索:bool centreIntercept_WS_EN(int x,int y,int max,int color);
东南西北走向检索:bool centreIntercept_ES_WN(int x,int y,int max,int color);

5.9.破解三角阵:bool breakTriangle(int &x,int &y,int color);

南北走向检索:void breakTriangle_SN(int x, int y, int& count, int color);

int xi = x, yi = y;
    int k = 1;
    if ((yi - 1) >= 0 && this->chessBoard->getLocationColor(xi,yi - 1) == 0) {
        k++;
    }
    yi++;
    while (yi >= 0 && yi < this->chessBoard->getCol() && this->chessBoard->getLocationColor(xi,yi) == color) {
        k++;
        yi++;
    }
    if (yi < this->chessBoard->getCol() && this->chessBoard->getLocationColor(xi,yi) == 0) {
        k++;
    }
    if (k >= 5) {
        count++;

}
看这一段代码,因为是三角,所以不用考虑一条线上的(三角的优先级在后面,一条线的早就已经先判断了)。
K的作用是统计是否存在五子连珠的危险,若存在则记录该位置,返回真。
首先检查该位置的上一个是否是空位,是空位则记录k++,然后进行该位置下面是否存在当前颜色的棋子,若存在则记录k++,否则退出循环,退出之后再判断yi位置是否为空,是则记录k++。
若k大于等于5,则统计这个方向存在危险。
再判断其他位置。
东西走向检索:void breakTriangle_EW(int x, int y, int& count, int color);
西南东北走向检索:void breakTriangle_WN_WS(int x, int y, int& count, int color);
东南西北走向检索:void breakTriangle_EN_ES(int x, int y, int& count, int color);
若八个方向有至少两个位置存在危险,则存在三角,需要破解,记录该位置,返回真。

5.10.九宫格:bool jiuGongge(int& x,int& y,int no_color);

以某一颗棋子为中心,判断四周是否可以落子,并有落子最佳位置。

上一篇:字符串转换


下一篇:CMU团队开发的局部路径导航算法 localPlanner 代码详解以及如何适用于现实小车