• 《QT实用小工具·六十九》基于QT开发的五子棋AI游戏


    1、概述
    源码放在文章末尾

    该项目实现了五子棋对战AI,可以享受和AI下棋的快乐,项目实现思路如下:
    博弈树

    Alpha-Beta剪枝(性能提高较大)

    ●启发式搜索(性能提高较大)

    ●落子区域限制(性能提高较大)

    ●Zobrist哈希(性能小幅提升)

    ●Qt多线程计算避免界面卡死

    ●小概率走法剔除

    仅进行Alpha-Beta剪枝+落子区域限制,思考两层,计算量在3k-9k,2s内计算完毕;思考四层,计算量在9k-20w,2s~20min内计算完毕.

    +启发式搜索,思考两层,思考两层,计算量在900-2k,1s内计算完毕;思考四层,计算量在3k-3w,2s~20s内计算完毕.

    +小概率走法剔除,思考两层,思考两层,计算量在24-60,1s内计算完毕;思考5层,计算量在2k-3k,1s内计算完毕;思考7层,计算量在8k-3w,2min~10min内计算完毕

    项目界面图如下所示:
    在这里插入图片描述
    项目部分代码如下所示:

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #define QOUT qDebug()
    
    enum patternID{
      LongLink=0,
      Active4,
      Sleep4,
      Active3,
      Sleep3,
      Active2,
      Sleep2,
      Dead4,
      Dead3,
      Dead2
    };
    
    struct step{
      int x;
      int y;
      bool nowWhite;
      int score;
      step(int xx=0,int yy=0,bool nw=true){
        x=xx;
        y=yy;
        nowWhite=nw;
      }
    };
    
    
    struct pattern{
      std::vector<QString> whitePattern;
      std::vector<QString> blackPattern;
      int id;
      int whiteScore;
      int blackScore;
      void clear(){
        whitePattern.clear();
        blackPattern.clear();
      }
    };
    
    namespace Ui {
      class MainWindow;
    }
    
    class MainWindow;
    class AI:public QObject{
      Q_OBJECT
    public:
      AI();
      AI(MainWindow *p):parentWindow(p){}
      int count;
    private:
      MainWindow* parentWindow;
    
    public slots:
      void getAINextStep();
     public:
    
      int getChessScore(int chess[15][15],int leftEdge=0,int rightEdge=14,int upEdge=0,int downEdge=14);
      int getLineScore(QString,int whitePatternNum[10],int blackPatternNum[15]);
      std::vector<step> getPossibleSteps(int chess[15][15],bool white,int leftEdge=0,int rightEdge=14,int upEdge=0,int downEdge=14);
      int alpha_beta(int chess[15][15], int depth, int alpha, int beta);
      bool calculateScore(std::vector<step>& possibleSteps,int chess[15][15]);
      void deleteUselessStep(std::vector<step>& possibleSteps,int chess[15][15]);
      bool reserveKillStep(std::vector<step>& possibleSteps,int chess[15][15]);
      signals:
      void stepReady();
    };
    
    
    class MainWindow : public QMainWindow
    {
      Q_OBJECT
    friend class AI;
    public:
      explicit MainWindow(QWidget *parent = 0);
      ~MainWindow();
      void paintEvent(QPaintEvent *e);
      void mousePressEvent(QMouseEvent *e);
      void keyPressEvent(QKeyEvent *e);
    public slots:
      void handleAIStep();
    signals:
      void AIShouldMove();
    private:
      QThread AIThread;
      bool gameOver;
      int searchDepth;//搜索深度,应当是偶数
      int killStepSearchDepth;
      int stepAlreadyMade;//已经走的步数
      Ui::MainWindow *ui;
      const int gap=20;
      constexpr static int boxNum=14;
      const int boxWidth=gap*boxNum;
      const int startX=30;
      const int startY=30;
      bool nowWhite;//记录当前是否是白子 白色=1 黑色=2
      int gomoku[boxNum+1][boxNum+1];
      int gomokuForPaint[boxNum+1][boxNum+1];
      bool judge(int x,int y,bool nowWhite);
      bool judge(int chess[15][15],int x, int y, bool nowWhite);
      int steps;//用于设定搜索范围的步数
      int AINextX;
      int AINextY;
      bool AIIsThinking;
      std::vector<pattern> patterns;//储存算分的模式
      std::vector<pattern> lightPatterns;//排序走法用的模式
      int zobristHash;
    
      std::unordered_map<int,int> scoreCache;
      bool debug;
    
      int basicScore[15][15]={
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
        { 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0 },
        { 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0 },
        { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, 0 },
        { 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 4, 3, 2, 1, 0 },
        { 0, 1, 2, 3, 4, 5, 6, 6, 6, 5, 4, 3, 2, 1, 0 },
        { 0, 1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1, 0 },
        { 0, 1, 2, 3, 4, 5, 6, 6, 6, 5, 4, 3, 2, 1, 0 },
        { 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 4, 3, 2, 1, 0 },
        { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, 0 },
        { 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0 },
        { 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0 },
        { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
      int zobristWhite[15][15];
      int zobristBlack[15][15];
      int XStack[250];//从1开始算
      int YStack[250];//从1开始算
      void initPattern();//初始化算分模式
    public slots:
      void restartGame();
      void regret();
    
    };
    
    #endif // MAINWINDOW_H
    
    

    源码下载

  • 相关阅读:
    记一次使用LruCache并探究
    【云原生 • Kubernetes】一文掌握 k8s 包管理工具 Helm
    rsa加密解密java和C#互通
    [附源码]Python计算机毕业设计二手图书回收销售网站
    新入手Mac配置前端环境教程
    【毕业设计】基于STM32的天气预报盒子 - 嵌入式 单片机 物联网
    力扣每日一题---2594. 修车的最少时间
    Docker(1)
    (附源码)计算机毕业设计SSM基于框架的旅游订票系统
    CANoe 简介
  • 原文地址:https://blog.csdn.net/cs1395293598/article/details/139334008