赞
踩
学习视频链接
目录
- #ifndef GAMEMODEL_H
- #define GAMEMODEL_H
-
- #include <vector>
-
- // 游戏类型,双人还是AI(目前固定让AI下黑子)
- enum GameType
- {
- MAN, // 双人模式
- AI // 人机对弈模式
- };
-
- // 游戏状态
- enum GameStatus
- {
- PLAYING, // 游戏中
- WIN, // 赢了
- DEAD // 和棋
- };
-
- // 棋盘尺寸
- const int BOARD_GRAD_SIZE = 15;
-
- const int MARGIN = 30; // 棋盘边缘空隙
- const int CHESS_PADTUS = 15; // 棋子半径
- const int MARK_SIZE = 6; // 落子标记边长
- const int BLOCK_SIZE = 40; // 格子的大小
- const int POS_OFFSET = BLOCK_SIZE * 0.4; // 20 鼠标点击的模糊距离上限
-
- const int AI_THINK_TIME = 700; // AI下棋思考时间
-
- class GameModel
- {
- public:
- GameModel();
- ~GameModel();
-
- public:
- // 存储当前游戏棋盘和棋子的情况,空白为0,黑子1,白子-1
- std::vector<std::vector<int>> gameMapVec;
-
- // 存储各个点位的评分情况,作为AI下棋依据
- std::vector<std::vector<int>> scoreMapVec;
-
- // 标示下棋方,true:黑棋方 false:AI白棋方
- bool playerFlag;
-
- GameType gameType; // 游戏模式:人机对弈,还是双人
-
- GameStatus gameStatus; // 游戏状态
-
- void startGame(GameType type); // 开始游戏
- void calculateScore(); // 计算评分
- void actionByPerson(int row, int col); // 人执行下棋
- void actionByAI(int &clickRow, int &clickCol); // 机器执行下棋
- void updateGameMap(int row, int col); // 每次落子后更新游戏棋盘
- bool isWin(int row, int col); // 判断游戏是否胜利
- bool isDeadGame(); // 判断是否和棋
- };
-
- #endif // GAMEMODEL_H
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
-
- #include <QMainWindow>
- #include <QPainter>
- #include "gamemodel.h"
-
- QT_BEGIN_NAMESPACE
- namespace Ui { class MainWindow; }
- QT_END_NAMESPACE
-
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
-
- public:
- MainWindow(QWidget *parent = nullptr);
- ~MainWindow();
- void paintEvent(QPaintEvent *event);
- void initGame();
- void initAIGame();
-
- private:
- Ui::MainWindow *ui;
- GameModel *game; // 游戏指针
- GameType game_type; // 存储游戏类型
- };
- #endif // MAINWINDOW_H
- #include "gamemodel.h"
-
- GameModel::GameModel()
- {
-
- }
-
- GameModel::~GameModel()
- {
-
- }
-
- void GameModel::startGame(GameType type)
- {
- gameType = type;
-
- //初始棋盘
- gameMapVec.clear() ;
- for(int i = 0; i < BOARD_GRAD_SIZE; i++)
- {
- std::vector<int> lineBoard;
- for(int j = 0; j < BOARD_GRAD_SIZE; j++)
- lineBoard.push_back(0);
- gameMapVec.push_back(lineBoard);
- }
-
- // 如果是AI模式, 需要初始化评分数组
- if(gameType == AI)
- {
- scoreMapVec.clear() ;
- for(int i = 0; i < BOARD_GRAD_SIZE; i++)
- {
- std::vector<int> lineScores;
- for(int j = 0; j < BOARD_GRAD_SIZE; j++)
- lineScores.push_back(0);
- scoreMapVec.push_back(lineScores);
- }
- }
-
- // 轮到黑方下棋为true,白方为false
- playerFlag = true ;
- }
- #include "mainwindow.h"
- #include "ui_mainwindow.h"
-
- MainWindow::MainWindow(QWidget *parent)
- : QMainWindow(parent)
- , ui(new Ui::MainWindow)
- {
- ui->setupUi(this);
- setFixedSize(MARGIN * 2 + BLOCK_SIZE * BOARD_GRAD_SIZE, MARGIN * 2 + BLOCK_SIZE * BOARD_GRAD_SIZE);
- initGame();
- }
-
- MainWindow::~MainWindow()
- {
- delete ui;
- }
-
- void MainWindow::paintEvent(QPaintEvent *event)
- {
- QPainter painter(this);
- //绘制棋盘
- painter.setRenderHint (QPainter::Antialiasing, true); // 抗锯齿
- for (int i = 0; i < BOARD_GRAD_SIZE + 1; i++)
- {
- // 从左到右,第(i+1)条竖线
- painter.drawLine(MARGIN + BLOCK_SIZE * i, MARGIN, MARGIN + BLOCK_SIZE * i, size().height() - MARGIN);
- // 从上到下,第(i+1)条横线
- painter.drawLine(MARGIN, MARGIN + BLOCK_SIZE * i, size().width() - MARGIN, MARGIN + BLOCK_SIZE * i);
- }
- }
-
- void MainWindow::initGame()
- {
- game = new GameModel;
- initAIGame();
- }
-
- void MainWindow::initAIGame()
- {
- game_type = AI;
- game->gameStatus = PLAYING;
- // 在数据模型中进行初始化功能
- game->startGame(game_type);
- update();
- }
添加头文件 #include <QMouseEvent>、#include <math.h>
重写鼠标移动事件方法
打开自动检测鼠标移动的按钮
给鼠标移动事件添加逻辑
1、准备需要的变量
2、检测是离哪个点最近
- void MainWindow::mouseMoveEvent(QMouseEvent *event)
- {
- // 通过鼠标的位置确定落子的标记
- int x = event->x();
- int y = event->y();
-
- // 棋盘边缘不能落子
- if(x >= MARGIN + BLOCK_SIZE / 2 && x < size().width() - MARGIN - BLOCK_SIZE / 2 &&
- y >= MARGIN + BLOCK_SIZE / 2 && y < size().height() - MARGIN - BLOCK_SIZE / 2)
- {
- // 获取最近的左上角的点
- // add by rock
- int col = (x - MARGIN) / BLOCK_SIZE;
- int row = (y - MARGIN) / BLOCK_SIZE;
-
- int leftTopPosX = MARGIN + BLOCK_SIZE * col;
- int leftTopPosY = MARGIN + BLOCK_SIZE * row;
-
- //根据距离算出合适的点击位置,一 共四个点,根据半径距离选最近的
- clickPosRow = -1; //初始化最终的值
- clickPosCol = -1;
- int len = 0; // 计算完后取整就可以了
- selectPos = false;
-
- //确定一个误差在范围内的点,且只可能确定一个出来
- len = sqrt((x - leftTopPosX) * (x - leftTopPosX) + (y - leftTopPosY) * (y - leftTopPosY));
- if(len < POS_OFFSET)
- {
- clickPosRow = row;
- clickPosCol = col;
- if(game->gameMapVec[clickPosRow][clickPosCol] == 0) {
- selectPos = true;
- }
- }
-
- len = sqrt((x - leftTopPosX - BLOCK_SIZE) * (x - leftTopPosX - BLOCK_SIZE) + (y - leftTopPosY - BLOCK_SIZE) * (y - leftTopPosY - BLOCK_SIZE));
- if(len < POS_OFFSET)
- {
- clickPosRow = row;
- clickPosCol = col + 1;
- if(game->gameMapVec[clickPosRow][clickPosCol] == 0) {
- selectPos = true;
- }
- }
-
- 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->gameMapVec[clickPosRow][clickPosCol] == 0) {
- selectPos = true;
- }
- }
-
- len = sqrt((x - leftTopPosX - BLOCK_SIZE) * (x - leftTopPosX - BLOCK_SIZE) + (y - leftTopPosY) * (y - leftTopPosY));
- if(len < POS_OFFSET)
- {
- clickPosRow = row + 1;
- clickPosCol = col + 1;
- if(game->gameMapVec[clickPosRow][clickPosCol] == 0) {
- selectPos = true;
- }
- }
- }
-
- // 存了坐标后要重绘
- update();
- }
3、绘制落点
- void MainWindow::paintEvent(QPaintEvent *event)
- {
- QPainter painter(this);
- //绘制棋盘
- painter.setRenderHint (QPainter::Antialiasing, true); // 抗锯齿
- for(int i = 0; i < BOARD_GRAD_SIZE + 1; i++)
- {
- // 从左到右,第(i+1)条竖线
- painter.drawLine(MARGIN + BLOCK_SIZE * i, MARGIN, MARGIN + BLOCK_SIZE * i, size().height() - MARGIN);
- // 从上到下,第(i+1)条横线
- painter.drawLine(MARGIN, MARGIN + BLOCK_SIZE * i, size().width() - MARGIN, MARGIN + BLOCK_SIZE * i);
- }
- // 绘制选中点
- QBrush brush;
- brush.setStyle(Qt::SolidPattern);
- // 绘制落子标记(防止鼠标出框越界)
- if(clickPosRow > 0 && clickPosRow < BOARD_GRAD_SIZE &&
- clickPosCol > 0 && clickPosCol < BOARD_GRAD_SIZE &&
- game->gameMapVec[clickPosRow][clickPosCol] == 0)
- {
- if(game->playerFlag) {
- brush.setColor(Qt::black);
- }
- else {
- brush.setColor(Qt::white);
- }
- painter.setBrush(brush);
- painter.drawRect(MARGIN + BLOCK_SIZE * clickPosCol - MARK_SIZE / 2, MARGIN + BLOCK_SIZE * clickPosRow - MARK_SIZE, 8, 8);
- }
-
- }
1、重写鼠标释放事件
- void MainWindow::mouseReleaseEvent(QMouseEvent *event)
- {
- if(selectPos == false) {
- return;
- } else {
- selectPos = false;
- }
-
- chessOneByPerson();
-
- if(game_type == AI) { // 人机模式
- // AI下棋
- }
- }
2、写下棋的方法
- void MainWindow::chessOneByPerson()
- {
- // 根据当前存储的坐标下子
- // 只有有效点击才下子,并且该处没有子
- if(clickPosRow != -1 && clickPosCol != -1 && game->gameMapVec[clickPosRow][clickPosRow] == 0)
- {
- game->actionByPerson(clickPosRow, clickPosCol);
-
- // 播放落子音效,待实现
-
- //重绘
- update() ;
- }
- }
- void GameModel::actionByPerson(int row, int col)
- {
- updateGameMap(row, col);
- }
-
- void GameModel::updateGameMap(int row, int col)
- {
- if(playerFlag)
- gameMapVec[row][col] = 1;
- else
- gameMapVec[row][col] = -1;
- // 换手
- playerFlag = !playerFlag;
- }
3、绘制棋子
- void MainWindow::paintEvent(QPaintEvent *event)
- {
- QPainter painter(this);
- //绘制棋盘
- painter.setRenderHint (QPainter::Antialiasing, true); // 抗锯齿
- for(int i = 0; i < BOARD_GRAD_SIZE + 1; i++)
- {
- // 从左到右,第(i+1)条竖线
- painter.drawLine(MARGIN + BLOCK_SIZE * i, MARGIN, MARGIN + BLOCK_SIZE * i, size().height() - MARGIN);
- // 从上到下,第(i+1)条横线
- painter.drawLine(MARGIN, MARGIN + BLOCK_SIZE * i, size().width() - MARGIN, MARGIN + BLOCK_SIZE * i);
- }
- // 绘制选中点
- QBrush brush;
- brush.setStyle(Qt::SolidPattern);
- // 绘制落子标记(防止鼠标出框越界)
- if(clickPosRow > 0 && clickPosRow < BOARD_GRAD_SIZE &&
- clickPosCol > 0 && clickPosCol < BOARD_GRAD_SIZE &&
- game->gameMapVec[clickPosRow][clickPosCol] == 0)
- {
- if(game->playerFlag) {
- brush.setColor(Qt::black);
- }
- else {
- brush.setColor(Qt::white);
- }
- painter.setBrush(brush);
- painter.drawRect(MARGIN + BLOCK_SIZE * clickPosCol - MARK_SIZE / 2, MARGIN + BLOCK_SIZE * clickPosRow - MARK_SIZE, 8, 8);
- }
-
- //绘制棋子
- for(int i = 0; i < BOARD_GRAD_SIZE; i++)
- for(int j = 0; j < BOARD_GRAD_SIZE; j++)
- {
- if(game->gameMapVec[i][j] == 1)
- {
- // brush.setColor(Qt::white);
- brush.setColor(Qt::black);
- painter.setBrush(brush);
- painter.drawEllipse(MARGIN + BLOCK_SIZE * j - CHESS_RADTUS/2, MARGIN + BLOCK_SIZE * i - CHESS_RADTUS/2, CHESS_RADTUS, CHESS_RADTUS);
- }
- else if(game->gameMapVec[i][j] == -1)
- {
- //brush.setColor(Qt::black);
- brush.setColor(Qt::white);
- painter.setBrush(brush);
- painter.drawEllipse(MARGIN + BLOCK_SIZE * j - CHESS_RADTUS/2, MARGIN + BLOCK_SIZE * i - CHESS_RADTUS/2, CHESS_RADTUS, CHESS_RADTUS);
- }
- }
- }
- bool GameModel::isWin(int row, int col)
- {
- // 横竖斜四种大情况,每种情况都根据当前落子往后遍历5个棋子,有一种符合就算赢
- // 水平方向
- for(int i = 0; i < 5; i++)
- {
- // 往左5个,往右匹配4个子,20种情况
- if(col - i > 0 && col - i + 4 < BOARD_GRAD_SIZE &&
- gameMapVec[row][col - i] == gameMapVec[row][col - i + 1] &&
- gameMapVec[row][col - i] == gameMapVec[row][col - i + 2] &&
- gameMapVec[row][col - i] == gameMapVec[row][col - i + 3] &&
- gameMapVec[row][col - i] == gameMapVec[row][col - i + 4]) {
- return true;
- }
- }
-
- // 竖直方向(上下延伸4个)
- for(int i = 0; i < 5; i++)
- {
- if(row - i > 0 && row - i + 4 < BOARD_GRAD_SIZE &&
- gameMapVec[row - i][col] == gameMapVec[row - i + 1][col] &&
- gameMapVec[row - i][col] == gameMapVec[row - i + 2][col] &&
- gameMapVec[row - i][col] == gameMapVec[row - i + 3][col] &&
- gameMapVec[row - i][col] == gameMapVec[row - i + 4][col]) {
- return true;
- }
- }
-
- // "/"方向(上下延伸4个)
- for(int i = 0; i < 5; i++)
- {
- if(row + i < BOARD_GRAD_SIZE && row + i - 4 > 0 &&
- col - i > 0 && col - i + 4 < BOARD_GRAD_SIZE &&
- gameMapVec[row + i][col - i] == gameMapVec[row + i - 1][col - i + 1] &&
- gameMapVec[row + i][col - i] == gameMapVec[row + i - 2][col - i + 2] &&
- gameMapVec[row + i][col - i] == gameMapVec[row + i - 3][col - i + 3] &&
- gameMapVec[row + i][col - i] == gameMapVec[row + i - 4][col - i + 4]) {
- return true;
- }
- }
-
- // "\"方向(上下延伸4个)
- for(int i = 0; i < 5; i++)
- {
- if(row - i > 0 && row + i + 4 < BOARD_GRAD_SIZE &&
- col - i > 0 && col - i + 4 < BOARD_GRAD_SIZE &&
- gameMapVec[row - i][col - i] == gameMapVec[row - i + 1][col - i + 1] &&
- gameMapVec[row - i][col - i] == gameMapVec[row - i + 2][col - i + 2] &&
- gameMapVec[row - i][col - i] == gameMapVec[row - i + 3][col - i + 3] &&
- gameMapVec[row - i][col - i] == gameMapVec[row - i + 4][col - i + 4]) {
- return true;
- }
- }
-
- return false;
- }
在重绘函数里面判断输赢
- void MainWindow::paintEvent(QPaintEvent *event)
- {
- QPainter painter(this);
- //绘制棋盘
- painter.setRenderHint (QPainter::Antialiasing, true); // 抗锯齿
- for(int i = 0; i < BOARD_GRAD_SIZE + 1; i++)
- {
- // 从左到右,第(i+1)条竖线
- painter.drawLine(MARGIN + BLOCK_SIZE * i, MARGIN, MARGIN + BLOCK_SIZE * i, size().height() - MARGIN);
- // 从上到下,第(i+1)条横线
- painter.drawLine(MARGIN, MARGIN + BLOCK_SIZE * i, size().width() - MARGIN, MARGIN + BLOCK_SIZE * i);
- }
- // 绘制选中点
- QBrush brush;
- brush.setStyle(Qt::SolidPattern);
- // 绘制落子标记(防止鼠标出框越界)
- if(clickPosRow > 0 && clickPosRow < BOARD_GRAD_SIZE &&
- clickPosCol > 0 && clickPosCol < BOARD_GRAD_SIZE &&
- game->gameMapVec[clickPosRow][clickPosCol] == 0)
- {
- if(game->playerFlag) {
- brush.setColor(Qt::black);
- }
- else {
- brush.setColor(Qt::white);
- }
- painter.setBrush(brush);
- painter.drawRect(MARGIN + BLOCK_SIZE * clickPosCol - MARK_SIZE / 2, MARGIN + BLOCK_SIZE * clickPosRow - MARK_SIZE, 8, 8);
- }
-
- //绘制棋子
- for(int i = 0; i < BOARD_GRAD_SIZE; i++)
- for(int j = 0; j < BOARD_GRAD_SIZE; j++)
- {
- if(game->gameMapVec[i][j] == 1)
- {
- // brush.setColor(Qt::white);
- brush.setColor(Qt::black);
- painter.setBrush(brush);
- painter.drawEllipse(MARGIN + BLOCK_SIZE * j - CHESS_RADTUS/2, MARGIN + BLOCK_SIZE * i - CHESS_RADTUS/2, CHESS_RADTUS, CHESS_RADTUS);
- }
- else if(game->gameMapVec[i][j] == -1)
- {
- //brush.setColor(Qt::black);
- brush.setColor(Qt::white);
- painter.setBrush(brush);
- painter.drawEllipse(MARGIN + BLOCK_SIZE * j - CHESS_RADTUS/2, MARGIN + BLOCK_SIZE * i - CHESS_RADTUS/2, CHESS_RADTUS, CHESS_RADTUS);
- }
- }
-
- // 判断输赢
- if(clickPosRow > 0 && clickPosRow < BOARD_GRAD_SIZE &&
- clickPosCol > 0 && clickPosCol < BOARD_GRAD_SIZE &&
- (game->gameMapVec[clickPosRow][clickPosCol] == 1 ||
- game->gameMapVec[clickPosRow][clickPosCol] == -1))
- {
- if(game->isWin(clickPosRow, clickPosCol) && game->gameStatus == PLAYING)
- {
- game->gameStatus = WIN;
- QString str;
- if(game->gameMapVec[clickPosRow][clickPosCol] == 1) {
- str = "黑棋";
- }
- if(game->gameMapVec[clickPosRow][clickPosCol] == -1) {
- str = "白棋";
- }
- QMessageBox::StandardButton btnValue = QMessageBox::information(this, "五子棋嬴家", str + "胜利");
-
- // 重置游戏状态,否则容易死循环
- if(btnValue == QMessageBox::Ok) {
- game->startGame(game_type);
- game->gameStatus = PLAYING;
- }
- }
- }
- }
所有的空白点往8个方向寻找对方子弟的个数,如果子弟个数比较多,优先堵住
这个 Ai 是以防守为主的,如果对方没有对白棋构成威胁的旗形,白棋才会主动出击
- // 最关键的计算评分
- void GameModel::calculateScore()
- {
- //統計玩家或者電腦連成的子
- int personNum = 0; //玩家連成子的個數
- int botNum = 0; //AI連成子的個數
- int emptyNum = 0; //各方向空白位的個數
-
- //清空評分數組
- scoreMapVec.clear();
- for(int i=0;i<BOARD_GRAD_SIZE;i++){
- std::vector<int> lineScores;
- for(int j=0;j<BOARD_GRAD_SIZE;j++){
- lineScores.push_back(0);
- }
- scoreMapVec.push_back(lineScores);
- }
- //計分
- /*計分個人理解:
- * 遍歷每一個格子,判斷哪些是空白的點(即為0的點),以該點為中心,判斷周圍的八個點向外延伸的四格裡,
- * 有多少個是黑子、白子、空白,以此作為依據來評分。下方算法是以守為主,所以守的分數>攻的分數
- */
- for(int row=0;row<BOARD_GRAD_SIZE;row++){
- for(int col=0;col<BOARD_GRAD_SIZE;col++){
- //空白點才算
- if(row>0 && col>0 && gameMapVec[row][col]==0){
- //遍歷周圍8個方向
- for(int y=-1;y<=1;y++){
- for(int x=-1;x<=1;x++){
- //重置
- personNum = 0;
- botNum = 0;
- emptyNum = 0;
- //原坐標不算
- if(!(y==0 && x==0)){
- //每個方向延伸4個子
-
- //對玩家黑子評分(正反兩個方向)
- for(int i=1;i<=4;i++){
- if(row+i*y>0 && row+i*y<BOARD_GRAD_SIZE &&
- col+i*x>0 && col+i*x<BOARD_GRAD_SIZE &&
- gameMapVec[row+i*y][col+i*x]==1){ //真人玩家的子
- personNum++;
- }
- else if(row+i*y>0 && row+i*y<BOARD_GRAD_SIZE &&
- col+i*x>0 && col+i*x<BOARD_GRAD_SIZE &&
- gameMapVec[row+i*y][col+i*x]==0){ //空白位
- emptyNum++;
- break;
- }
- else{ //出邊界,或有白子
- break;
- }
- }
- for(int i=1;i<=4;i++){
- if(row-i*y>0 && row-i*y<BOARD_GRAD_SIZE &&
- col-i*x>0 && col-i*x<BOARD_GRAD_SIZE &&
- gameMapVec[row-i*y][col-i*x]==1){ //真人玩家的子
- personNum++;
- }
- else if(row-i*y>0 && row-i*y<BOARD_GRAD_SIZE &&
- col-i*x>0 && col-i*x<BOARD_GRAD_SIZE &&
- gameMapVec[row-i*y][col-i*x]==0){ //空白位
- emptyNum++;
- break;
- }
- else{ //出邊界,或有白子
- break;
- }
- }
- if(personNum == 1){ //殺2
- scoreMapVec[row][col]+=10;
- }else if(personNum == 2){ //殺3
- if(emptyNum == 1)
- scoreMapVec[row][col]+=30;
- else if(emptyNum == 2)
- scoreMapVec[row][col]+=40;
- }else if(personNum == 3){ //殺4
- //量變空位不一樣,優先級不一樣
- if(emptyNum == 1)
- scoreMapVec[row][col]+=60;
- else if(emptyNum == 2)
- scoreMapVec[row][col]+=110;
- }else if(personNum == 4){ //殺5
- scoreMapVec[row][col]+=10100;
- }
-
- //進行一次清空
- emptyNum = 0;
-
- //對AI白子評分
- for(int i=1;i<=4;i++){
- if(row+i*y>0 && row+i*y<BOARD_GRAD_SIZE &&
- col+i*x>0 && col+i*x<BOARD_GRAD_SIZE &&
- gameMapVec[row+i*y][col+i*x]==-1){ //AI的子
- botNum++;
- }else if(row+i*y>0 && row+i*y<BOARD_GRAD_SIZE &&
- col+i*x>0 && col+i*x<BOARD_GRAD_SIZE &&
- gameMapVec[row+i*y][col+i*x]==0){ //空白位
- emptyNum++;
- break;
- }else{ //出邊界
- break;
- }
- }
- for(int i=1;i<=4;i++){
- if(row-i*y>0 && row-i*y<BOARD_GRAD_SIZE &&
- col-i*x>0 && col-i*x<BOARD_GRAD_SIZE &&
- gameMapVec[row-i*y][col-i*x]==-1){ //AI的子
- botNum++;
- }else if(row-i*y>0 && row-i*y<BOARD_GRAD_SIZE &&
- col-i*x>0 && col-i*x<BOARD_GRAD_SIZE &&
- gameMapVec[row-i*y][col-i*x]==0){ //空白位
- emptyNum++;
- break;
- }else{ //出邊界
- break;
- }
- }
- if(botNum == 0){
- scoreMapVec[row][col]+=5; //活1
- }else if(botNum == 1){
- scoreMapVec[row][col]+=10; //活2
- }else if(botNum == 2){ //活3
- if(emptyNum == 1)
- scoreMapVec[row][col]+=25;
- else if(emptyNum == 2)
- scoreMapVec[row][col]+=50;
- }else if(botNum == 3){ //活4
- if(emptyNum == 1)
- scoreMapVec[row][col]+=55;
- else if(emptyNum == 2)
- scoreMapVec[row][col]+=100;
- }else if(botNum >= 4){ //活5
- scoreMapVec[row][col]+=20000;
- }
-
-
- }
- }
- }
- }
- }
- }
- }
每次 AI 思考的时间为 AI_THINK_TIME
写槽函数
加入头文件 #include <time.h> #include <stdlib.h>,写 AI 下棋方法
- void GameModel::actionByAI(int &clickRow, int &clickCol)
- {
- //計算評分
- calculateScore();
-
- //從評分中找出最大分數的位置
- int maxScore = 0;
- std::vector<std::pair<int,int>> maxPoints;
- for(int row = 1;row<BOARD_GRAD_SIZE;row++){
- for(int col = 1;col<BOARD_GRAD_SIZE;col++){
- //前提是這個坐標是空的
- if(gameMapVec[row][col] == 0){
- if(scoreMapVec[row][col]>maxScore){ //找最大數和坐標
- maxPoints.clear();
- maxScore = scoreMapVec[row][col];
- maxPoints.push_back(std::make_pair(row,col));
- }else if(scoreMapVec[row][col] == maxScore){ //如果有多個最大值就將他們存儲起來,在後面的代碼隨機抽1個
- maxPoints.push_back(std::make_pair(row,col));
- }
- }
- }
- }
- //隨機落子,如果有多個點的話
- srand((unsigned)time(0));
- int index = rand()%maxPoints.size();
- std::pair<int,int> pointPair = maxPoints.at(index);
- clickRow = pointPair.first;
- clickCol = pointPair.second;
- updateGameMap(clickRow,clickCol);
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。