├── .DS_Store ├── RicardoGoBang ├── game.cpp ├── logo.rc ├── .DS_Store ├── logo.icns ├── game.h ├── main.cpp ├── dialogabout.h ├── dialoggameover.cpp ├── chess.ui ├── dialoggameover.h ├── chessai.h ├── mainwindow.h ├── dialogchoosepiece.h ├── pvpwindow.h ├── possiblepositionmanager.h ├── pvmwindow.h ├── acsearcher.h ├── dialogabout.cpp ├── dialoggameover.ui ├── chess.h ├── chessengine.h ├── mainwindow.cpp ├── RicardoGoBang.pro ├── dialogchoosepiece.cpp ├── possiblepositionmanager.cpp ├── pvpwindow.cpp ├── dialogchoosepiece.ui ├── pvmwindow.cpp ├── acsearcher.cpp ├── mainwindow.ui ├── dialogabout.ui ├── pvmwindow.ui ├── pvpwindow.ui ├── chessai.cpp ├── chessengine.cpp ├── chess.cpp └── RicardoGoBang.pro.user ├── ScreenShot ├── .DS_Store ├── ScreenShot1.png ├── ScreenShot2.png ├── ScreenShot3.png ├── ScreenShot4.png ├── ScreenShot5.png ├── ScreenShot6.png └── ScreenShot7.png └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maplefan/RicardoGoBang/HEAD/.DS_Store -------------------------------------------------------------------------------- /RicardoGoBang/game.cpp: -------------------------------------------------------------------------------- 1 | #include "game.h" 2 | 3 | bool gameState = false; 4 | -------------------------------------------------------------------------------- /RicardoGoBang/logo.rc: -------------------------------------------------------------------------------- 1 | IDI_ICON1 ICON DISCARDABLE "logo.icns" 2 | -------------------------------------------------------------------------------- /ScreenShot/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maplefan/RicardoGoBang/HEAD/ScreenShot/.DS_Store -------------------------------------------------------------------------------- /RicardoGoBang/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maplefan/RicardoGoBang/HEAD/RicardoGoBang/.DS_Store -------------------------------------------------------------------------------- /RicardoGoBang/logo.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maplefan/RicardoGoBang/HEAD/RicardoGoBang/logo.icns -------------------------------------------------------------------------------- /ScreenShot/ScreenShot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maplefan/RicardoGoBang/HEAD/ScreenShot/ScreenShot1.png -------------------------------------------------------------------------------- /ScreenShot/ScreenShot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maplefan/RicardoGoBang/HEAD/ScreenShot/ScreenShot2.png -------------------------------------------------------------------------------- /ScreenShot/ScreenShot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maplefan/RicardoGoBang/HEAD/ScreenShot/ScreenShot3.png -------------------------------------------------------------------------------- /ScreenShot/ScreenShot4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maplefan/RicardoGoBang/HEAD/ScreenShot/ScreenShot4.png -------------------------------------------------------------------------------- /ScreenShot/ScreenShot5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maplefan/RicardoGoBang/HEAD/ScreenShot/ScreenShot5.png -------------------------------------------------------------------------------- /ScreenShot/ScreenShot6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maplefan/RicardoGoBang/HEAD/ScreenShot/ScreenShot6.png -------------------------------------------------------------------------------- /ScreenShot/ScreenShot7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maplefan/RicardoGoBang/HEAD/ScreenShot/ScreenShot7.png -------------------------------------------------------------------------------- /RicardoGoBang/game.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef GAME_H 3 | #define GAME_H 4 | #include 5 | 6 | 7 | class Game 8 | { 9 | public: 10 | 11 | private: 12 | 13 | 14 | }; 15 | 16 | #endif // GAME_H 17 | -------------------------------------------------------------------------------- /RicardoGoBang/main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | QApplication a(argc, argv); 9 | MainWindow w; 10 | w.setWindowTitle("RicardoGoBang"); 11 | 12 | 13 | w.show();//显示窗体 14 | return a.exec(); 15 | } 16 | -------------------------------------------------------------------------------- /RicardoGoBang/dialogabout.h: -------------------------------------------------------------------------------- 1 | #ifndef DIALOGABOUT_H 2 | #define DIALOGABOUT_H 3 | 4 | #include 5 | 6 | namespace Ui { 7 | class DialogAbout; 8 | } 9 | 10 | class DialogAbout : public QDialog 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit DialogAbout(QWidget *parent = 0); 16 | ~DialogAbout(); 17 | 18 | private: 19 | Ui::DialogAbout *ui; 20 | }; 21 | 22 | #endif // DIALOGABOUT_H 23 | -------------------------------------------------------------------------------- /RicardoGoBang/dialoggameover.cpp: -------------------------------------------------------------------------------- 1 | #include "dialoggameover.h" 2 | #include "ui_dialoggameover.h" 3 | 4 | DialogGameOver::DialogGameOver(QWidget *parent) : 5 | QDialog(parent), 6 | ui(new Ui::DialogGameOver) 7 | { 8 | ui->setupUi(this); 9 | } 10 | 11 | DialogGameOver::~DialogGameOver() 12 | { 13 | delete ui; 14 | } 15 | 16 | void DialogGameOver::setLabelText(QString str) 17 | { 18 | this->ui->label_gameover->setText(str); 19 | } 20 | -------------------------------------------------------------------------------- /RicardoGoBang/chess.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Chess 4 | 5 | 6 | 7 | 0 8 | 0 9 | 600 10 | 600 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /RicardoGoBang/dialoggameover.h: -------------------------------------------------------------------------------- 1 | #ifndef DIALOGGAMEOVER_H 2 | #define DIALOGGAMEOVER_H 3 | 4 | #include 5 | 6 | namespace Ui { 7 | class DialogGameOver; 8 | } 9 | 10 | class DialogGameOver : public QDialog 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit DialogGameOver(QWidget *parent = 0); 16 | ~DialogGameOver(); 17 | void setLabelText(QString str); 18 | 19 | private: 20 | Ui::DialogGameOver *ui; 21 | }; 22 | 23 | #endif // DIALOGGAMEOVER_H 24 | -------------------------------------------------------------------------------- /RicardoGoBang/chessai.h: -------------------------------------------------------------------------------- 1 | #ifndef CHESS_H_INCLUDED 2 | #define CHESS_H_INCLUDED 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define BOARD_WIDTH 15 12 | 13 | extern int isover; 14 | extern int myturn; 15 | extern int prex,prey; 16 | extern int backnum,whitenum; 17 | 18 | class ChessAI 19 | { 20 | 21 | public: 22 | void chess_isover(int x,int y,int turn); 23 | void chess_ai_killcount(int &x,int &y,bool &winFlag,int depth); 24 | }; 25 | 26 | #endif // CHESS_H_INCLUDED 27 | -------------------------------------------------------------------------------- /RicardoGoBang/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace Ui { 12 | class MainWindow; 13 | } 14 | 15 | class MainWindow : public QMainWindow 16 | { 17 | Q_OBJECT 18 | private slots: 19 | 20 | void closeEvent( QCloseEvent * event ); 21 | 22 | void on_btnPVP_clicked(); 23 | 24 | void on_btnQuit_clicked(); 25 | 26 | void reshow(); 27 | 28 | void on_btnPVM_clicked(); 29 | 30 | public: 31 | explicit MainWindow(QWidget *parent = 0); 32 | ~MainWindow(); 33 | 34 | private: 35 | Ui::MainWindow *ui; 36 | 37 | signals: 38 | void clicked(); 39 | }; 40 | 41 | #endif // MAINWINDOW_H 42 | -------------------------------------------------------------------------------- /RicardoGoBang/dialogchoosepiece.h: -------------------------------------------------------------------------------- 1 | #ifndef DIALOGCHOOSEPIECE_H 2 | #define DIALOGCHOOSEPIECE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Ui { 9 | class DialogChoosePiece; 10 | } 11 | 12 | class DialogChoosePiece : public QDialog 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit DialogChoosePiece(QWidget *parent = 0); 18 | ~DialogChoosePiece(); 19 | bool getWhoFirst(); 20 | bool getPlayer1Use(); 21 | 22 | private slots: 23 | void on_buttonBox_accepted(); 24 | 25 | signals: 26 | void restart_emit(); 27 | 28 | private: 29 | Ui::DialogChoosePiece *ui; 30 | QButtonGroup *groupButtonWhoFirst; 31 | QButtonGroup *groupButtonPlayer1Piece; 32 | bool whoFirst = false; 33 | bool player1Use = false; 34 | }; 35 | 36 | #endif // DIALOGCHOOSEPIECE_H 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | RicardoGoBang 2 | 这是一个开源的五子棋软件,包括双人对战和人机对战。 3 | 由C++及QT框架完成,无后台通信,AI具有一定的棋力,且能即时显示当前局势下黑子与白子对应的局势得分。 4 | 该软件跨Windows,MacOS,Linux三大主流桌面操作系统。 5 | 6 | 7 | 8 | ![Image text](https://github.com/maplefan/RicardoGoBang/blob/master/ScreenShot/ScreenShot1.png) 9 | 10 | ![Image text](https://github.com/maplefan/RicardoGoBang/blob/master/ScreenShot/ScreenShot2.png) 11 | 12 | ![Image text](https://github.com/maplefan/RicardoGoBang/blob/master/ScreenShot/ScreenShot3.png) 13 | 14 | ![Image text](https://github.com/maplefan/RicardoGoBang/blob/master/ScreenShot/ScreenShot4.png) 15 | 16 | ![Image text](https://github.com/maplefan/RicardoGoBang/blob/master/ScreenShot/ScreenShot5.png) 17 | 18 | ![Image text](https://github.com/maplefan/RicardoGoBang/blob/master/ScreenShot/ScreenShot6.png) 19 | 20 | ![Image text](https://github.com/maplefan/RicardoGoBang/blob/master/ScreenShot/ScreenShot7.png) -------------------------------------------------------------------------------- /RicardoGoBang/pvpwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef PVPWINDOW_H 2 | #define PVPWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace Ui { 11 | class PVPWindow; 12 | } 13 | 14 | class PVPWindow : public QMainWindow 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | explicit PVPWindow(QWidget *parent = 0); 20 | ~PVPWindow(); 21 | 22 | signals: 23 | void sendsignal();//这个函数用户向主界面通知关闭的消息 24 | 25 | private slots: 26 | 27 | void read_emit(int,int,int); 28 | 29 | void restartGame(); 30 | 31 | void on_btn_about_clicked(); 32 | 33 | void on_btn_back_clicked(); 34 | 35 | void on_btn_start_clicked(); 36 | 37 | void on_btn_undo_clicked(); 38 | 39 | void on_btn_giveup_clicked(); 40 | 41 | private: 42 | Ui::PVPWindow *ui; 43 | Chess *chess; 44 | void paintEvent(QPaintEvent *); 45 | }; 46 | 47 | #endif // PVPWINDOW_H 48 | -------------------------------------------------------------------------------- /RicardoGoBang/possiblepositionmanager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ChessEngine.h" 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | struct HistoryItem { 11 | set addedPositions; 12 | ChessEngine::Position removedPosition; 13 | }; 14 | 15 | class PossiblePositionManager 16 | { 17 | public: 18 | PossiblePositionManager(); 19 | ~PossiblePositionManager(); 20 | void AddPossiblePositions(int board[15][15], const ChessEngine::Position& p); 21 | void Rollback(); 22 | set GetCurrentPossiblePositions(); 23 | void RemoveAll(); 24 | void SetEvaluateFunc(int(*evaluateFunc)(int board[15][15], ChessEngine::Position p)); 25 | private: 26 | set currentPossiblePositions; 27 | vector history; 28 | vector > directions; 29 | int (*evaluateFunc)(int board[15][15], ChessEngine::Position p); 30 | }; 31 | -------------------------------------------------------------------------------- /RicardoGoBang/pvmwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef PVMWINDOW_H 2 | #define PVMWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace Ui { 11 | class PVMWindow; 12 | } 13 | 14 | class PVMWindow : public QMainWindow 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | explicit PVMWindow(QWidget *parent = 0); 20 | ~PVMWindow(); 21 | 22 | signals: 23 | void sendsignal();//这个函数用户向主界面通知关闭的消息 24 | 25 | private slots: 26 | 27 | void read_emit(int,int,int); 28 | 29 | void on_btn_back_clicked(); 30 | 31 | void on_btn_about_clicked(); 32 | 33 | void on_btn_start_clicked(); 34 | 35 | void restartGame(); 36 | 37 | void on_btn_undo_clicked(); 38 | 39 | void on_btn_giveup_clicked(); 40 | 41 | private: 42 | Ui::PVMWindow *ui; 43 | Chess *chess; 44 | void paintEvent(QPaintEvent *); 45 | }; 46 | 47 | #endif // PVMWINDOW_H 48 | -------------------------------------------------------------------------------- /RicardoGoBang/acsearcher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | //trie树节点 9 | struct ACNode { 10 | ACNode(int p, char c) 11 | :parent(p), 12 | ch(c), 13 | fail(-1) 14 | { 15 | } 16 | 17 | ACNode() {} 18 | 19 | char ch; 20 | map sons; 21 | int fail; 22 | vector output; 23 | int parent; 24 | }; 25 | 26 | //AC算法类 27 | class ACSearcher 28 | { 29 | public: 30 | ACSearcher(); 31 | ~ACSearcher(); 32 | 33 | void LoadPatern(const vector& paterns); 34 | void BuildGotoTable(); 35 | void BuildFailTable(); 36 | vector ACSearch(const string& text); //返回匹配到的模式的索引 37 | 38 | private: 39 | int maxState; //最大状态数 40 | vector nodes; //trie树 41 | vector paterns; //需要匹配的模式 42 | 43 | void AddState(int parent, char ch); //初始化新状态 44 | }; 45 | -------------------------------------------------------------------------------- /RicardoGoBang/dialogabout.cpp: -------------------------------------------------------------------------------- 1 | #include "dialogabout.h" 2 | #include "ui_dialogabout.h" 3 | 4 | DialogAbout::DialogAbout(QWidget *parent) : 5 | QDialog(parent), 6 | ui(new Ui::DialogAbout) 7 | { 8 | ui->setupUi(this); 9 | QLabel* labelSourceCode =new QLabel(this); 10 | labelSourceCode->setGeometry(111,170,300,21); 11 | labelSourceCode->setOpenExternalLinks(true); 12 | labelSourceCode->setText("源代码"); 13 | labelSourceCode->show(); 14 | 15 | QLabel* labelMaplefan =new QLabel(this); 16 | labelMaplefan->setGeometry(111,240,300,21); 17 | 18 | labelMaplefan->setOpenExternalLinks(true); 19 | labelMaplefan->setText("maplefan.com"); 20 | labelMaplefan->show(); 21 | 22 | 23 | QLabel* labelGithub =new QLabel(this); 24 | labelGithub->setGeometry(111,260,300,21); 25 | labelGithub->setOpenExternalLinks(true); 26 | labelGithub->setText("github.com/maplefan"); 27 | labelGithub->show(); 28 | } 29 | 30 | DialogAbout::~DialogAbout() 31 | { 32 | delete ui; 33 | } 34 | -------------------------------------------------------------------------------- /RicardoGoBang/dialoggameover.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | DialogGameOver 4 | 5 | 6 | 7 | 0 8 | 0 9 | 200 10 | 150 11 | 12 | 13 | 14 | GameOver! 15 | 16 | 17 | 18 | 19 | 0 20 | 0 21 | 200 22 | 150 23 | 24 | 25 | 26 | 27 | Microsoft Sans Serif 28 | 30 29 | 75 30 | true 31 | 32 | 33 | 34 | color:#1FB922 35 | 36 | 37 | 38 | 39 | 40 | Qt::AlignCenter 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /RicardoGoBang/chess.h: -------------------------------------------------------------------------------- 1 | #ifndef CHESS_H 2 | #define CHESS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace Ui { 14 | class Chess; 15 | } 16 | 17 | class Chess : public QWidget 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | explicit Chess(QWidget *parent = 0); 23 | ~Chess(); 24 | 25 | void send_emit(); 26 | int getChessBoard(int x,int y); 27 | void setChessBoard(int x,int y,int value); 28 | bool deleteChessBoardXY(); 29 | void addChessBoardXY(int x,int y); 30 | void clearChessBoard(); 31 | void setStep(int step); 32 | int getStep(); 33 | void setWhoWin(int); 34 | bool isWin(int row, int col); 35 | void gameOver(int ,int); 36 | 37 | signals: 38 | void start_emit(int,int,int); 39 | 40 | private: 41 | Ui::Chess *ui; 42 | int whoWin; 43 | int moveX,moveY; 44 | int preX,preY;//上一步 45 | int step ;//步数 46 | void paintEvent(QPaintEvent *); 47 | void mouseMoveEvent(QMouseEvent *event); 48 | void mouseReleaseEvent(QMouseEvent* event); 49 | std::vectorchessBoardX;//记录步数的X 50 | std::vectorchessBoardY;//记录步数的Y 51 | 52 | }; 53 | 54 | #endif // CHESS_H 55 | -------------------------------------------------------------------------------- /RicardoGoBang/chessengine.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | 9 | 10 | 11 | namespace ChessEngine { 12 | 13 | enum Role { HUMAN = 1, COMPUTOR = 2, EMPTY = 0 }; 14 | 15 | //位置结构体,行是x,列是y 16 | struct Position { 17 | int x; 18 | int y; 19 | int score; 20 | Position() {} 21 | Position(int x, int y) { 22 | this->x = x; 23 | this->y = y; 24 | score = 0; 25 | } 26 | Position(int x, int y, int score) { 27 | this->x = x; 28 | this->y = y; 29 | this->score = score; 30 | } 31 | bool operator <(const Position &pos) const { 32 | if (score != pos.score) { 33 | return score > pos.score; 34 | } 35 | if (x != pos.x) { 36 | return x < pos.x; 37 | } 38 | else { 39 | return y < pos.y; 40 | } 41 | } 42 | }; 43 | 44 | 45 | //在开始之前,一些初始化工作 46 | void beforeStart(); 47 | 48 | //判断是否是某一方赢了 49 | int isSomeOneWin(); 50 | 51 | //悔棋 52 | string takeBack(); 53 | 54 | //清除之前的记录,重新开局 55 | string reset(int role); 56 | 57 | //重新设置层数 58 | void setLevel(int level); 59 | 60 | //取得刚才电脑下得那一步棋子的位置 61 | Position getLastPosition(); 62 | 63 | //人类下棋,返回棋盘,传给界面 64 | string nextStep(int &x, int &y ); 65 | 66 | bool killCount(int level); 67 | 68 | //获得局势评分,role为1时获得玩家局势评分,role为2时获得电脑局势评分 69 | int evaluate(int chessBoard[15][15], int role); 70 | }; 71 | //namespace end 72 | -------------------------------------------------------------------------------- /RicardoGoBang/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "ui_mainwindow.h" 3 | 4 | MainWindow::MainWindow(QWidget *parent) : 5 | QMainWindow(parent), 6 | ui(new Ui::MainWindow) 7 | { 8 | QColor btnColor = QColor(0,161,241); 9 | 10 | QPalette btnPalette = QPalette(btnColor); 11 | QPalette palette(this->palette()); 12 | palette.setColor(QPalette::Background, QColor(124,187,0)); 13 | this->setPalette(palette); 14 | 15 | ui->setupUi(this); 16 | } 17 | 18 | MainWindow::~MainWindow() 19 | { 20 | delete ui; 21 | } 22 | 23 | 24 | 25 | void MainWindow::closeEvent( QCloseEvent *event )//关闭窗口会先处理该事件函数 26 | { 27 | switch( QMessageBox::critical( this, "警告", 28 | "确定要退出RicardoGoBang吗?", 29 | "是", "否", 30 | 0, 1 ) ) 31 | { 32 | case 0: 33 | event->accept(); 34 | break; 35 | case 1: 36 | default: 37 | event->ignore(); 38 | break; 39 | } 40 | } 41 | 42 | 43 | void MainWindow::on_btnPVP_clicked() 44 | { 45 | PVPWindow *pvpwindow = new PVPWindow(this); 46 | pvpwindow->show(); 47 | connect(pvpwindow,SIGNAL(sendsignal()),this,SLOT(reshow())); 48 | this->hide(); 49 | 50 | } 51 | 52 | 53 | 54 | void MainWindow::on_btnQuit_clicked() 55 | { 56 | exit(0); 57 | } 58 | 59 | void MainWindow::reshow(){ 60 | this->show(); 61 | } 62 | 63 | void MainWindow::on_btnPVM_clicked() 64 | { 65 | PVMWindow *pvmwindow = new PVMWindow(this); 66 | pvmwindow->show(); 67 | connect(pvmwindow,SIGNAL(sendsignal()),this,SLOT(reshow())); 68 | this->hide(); 69 | } 70 | -------------------------------------------------------------------------------- /RicardoGoBang/RicardoGoBang.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2019-04-27T01:11:27 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 9 | TARGET = RicardoGoBang 10 | TEMPLATE = app 11 | 12 | # The following define makes your compiler emit warnings if you use 13 | # any feature of Qt which has been marked as deprecated (the exact warnings 14 | # depend on your compiler). Please consult the documentation of the 15 | # deprecated API in order to know how to port your code away from it. 16 | DEFINES += QT_DEPRECATED_WARNINGS 17 | 18 | # You can also make your code fail to compile if you use deprecated APIs. 19 | # In order to do so, uncomment the following line. 20 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 21 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 22 | 23 | 24 | SOURCES += \ 25 | main.cpp \ 26 | mainwindow.cpp \ 27 | pvpwindow.cpp \ 28 | pvmwindow.cpp \ 29 | dialogabout.cpp \ 30 | chess.cpp \ 31 | game.cpp \ 32 | dialogchoosepiece.cpp \ 33 | dialoggameover.cpp \ 34 | possiblepositionmanager.cpp \ 35 | chessai.cpp \ 36 | acsearcher.cpp \ 37 | chessengine.cpp 38 | 39 | HEADERS += \ 40 | mainwindow.h \ 41 | pvpwindow.h \ 42 | pvmwindow.h \ 43 | dialogabout.h \ 44 | chess.h \ 45 | game.h \ 46 | dialogchoosepiece.h \ 47 | dialoggameover.h \ 48 | acsearcher.h \ 49 | possiblepositionmanager.h \ 50 | chessengine.h \ 51 | chessai.h 52 | 53 | FORMS += \ 54 | mainwindow.ui \ 55 | pvpwindow.ui \ 56 | pvmwindow.ui \ 57 | dialogabout.ui \ 58 | chess.ui \ 59 | dialogchoosepiece.ui \ 60 | dialoggameover.ui 61 | 62 | DISTFILES += \ 63 | logo.icns 64 | 65 | ICON = logo.icns 66 | 67 | -------------------------------------------------------------------------------- /RicardoGoBang/dialogchoosepiece.cpp: -------------------------------------------------------------------------------- 1 | #include "dialogchoosepiece.h" 2 | #include "ui_dialogchoosepiece.h" 3 | #include 4 | #include 5 | 6 | extern int countWhoFirst; 7 | extern int countPlayer1Use; 8 | extern bool isFirstStep; 9 | extern int chessBoard[15][15]; 10 | extern int gameMode; 11 | 12 | DialogChoosePiece::DialogChoosePiece(QWidget *parent) : 13 | QDialog(parent), 14 | ui(new Ui::DialogChoosePiece) 15 | { 16 | ui->setupUi(this); 17 | groupButtonPlayer1Piece=new QButtonGroup(this); 18 | groupButtonPlayer1Piece->addButton(ui->radioButtonBlack,0); 19 | groupButtonPlayer1Piece->addButton(ui->radioButtonWhite,1); 20 | ui->radioButtonBlack->setChecked(true); //默认选中apple_radioButton 21 | 22 | groupButtonWhoFirst=new QButtonGroup(this); 23 | 24 | groupButtonWhoFirst->addButton(ui->radioButtonBlackFirst,0); 25 | groupButtonWhoFirst->addButton(ui->radioButtonWhiteFirst,1); 26 | ui->radioButtonBlackFirst->setChecked(true); 27 | 28 | } 29 | 30 | DialogChoosePiece::~DialogChoosePiece() 31 | { 32 | delete ui; 33 | } 34 | 35 | bool DialogChoosePiece::getWhoFirst(){ 36 | return whoFirst; 37 | } 38 | 39 | bool DialogChoosePiece::getPlayer1Use(){ 40 | return player1Use; 41 | } 42 | 43 | void DialogChoosePiece::on_buttonBox_accepted() 44 | { 45 | isFirstStep = true; 46 | int temp = groupButtonWhoFirst->checkedId(); 47 | if(temp == 0){ 48 | whoFirst = false;//黑子 49 | } 50 | else{ 51 | whoFirst = true;//白子 52 | } 53 | temp = groupButtonPlayer1Piece->checkedId(); 54 | if(temp == 0){ 55 | player1Use = false;//黑子 56 | } 57 | else{ 58 | player1Use = true;//白子 59 | } 60 | 61 | if(getWhoFirst() == false && getPlayer1Use() == false){ 62 | countWhoFirst = 0;//黑色先手 63 | countPlayer1Use = 0;//玩家1为黑色 64 | isFirstStep = true; 65 | 66 | } 67 | else if(getWhoFirst() == false && getPlayer1Use() == true){ 68 | countWhoFirst = 0;//黑色先手 69 | countPlayer1Use = 1;//玩家1为白色 70 | isFirstStep = true; 71 | } 72 | else if(getWhoFirst() == true && getPlayer1Use() == false){ 73 | countWhoFirst = 1;//白色先手 74 | countPlayer1Use = 0;//玩家1为黑色 75 | isFirstStep = true; 76 | } 77 | else if(getWhoFirst() == true && getPlayer1Use() == true){ 78 | countWhoFirst = 1;//白色先手 79 | countPlayer1Use = 1;//玩家1为白色 80 | isFirstStep = true; 81 | } 82 | restart_emit(); 83 | } 84 | -------------------------------------------------------------------------------- /RicardoGoBang/possiblepositionmanager.cpp: -------------------------------------------------------------------------------- 1 | #include "PossiblePositionManager.h" 2 | 3 | #include 4 | 5 | 6 | bool IsInBoard(int x, int y) { 7 | if (x >= 0 && x < 15 && y >= 0 && y < 15) 8 | return true; 9 | return false; 10 | } 11 | 12 | PossiblePositionManager::PossiblePositionManager() 13 | { 14 | directions.push_back(pair(1, 1)); 15 | directions.push_back(pair(1, -1)); 16 | directions.push_back(pair(-1, 1)); 17 | directions.push_back(pair(-1, -1)); 18 | directions.push_back(pair(1, 0)); 19 | directions.push_back(pair(0, 1)); 20 | directions.push_back(pair(-1, 0)); 21 | directions.push_back(pair(0, -1)); 22 | } 23 | 24 | 25 | PossiblePositionManager::~PossiblePositionManager() 26 | { 27 | } 28 | 29 | void PossiblePositionManager::AddPossiblePositions(int board[15][15], const ChessEngine::Position& p) { 30 | unsigned int i; 31 | set addedPositions; 32 | 33 | for (i = 0; i < directions.size(); i++) { 34 | //判断范围 35 | if (!IsInBoard(p.x + directions[i].first, p.y + directions[i].second)) 36 | continue; 37 | 38 | if (board[p.x + directions[i].first][p.y + directions[i].second] == ChessEngine::EMPTY) { 39 | ChessEngine::Position pos(p.x + directions[i].first, p.y + directions[i].second); 40 | pair::iterator, bool> insertResult = currentPossiblePositions.insert(pos); 41 | 42 | //如果插入成功 43 | if(insertResult.second) 44 | addedPositions.insert(pos); 45 | } 46 | } 47 | 48 | HistoryItem hi; 49 | hi.addedPositions = addedPositions; 50 | 51 | if (currentPossiblePositions.find(p) != currentPossiblePositions.end()) { 52 | currentPossiblePositions.erase(p); 53 | hi.removedPosition = p; 54 | } 55 | else { 56 | hi.removedPosition.x = -1; 57 | } 58 | 59 | history.push_back(hi); 60 | } 61 | 62 | void PossiblePositionManager::Rollback() { 63 | if (currentPossiblePositions.empty()) 64 | return; 65 | 66 | HistoryItem hi = history[history.size() - 1]; 67 | history.pop_back(); 68 | 69 | set::iterator iter; 70 | 71 | //清除掉前一步加入的点 72 | for (iter = hi.addedPositions.begin(); iter != hi.addedPositions.end(); iter++) { 73 | currentPossiblePositions.erase(*iter); 74 | } 75 | 76 | //加入前一步删除的点 77 | if(hi.removedPosition.x != -1) 78 | currentPossiblePositions.insert(hi.removedPosition); 79 | } 80 | 81 | set PossiblePositionManager::GetCurrentPossiblePositions() { 82 | return currentPossiblePositions; 83 | } 84 | 85 | void PossiblePositionManager::RemoveAll() { 86 | currentPossiblePositions.clear(); 87 | history.clear(); 88 | } 89 | -------------------------------------------------------------------------------- /RicardoGoBang/pvpwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "pvpwindow.h" 2 | #include "ui_pvpwindow.h" 3 | 4 | extern bool gameState; 5 | extern int countWhoFirst; 6 | extern int countPlayer1Use; 7 | extern int gameMode; 8 | 9 | PVPWindow::PVPWindow(QWidget *parent) : 10 | QMainWindow(parent), 11 | ui(new Ui::PVPWindow) 12 | { 13 | ui->setupUi(this); 14 | Chess *chess = new Chess(ui->widget_chess); 15 | this->chess = chess; 16 | gameMode = 1; 17 | connect(chess,SIGNAL(start_emit(int , int ,int)),this,SLOT(read_emit(int,int,int))); 18 | } 19 | 20 | PVPWindow::~PVPWindow() 21 | { 22 | delete ui; 23 | } 24 | 25 | void PVPWindow::on_btn_about_clicked() 26 | { 27 | DialogAbout *dialogAbout = new DialogAbout(this); 28 | dialogAbout->show(); 29 | } 30 | 31 | void PVPWindow::on_btn_back_clicked() 32 | { 33 | gameState = false; 34 | countPlayer1Use = -1; 35 | emit sendsignal(); 36 | this->close(); 37 | } 38 | 39 | void PVPWindow::on_btn_start_clicked() 40 | { 41 | gameState = true; 42 | DialogChoosePiece *dialog = new DialogChoosePiece(this); 43 | dialog->show(); 44 | connect(dialog,SIGNAL(restart_emit()),this,SLOT(restartGame())); 45 | } 46 | 47 | void PVPWindow::on_btn_undo_clicked() 48 | { 49 | gameState = true; 50 | this->chess->deleteChessBoardXY(); 51 | update(); 52 | } 53 | 54 | void PVPWindow::read_emit(int num,int score1 , int score2){ 55 | QString str = QString("STEP: ")+QString::number(num,10)+QString(" 步"); 56 | ui->label_step->setText(str); 57 | } 58 | 59 | void PVPWindow::restartGame(){ 60 | this->chess->clearChessBoard(); 61 | this->chess->setWhoWin(0); 62 | this->ui->label_step->setText(QString("STEP: ")+QString::number(this->chess->getStep(),10)+QString(" 步")); 63 | this->ui->btn_start->setText("重新开始"); 64 | } 65 | 66 | void PVPWindow::on_btn_giveup_clicked() 67 | { 68 | if((this->chess->getStep()+ countWhoFirst )%2 == 0){//黑子回合弃权 69 | if(countPlayer1Use == 0){//玩家1是黑子 70 | this->chess->gameOver(gameMode,2); 71 | } 72 | else if(countPlayer1Use == 1){//玩家1是白子 73 | this->chess->gameOver(gameMode,1); 74 | } 75 | } 76 | else if((this->chess->getStep() + countWhoFirst )%2 == 1){//白子回合弃权 77 | if(countPlayer1Use == 0){//玩家1是黑子 78 | this->chess->gameOver(gameMode,1); 79 | } 80 | else if(countPlayer1Use == 1){//玩家1是白子 81 | this->chess->gameOver(gameMode,2); 82 | } 83 | } 84 | } 85 | 86 | void PVPWindow::paintEvent(QPaintEvent *)//绘制事件 87 | { 88 | QPainter *paint=new QPainter; 89 | paint->begin(this);//开始绘制 90 | paint->setRenderHint(QPainter::Antialiasing, true);//抗锯齿 91 | paint->setPen(Qt::NoPen); 92 | QBrush *brush = new QBrush(); 93 | brush->setStyle(Qt::SolidPattern); 94 | 95 | if(countPlayer1Use == 0){ 96 | brush->setColor(Qt::black); 97 | paint->setBrush(*brush); 98 | paint->drawEllipse(625,180,28,28); 99 | 100 | brush->setColor(Qt::white); 101 | paint->setBrush(*brush); 102 | paint->drawEllipse(725,180,28,28); 103 | 104 | } 105 | else if(countPlayer1Use == 1){ 106 | brush->setColor(Qt::white); 107 | paint->setBrush(*brush); 108 | paint->drawEllipse(625,180,28,28); 109 | 110 | brush->setColor(Qt::black); 111 | paint->setBrush(*brush); 112 | paint->drawEllipse(725,180,28,28); 113 | } 114 | paint->end(); 115 | } 116 | -------------------------------------------------------------------------------- /RicardoGoBang/dialogchoosepiece.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | DialogChoosePiece 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 30 20 | 240 21 | 341 22 | 32 23 | 24 | 25 | 26 | Qt::Horizontal 27 | 28 | 29 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 30 | 31 | 32 | 33 | 34 | 35 | 50 36 | 50 37 | 151 38 | 61 39 | 40 | 41 | 42 | 黑子 43 | 44 | 45 | 46 | 47 | 48 | 210 49 | 50 50 | 151 51 | 61 52 | 53 | 54 | 55 | 白子 56 | 57 | 58 | 59 | 60 | 61 | 50 62 | 130 63 | 151 64 | 61 65 | 66 | 67 | 68 | 黑子先手 69 | 70 | 71 | 72 | 73 | 74 | 210 75 | 130 76 | 151 77 | 61 78 | 79 | 80 | 81 | 白子先手 82 | 83 | 84 | 85 | 86 | 87 | 30 88 | 40 89 | 191 90 | 16 91 | 92 | 93 | 94 | 选择玩家1棋子 95 | 96 | 97 | 98 | 99 | 100 | 30 101 | 120 102 | 171 103 | 16 104 | 105 | 106 | 107 | 选择先手: 108 | 109 | 110 | 111 | 112 | 113 | 114 | buttonBox 115 | accepted() 116 | DialogChoosePiece 117 | accept() 118 | 119 | 120 | 248 121 | 254 122 | 123 | 124 | 157 125 | 274 126 | 127 | 128 | 129 | 130 | buttonBox 131 | rejected() 132 | DialogChoosePiece 133 | reject() 134 | 135 | 136 | 316 137 | 260 138 | 139 | 140 | 286 141 | 274 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /RicardoGoBang/pvmwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "pvmwindow.h" 2 | #include "ui_pvmwindow.h" 3 | #include 4 | extern bool gameState; 5 | extern int gameMode; 6 | extern int countWhoFirst; 7 | extern int countPlayer1Use; 8 | extern bool isFirstStep; 9 | 10 | PVMWindow::PVMWindow(QWidget *parent) : 11 | QMainWindow(parent), 12 | ui(new Ui::PVMWindow) 13 | { 14 | ui->setupUi(this); 15 | Chess *chess = new Chess(ui->widget_chess); 16 | this->chess = chess; 17 | isFirstStep = true; 18 | gameMode = 2; 19 | connect(chess,SIGNAL(start_emit(int,int,int)),this,SLOT(read_emit(int,int,int))); 20 | } 21 | 22 | PVMWindow::~PVMWindow() 23 | { 24 | delete ui; 25 | } 26 | 27 | void PVMWindow::on_btn_back_clicked() 28 | { 29 | gameState = false; 30 | countPlayer1Use = -1; 31 | emit sendsignal(); 32 | this->close(); 33 | isFirstStep = true; 34 | } 35 | 36 | void PVMWindow::on_btn_about_clicked() 37 | { 38 | DialogAbout *dialogAbout = new DialogAbout(this); 39 | dialogAbout->show(); 40 | } 41 | 42 | void PVMWindow::on_btn_start_clicked() 43 | { 44 | DialogChoosePiece *dialog = new DialogChoosePiece(this); 45 | dialog->show(); 46 | connect(dialog,SIGNAL(restart_emit()),this,SLOT(restartGame())); 47 | } 48 | 49 | void PVMWindow::restartGame(){ 50 | this->chess->clearChessBoard(); 51 | this->chess->setWhoWin(0); 52 | this->ui->label_step->setText(QString("STEP: ")+QString::number(this->chess->getStep(),10)+QString(" 步")); 53 | this->ui->btn_start->setText("重新开始"); 54 | isFirstStep = true; 55 | gameState = true; 56 | if(gameMode == 2){ 57 | if(countWhoFirst == 0 && countPlayer1Use == 1){//黑子先手 白子玩家 58 | ChessEngine::reset(1); 59 | this->chess->setStep(1); 60 | read_emit(1,0,0); 61 | } 62 | else if(countWhoFirst == 1 && countPlayer1Use == 0){//白子先手 黑子玩家 63 | ChessEngine::reset(1); 64 | this->chess->setStep(1); 65 | read_emit(1,0,0); 66 | } 67 | else{ 68 | ChessEngine::reset(0); 69 | this->chess->setStep(0); 70 | read_emit(0,0,0); 71 | } 72 | } 73 | } 74 | 75 | void PVMWindow::paintEvent(QPaintEvent *)//绘制事件 76 | { 77 | QPainter *paint=new QPainter; 78 | paint->begin(this);//开始绘制 79 | paint->setRenderHint(QPainter::Antialiasing, true);//抗锯齿 80 | paint->setPen(Qt::NoPen); 81 | QBrush *brush = new QBrush(); 82 | brush->setStyle(Qt::SolidPattern); 83 | 84 | if(countPlayer1Use == 0){ 85 | brush->setColor(Qt::black); 86 | paint->setBrush(*brush); 87 | paint->drawEllipse(625,180,28,28); 88 | 89 | brush->setColor(Qt::white); 90 | paint->setBrush(*brush); 91 | paint->drawEllipse(725,180,28,28); 92 | 93 | } 94 | else if(countPlayer1Use == 1){ 95 | brush->setColor(Qt::white); 96 | paint->setBrush(*brush); 97 | paint->drawEllipse(625,180,28,28); 98 | 99 | brush->setColor(Qt::black); 100 | paint->setBrush(*brush); 101 | paint->drawEllipse(725,180,28,28); 102 | } 103 | paint->end(); 104 | } 105 | 106 | void PVMWindow::on_btn_undo_clicked()//人机模式悔棋悔两步,一步玩家一步电脑 107 | { 108 | gameState = true; 109 | ChessEngine::takeBack(); 110 | this->chess->deleteChessBoardXY(); 111 | update(); 112 | } 113 | 114 | void PVMWindow::on_btn_giveup_clicked() 115 | { 116 | isFirstStep = true; 117 | if(gameMode == 2){ 118 | this->chess->gameOver(gameMode,2); 119 | } 120 | else if((this->chess->getStep()+ countWhoFirst )%2 == 0){//黑子回合弃权 121 | if(countPlayer1Use == 0){//玩家1是黑子 122 | this->chess->gameOver(gameMode,2); 123 | } 124 | else if(countPlayer1Use == 1){//玩家1是白子 125 | this->chess->gameOver(gameMode,1); 126 | } 127 | } 128 | else if((this->chess->getStep() + countWhoFirst )%2 == 1){//白子回合弃权 129 | if(countPlayer1Use == 0){//玩家1是黑子 130 | this->chess->gameOver(gameMode,1); 131 | } 132 | else if(countPlayer1Use == 1){//玩家1是白子 133 | this->chess->gameOver(gameMode,2); 134 | } 135 | } 136 | } 137 | 138 | void PVMWindow::read_emit(int num ,int score1 ,int score2){ 139 | QString str = QString("STEP: ")+QString::number(num,10)+QString(" 步"); 140 | 141 | QString score = QString("局势得分:\n黑子:白子 = ")+QString::number(score1,10) + QString(" : ") +QString::number(score2,10); 142 | ui->label_step->setText(str); 143 | ui->label_rate->setText(score); 144 | } 145 | -------------------------------------------------------------------------------- /RicardoGoBang/acsearcher.cpp: -------------------------------------------------------------------------------- 1 | #include "ACSearcher.h" 2 | 3 | #include 4 | 5 | 6 | ACSearcher::ACSearcher() 7 | :maxState(0) 8 | { 9 | //初始化根节点 10 | AddState(-1, 'a'); 11 | nodes[0].fail = -1; 12 | 13 | } 14 | 15 | 16 | ACSearcher::~ACSearcher() 17 | { 18 | } 19 | 20 | 21 | void ACSearcher::LoadPatern(const vector& paterns) { 22 | this->paterns = paterns; 23 | } 24 | 25 | void ACSearcher::BuildGotoTable() { 26 | assert(nodes.size()); 27 | 28 | unsigned int i, j; 29 | for (i = 0; i < paterns.size(); i++) { 30 | //从根节点开始 31 | int currentIndex = 0; 32 | for (j = 0; j < paterns[i].size(); j++) { 33 | if (nodes[currentIndex].sons.find(paterns[i][j]) == nodes[currentIndex].sons.end()) { 34 | nodes[currentIndex].sons[paterns[i][j]] = ++maxState; 35 | 36 | //生成新节点 37 | AddState(currentIndex, paterns[i][j]); 38 | currentIndex = maxState; 39 | } 40 | else { 41 | currentIndex = nodes[currentIndex].sons[paterns[i][j]]; 42 | } 43 | } 44 | 45 | nodes[currentIndex].output.push_back(i); 46 | } 47 | } 48 | 49 | void ACSearcher::BuildFailTable() { 50 | assert(nodes.size()); 51 | 52 | //中间节点收集器 53 | vector midNodesIndex; 54 | 55 | //给第一层的节点设置fail为0,并把第二层节点加入到midState里 56 | ACNode root = nodes[0]; 57 | 58 | map::iterator iter1, iter2; 59 | for (iter1 = root.sons.begin(); iter1 != root.sons.end(); iter1++) { 60 | nodes[iter1->second].fail = 0; 61 | ACNode ¤tNode = nodes[iter1->second]; 62 | 63 | //收集第三层节点 64 | for (iter2 = currentNode.sons.begin(); iter2 != currentNode.sons.end(); iter2++) { 65 | midNodesIndex.push_back(iter2->second); 66 | } 67 | } 68 | 69 | //广度优先遍历 70 | while (midNodesIndex.size()) { 71 | vector newMidNodesIndex; 72 | 73 | unsigned int i; 74 | for (i = 0; i < midNodesIndex.size(); i++) { 75 | ACNode ¤tNode = nodes[midNodesIndex[i]]; 76 | 77 | //以下循环为寻找当前节点的fail值 78 | int currentFail = nodes[currentNode.parent].fail; 79 | while (true) { 80 | ACNode ¤tFailNode = nodes[currentFail]; 81 | 82 | if (currentFailNode.sons.find(currentNode.ch) != currentFailNode.sons.end()) { 83 | //成功找到该节点的fail值 84 | currentNode.fail = currentFailNode.sons.find(currentNode.ch)->second; 85 | 86 | //后缀包含 87 | if (nodes[currentNode.fail].output.size()) { 88 | currentNode.output.insert(currentNode.output.end(), nodes[currentNode.fail].output.begin(), nodes[currentNode.fail].output.end()); 89 | } 90 | 91 | break; 92 | } 93 | else { 94 | currentFail = currentFailNode.fail; 95 | } 96 | 97 | //如果是根节点 98 | if (currentFail == -1) { 99 | currentNode.fail = 0; 100 | break; 101 | } 102 | } 103 | 104 | //收集下一层节点 105 | for (iter1 = currentNode.sons.begin(); iter1 != currentNode.sons.end(); iter1++) { 106 | //收集下一层节点 107 | newMidNodesIndex.push_back(iter1->second); 108 | } 109 | } 110 | midNodesIndex = newMidNodesIndex; 111 | } 112 | } 113 | 114 | vector ACSearcher::ACSearch(const std::string& text) { 115 | vector result; 116 | 117 | //初始化为根节点 118 | int currentIndex = 0; 119 | 120 | unsigned int i; 121 | map::iterator tmpIter; 122 | for (i = 0; i < text.size();) { 123 | //顺着trie树查找 124 | if ((tmpIter = nodes[currentIndex].sons.find(text[i])) != nodes[currentIndex].sons.end()) { 125 | currentIndex = tmpIter->second; 126 | i++; 127 | } 128 | else { 129 | //失配的情况 130 | while (nodes[currentIndex].fail != -1 && nodes[currentIndex].sons.find(text[i]) == nodes[currentIndex].sons.end()) { 131 | currentIndex = nodes[currentIndex].fail; 132 | } 133 | 134 | //如果没有成功找到合适的fail 135 | if (nodes[currentIndex].sons.find(text[i]) == nodes[currentIndex].sons.end()) { 136 | i++; 137 | } 138 | } 139 | 140 | if (nodes[currentIndex].output.size()) { 141 | result.insert(result.end(), nodes[currentIndex].output.begin(), nodes[currentIndex].output.end()); 142 | } 143 | 144 | } 145 | 146 | return result; 147 | } 148 | 149 | void ACSearcher::AddState(int parent, char ch) { 150 | nodes.push_back(ACNode(parent, ch)); 151 | assert(nodes.size() - 1 == maxState); 152 | } 153 | -------------------------------------------------------------------------------- /RicardoGoBang/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 800 10 | 610 11 | 12 | 13 | 14 | 15 | 800 16 | 610 17 | 18 | 19 | 20 | 21 | 800 22 | 610 23 | 24 | 25 | 26 | 27 | 800 28 | 600 29 | 30 | 31 | 32 | RicardoGoBang 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 300 42 | 150 43 | 200 44 | 70 45 | 46 | 47 | 48 | 49 | 200 50 | 70 51 | 52 | 53 | 54 | 55 | Microsoft Sans Serif 56 | 20 57 | 75 58 | true 59 | 60 | 61 | 62 | QPushButton { 63 | border: 2px solid #8f8f91; 64 | border-radius: 20px; 65 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 66 | stop: 0 #00A1F1, stop: 1 #0072C6); 67 | } 68 | 69 | QPushButton:pressed { 70 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 71 | stop: 0 #dadbde, stop: 1 #f6f7fa); 72 | } 73 | QPushButton:default { 74 | border-color: navy; /* 使得按钮显示变得更加突出 */ 75 | } 76 | 77 | 78 | 79 | 双人对战 80 | 81 | 82 | 83 | 84 | 85 | 300 86 | 250 87 | 200 88 | 70 89 | 90 | 91 | 92 | 93 | 200 94 | 70 95 | 96 | 97 | 98 | 99 | Microsoft Sans Serif 100 | 20 101 | 75 102 | true 103 | 104 | 105 | 106 | QPushButton { 107 | border: 2px solid #8f8f91; 108 | border-radius: 20px; 109 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 110 | stop: 0 #00A1F1, stop: 1 #0072C6); 111 | } 112 | 113 | QPushButton:pressed { 114 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 115 | stop: 0 #dadbde, stop: 1 #f6f7fa); 116 | } 117 | QPushButton:default { 118 | border-color: navy; /* 使得按钮显示变得更加突出 */ 119 | } 120 | 121 | 122 | 123 | 人机对战 124 | 125 | 126 | 127 | 128 | 129 | 300 130 | 350 131 | 200 132 | 70 133 | 134 | 135 | 136 | 137 | 200 138 | 70 139 | 140 | 141 | 142 | 143 | Microsoft Sans Serif 144 | 20 145 | 75 146 | true 147 | 148 | 149 | 150 | QPushButton { 151 | border: 2px solid #8f8f91; 152 | border-radius: 20px; 153 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 154 | stop: 0 #00A1F1, stop: 1 #0072C6); 155 | } 156 | 157 | QPushButton:pressed { 158 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 159 | stop: 0 #dadbde, stop: 1 #f6f7fa); 160 | } 161 | QPushButton:default { 162 | border-color: navy; /* 使得按钮显示变得更加突出 */ 163 | } 164 | 165 | 166 | 167 | 退出游戏 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /RicardoGoBang/dialogabout.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | DialogAbout 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | 关于 15 | 16 | 17 | 18 | 19 | 30 20 | 60 21 | 300 22 | 16 23 | 24 | 25 | 26 | 27 | Microsoft Sans Serif 28 | 15 29 | 75 30 | true 31 | 32 | 33 | 34 | color:#1FB922 35 | 36 | 37 | 这是什么: 38 | 39 | 40 | 41 | 42 | 43 | 30 44 | 80 45 | 361 46 | 61 47 | 48 | 49 | 50 | 51 | Microsoft Sans Serif 52 | 53 | 54 | 55 | 这是一个开源的五子棋软件,包含双人对战和人机对战。 56 | 由C++及QT框架完成,无后台通信,AI具有一定的棋力。 57 | 该软件跨Windows,MacOS,Linux三大主流桌面操作系统。 58 | 59 | 60 | 61 | 62 | 63 | 30 64 | 150 65 | 300 66 | 16 67 | 68 | 69 | 70 | 71 | Microsoft Sans Serif 72 | 15 73 | 75 74 | true 75 | 76 | 77 | 78 | color:#1FB922 79 | 80 | 81 | 源码: 82 | 83 | 84 | 85 | 86 | 87 | 30 88 | 170 89 | 300 90 | 21 91 | 92 | 93 | 94 | 95 | Microsoft Sans Serif 96 | 97 | 98 | 99 | 源码在这里: 100 | 101 | 102 | 103 | 104 | 105 | 30 106 | 200 107 | 300 108 | 16 109 | 110 | 111 | 112 | 113 | Microsoft Sans Serif 114 | 15 115 | 75 116 | true 117 | 118 | 119 | 120 | color:#1FB922 121 | 122 | 123 | 关于作者: 124 | 125 | 126 | 127 | 128 | 129 | 20 130 | 10 131 | 300 132 | 41 133 | 134 | 135 | 136 | 137 | Microsoft Sans Serif 138 | 22 139 | 75 140 | true 141 | 142 | 143 | 144 | RicardoGoBang 145 | 146 | 147 | 148 | 149 | 150 | 30 151 | 220 152 | 300 153 | 16 154 | 155 | 156 | 157 | 158 | Microsoft Sans Serif 159 | 160 | 161 | 162 | 作者@o风向晚o 163 | 164 | 165 | 166 | 167 | 168 | 30 169 | 240 170 | 300 171 | 21 172 | 173 | 174 | 175 | 176 | Microsoft Sans Serif 177 | 178 | 179 | 180 | 个人网站: 181 | 182 | 183 | 184 | 185 | 186 | 30 187 | 260 188 | 300 189 | 21 190 | 191 | 192 | 193 | 194 | Microsoft Sans Serif 195 | 196 | 197 | 198 | github主页: 199 | 200 | 201 | 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /RicardoGoBang/pvmwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | PVMWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 800 10 | 610 11 | 12 | 13 | 14 | 15 | 800 16 | 610 17 | 18 | 19 | 20 | 21 | 800 22 | 610 23 | 24 | 25 | 26 | RicardoGoBang 27 | 28 | 29 | 30 | 31 | 32 | 640 33 | 480 34 | 120 35 | 50 36 | 37 | 38 | 39 | 40 | Microsoft Sans Serif 41 | 18 42 | 75 43 | true 44 | 45 | 46 | 47 | QPushButton { 48 | border: 2px solid #8f8f91; 49 | border-radius: 20px; 50 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 51 | stop: 0 #00A1F1, stop: 1 #0072C6); 52 | } 53 | 54 | QPushButton:pressed { 55 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 56 | stop: 0 #dadbde, stop: 1 #f6f7fa); 57 | } 58 | QPushButton:default { 59 | border-color: navy; /* 使得按钮显示变得更加突出 */ 60 | } 61 | 62 | 63 | 64 | 返回 65 | 66 | 67 | 68 | 69 | 70 | 640 71 | 360 72 | 120 73 | 50 74 | 75 | 76 | 77 | 78 | Microsoft Sans Serif 79 | 18 80 | 75 81 | true 82 | 83 | 84 | 85 | QPushButton { 86 | border: 2px solid #8f8f91; 87 | border-radius: 20px; 88 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 89 | stop: 0 #00A1F1, stop: 1 #0072C6); 90 | } 91 | 92 | QPushButton:pressed { 93 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 94 | stop: 0 #dadbde, stop: 1 #f6f7fa); 95 | } 96 | QPushButton:default { 97 | border-color: navy; /* 使得按钮显示变得更加突出 */ 98 | } 99 | 100 | 101 | 102 | 悔棋 103 | 104 | 105 | 106 | 107 | 108 | 640 109 | 420 110 | 120 111 | 50 112 | 113 | 114 | 115 | 116 | Microsoft Sans Serif 117 | 18 118 | 75 119 | true 120 | 121 | 122 | 123 | QPushButton { 124 | border: 2px solid #8f8f91; 125 | border-radius: 20px; 126 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 127 | stop: 0 #00A1F1, stop: 1 #0072C6); 128 | } 129 | 130 | QPushButton:pressed { 131 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 132 | stop: 0 #dadbde, stop: 1 #f6f7fa); 133 | } 134 | QPushButton:default { 135 | border-color: navy; /* 使得按钮显示变得更加突出 */ 136 | } 137 | 138 | 139 | 140 | 弃权 141 | 142 | 143 | 144 | 145 | 146 | 640 147 | 300 148 | 120 149 | 50 150 | 151 | 152 | 153 | 154 | Microsoft Sans Serif 155 | 18 156 | 75 157 | true 158 | 159 | 160 | 161 | QPushButton { 162 | border: 2px solid #8f8f91; 163 | border-radius: 20px; 164 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 165 | stop: 0 #00A1F1, stop: 1 #0072C6); 166 | } 167 | 168 | QPushButton:pressed { 169 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 170 | stop: 0 #dadbde, stop: 1 #f6f7fa); 171 | } 172 | QPushButton:default { 173 | border-color: navy; /* 使得按钮显示变得更加突出 */ 174 | } 175 | 176 | 177 | 178 | 开始 179 | 180 | 181 | 182 | 183 | 184 | 640 185 | 540 186 | 120 187 | 50 188 | 189 | 190 | 191 | 192 | Microsoft Sans Serif 193 | 18 194 | 75 195 | true 196 | 197 | 198 | 199 | QPushButton { 200 | border: 2px solid #8f8f91; 201 | border-radius: 20px; 202 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 203 | stop: 0 #00A1F1, stop: 1 #0072C6); 204 | } 205 | 206 | QPushButton:pressed { 207 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 208 | stop: 0 #dadbde, stop: 1 #f6f7fa); 209 | } 210 | QPushButton:default { 211 | border-color: navy; /* 使得按钮显示变得更加突出 */ 212 | } 213 | 214 | 215 | 216 | 关于 217 | 218 | 219 | 220 | 221 | 222 | 600 223 | 20 224 | 200 225 | 50 226 | 227 | 228 | 229 | 230 | Microsoft Sans Serif 231 | 18 232 | 75 233 | true 234 | 235 | 236 | 237 | color:#f65314 238 | 239 | 240 | STEP: 0 步 241 | 242 | 243 | Qt::AlignCenter 244 | 245 | 246 | 247 | 248 | 249 | 600 250 | 89 251 | 200 252 | 41 253 | 254 | 255 | 256 | 257 | Microsoft Sans Serif 258 | 12 259 | 75 260 | true 261 | 262 | 263 | 264 | color:#f65314 265 | 266 | 267 | 局势得分: 268 | 黑子:白子 = 0 : 0 269 | 270 | 271 | Qt::AlignCenter 272 | 273 | 274 | 275 | 276 | 277 | 0 278 | 0 279 | 600 280 | 600 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 620 289 | 160 290 | 60 291 | 16 292 | 293 | 294 | 295 | 296 | Microsoft Sans Serif 297 | 298 | 299 | 300 | color:#1FB922 301 | 302 | 303 | 玩家: 304 | 305 | 306 | 307 | 308 | 309 | 720 310 | 160 311 | 60 312 | 16 313 | 314 | 315 | 316 | 317 | Microsoft Sans Serif 318 | 319 | 320 | 321 | color:#1FB922 322 | 323 | 324 | 电脑: 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | -------------------------------------------------------------------------------- /RicardoGoBang/pvpwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | PVPWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 800 10 | 610 11 | 12 | 13 | 14 | 15 | 800 16 | 610 17 | 18 | 19 | 20 | 21 | 800 22 | 610 23 | 24 | 25 | 26 | RicardoGoBang 27 | 28 | 29 | 30 | 31 | 32 | 640 33 | 540 34 | 120 35 | 50 36 | 37 | 38 | 39 | 40 | Microsoft Sans Serif 41 | 18 42 | 75 43 | true 44 | 45 | 46 | 47 | QPushButton { 48 | border: 2px solid #8f8f91; 49 | border-radius: 20px; 50 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 51 | stop: 0 #00A1F1, stop: 1 #0072C6); 52 | } 53 | 54 | QPushButton:pressed { 55 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 56 | stop: 0 #dadbde, stop: 1 #f6f7fa); 57 | } 58 | QPushButton:default { 59 | border-color: navy; /* 使得按钮显示变得更加突出 */ 60 | } 61 | 62 | 63 | 64 | 关于 65 | 66 | 67 | 68 | 69 | 70 | 640 71 | 420 72 | 120 73 | 50 74 | 75 | 76 | 77 | 78 | Microsoft Sans Serif 79 | 18 80 | 75 81 | true 82 | 83 | 84 | 85 | QPushButton { 86 | border: 2px solid #8f8f91; 87 | border-radius: 20px; 88 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 89 | stop: 0 #00A1F1, stop: 1 #0072C6); 90 | } 91 | 92 | QPushButton:pressed { 93 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 94 | stop: 0 #dadbde, stop: 1 #f6f7fa); 95 | } 96 | QPushButton:default { 97 | border-color: navy; /* 使得按钮显示变得更加突出 */ 98 | } 99 | 100 | 101 | 102 | 弃权 103 | 104 | 105 | 106 | 107 | 108 | 640 109 | 480 110 | 120 111 | 50 112 | 113 | 114 | 115 | 116 | Microsoft Sans Serif 117 | 18 118 | 75 119 | true 120 | 121 | 122 | 123 | QPushButton { 124 | border: 2px solid #8f8f91; 125 | border-radius: 20px; 126 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 127 | stop: 0 #00A1F1, stop: 1 #0072C6); 128 | } 129 | 130 | QPushButton:pressed { 131 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 132 | stop: 0 #dadbde, stop: 1 #f6f7fa); 133 | } 134 | QPushButton:default { 135 | border-color: navy; /* 使得按钮显示变得更加突出 */ 136 | } 137 | 138 | 139 | 140 | 返回 141 | 142 | 143 | 144 | 145 | 146 | 640 147 | 360 148 | 120 149 | 50 150 | 151 | 152 | 153 | 154 | Microsoft Sans Serif 155 | 18 156 | 75 157 | true 158 | 159 | 160 | 161 | QPushButton { 162 | border: 2px solid #8f8f91; 163 | border-radius: 20px; 164 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 165 | stop: 0 #00A1F1, stop: 1 #0072C6); 166 | } 167 | 168 | QPushButton:pressed { 169 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 170 | stop: 0 #dadbde, stop: 1 #f6f7fa); 171 | } 172 | QPushButton:default { 173 | border-color: navy; /* 使得按钮显示变得更加突出 */ 174 | } 175 | 176 | 177 | 178 | 悔棋 179 | 180 | 181 | 182 | 183 | 184 | 640 185 | 300 186 | 120 187 | 50 188 | 189 | 190 | 191 | 192 | Microsoft Sans Serif 193 | 18 194 | 75 195 | true 196 | 197 | 198 | 199 | QPushButton { 200 | border: 2px solid #8f8f91; 201 | border-radius: 20px; 202 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 203 | stop: 0 #00A1F1, stop: 1 #0072C6); 204 | } 205 | 206 | QPushButton:pressed { 207 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, 208 | stop: 0 #dadbde, stop: 1 #f6f7fa); 209 | } 210 | QPushButton:default { 211 | border-color: navy; /* 使得按钮显示变得更加突出 */ 212 | } 213 | 214 | 215 | 216 | 开始 217 | 218 | 219 | 220 | 221 | 222 | 600 223 | 20 224 | 200 225 | 50 226 | 227 | 228 | 229 | 230 | Microsoft Sans Serif 231 | 18 232 | 75 233 | true 234 | 235 | 236 | 237 | color:#f65314 238 | 239 | 240 | STEP: 0 步 241 | 242 | 243 | Qt::AlignCenter 244 | 245 | 246 | 247 | 248 | 249 | 619 250 | 79 251 | 161 252 | 51 253 | 254 | 255 | 256 | 257 | Microsoft Sans Serif 258 | 12 259 | 75 260 | true 261 | 262 | 263 | 264 | color:#f65314 265 | 266 | 267 | <html><head/><body><p><br/></p></body></html> 268 | 269 | 270 | Qt::AlignCenter 271 | 272 | 273 | 274 | 275 | 276 | 0 277 | 0 278 | 600 279 | 610 280 | 281 | 282 | 283 | 284 | 600 285 | 610 286 | 287 | 288 | 289 | 290 | 600 291 | 610 292 | 293 | 294 | 295 | 296 | 297 | 298 | 620 299 | 160 300 | 60 301 | 16 302 | 303 | 304 | 305 | color:#1FB922 306 | 307 | 308 | 玩家1: 309 | 310 | 311 | 312 | 313 | 314 | 720 315 | 160 316 | 60 317 | 16 318 | 319 | 320 | 321 | color:#1FB922 322 | 323 | 324 | 玩家2: 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | -------------------------------------------------------------------------------- /RicardoGoBang/chessai.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | extern int chessBoard[BOARD_WIDTH][BOARD_WIDTH]; 11 | 12 | 13 | void ChessAI::chess_isover(int x,int y,int turn) 14 | { 15 | int num=1; 16 | int i,j; 17 | for(i=y-1;i>=0;--i) 18 | if(chessBoard[x][i]==turn) ++num; 19 | else break; 20 | for(i=y+1;i<16;++i) 21 | if(chessBoard[x][i]==turn) ++num; 22 | else break; 23 | if(num>=5) 24 | { 25 | isover=turn; 26 | return; 27 | } 28 | num=1; 29 | for(i=x-1;i>=0;--i) 30 | if(chessBoard[i][y]==turn) ++num; 31 | else break; 32 | for(i=x+1;i<16;++i) 33 | if(chessBoard[i][y]==turn) ++num; 34 | else break; 35 | if(num>=5) 36 | { 37 | isover=turn; 38 | return; 39 | } 40 | num=1; 41 | for(i=x-1,j=y-1;i>=0&&j>=0;--i,--j) 42 | if(chessBoard[i][j]==turn) ++num; 43 | else break; 44 | for(i=x+1,j=y+1;i<16&&j<16;++i,++j) 45 | if(chessBoard[i][j]==turn) ++num; 46 | else break; 47 | if(num>=5) 48 | { 49 | isover=turn; 50 | return; 51 | } 52 | num=1; 53 | for(i=x-1,j=y+1;i>=0&&j<16;--i,++j) 54 | if(chessBoard[i][j]==turn) ++num; 55 | else break; 56 | for(i=x+1,j=y-1;i<16&&j>=0;++i,--j) 57 | if(chessBoard[i][j]==turn) ++num; 58 | else break; 59 | if(num>=5) 60 | { 61 | isover=turn; 62 | return; 63 | } 64 | if(backnum+whitenum==16*16) 65 | { 66 | isover=3; 67 | return; 68 | } 69 | } 70 | static int score[17][17]; 71 | 72 | void generatepoint(vector< pair > &v); 73 | int scoretable(int number,int empty1); 74 | int countscore(vector n,int turn); 75 | bool hasne(int x,int y); 76 | bool hasne(int x,int y)//判断该处是否可下 77 | { 78 | int i,j; 79 | for(i=(x-1>0?x-1:0);i<=x+1&&i<16;++i) 80 | for(j=(y-1>0?y-1:0);j<=y+1&&j<16;++j) 81 | if(i!=0||j!=0) 82 | if(chessBoard[i][j]!=0) 83 | return true; 84 | return false; 85 | } 86 | int evaluate_point(int x,int y,int turn) 87 | { 88 | int scoree=0; 89 | int number=0; 90 | int empty1=0; 91 | int i,j; 92 | for(i=y-1;i>=0&&i>y-6;--i) 93 | if(chessBoard[x][i]==turn) ++number; 94 | else if(chessBoard[x][i]==0) {++empty1;break;} 95 | else break; 96 | for(i=y+1;i<16&&i=0&&i>x-6;--i) 104 | if(chessBoard[i][y]==turn) ++number; 105 | else if(chessBoard[i][y]==0) {++empty1;break;} 106 | else break; 107 | for(i=x+1;i<16&&i=0&&j>=0&&i>x-6&&j>y-6;--i,--j) 115 | if(chessBoard[i][j]==turn) ++number; 116 | else if(chessBoard[i][j]==0) {++empty1;break;} 117 | else break; 118 | for(i=x+1,j=y+1;i<16&&j<16&&i=0&&i>x-6&&j<16&&j=0&&j>y-6;++i,--j) 130 | if(chessBoard[i][j]==turn) ++number; 131 | else if(chessBoard[i][j]==0) {++empty1;break;} 132 | else break; 133 | scoree+=scoretable(number+1,empty1); 134 | return scoree; 135 | } 136 | 137 | void generatepoint(vector< pair > &v) 138 | { 139 | vector< pair > humfive; 140 | vector< pair > comfour; 141 | vector< pair > humfour; 142 | vector< pair > comdoublethree; 143 | vector< pair > humdoublethree; 144 | vector< pair > comthree; 145 | vector< pair > humthree; 146 | vector< pair > comtwo; 147 | vector< pair > humtwo; 148 | vector< pair > others; 149 | for(int i=0;i<16;++i) 150 | for(int j=0;j<16;++j) 151 | if(chessBoard[i][j]==0&&hasne(i,j)) 152 | { 153 | int scorecom=evaluate_point(i,j,2); 154 | int scorehum=evaluate_point(i,j,1); 155 | pair p; 156 | p.first=i; 157 | p.second=j; 158 | if(scorecom>=100000) {v.push_back(p);return;} 159 | else if(scorehum>=100000) {humfive.push_back(p);} 160 | else if(scorecom>=10000) comfour.push_back(p); 161 | else if(scorehum>=10000) humfour.push_back(p); 162 | else if(scorecom>=2*1000) comdoublethree.push_back(p); 163 | else if(scorehum>=2*1000) humdoublethree.push_back(p); 164 | else if(scorecom>=1000) comthree.push_back(p); 165 | else if(scorehum>=1000) humthree.push_back(p); 166 | else if(scorecom>=100) comtwo.push_back(p); 167 | else if(scorehum>=100) humtwo.push_back(p); 168 | else others.push_back(p); 169 | } 170 | if(humfive.size()>0) {v=humfive;return;} 171 | if(comfour.size()>0||humfour.size()>0) {v=comfour;v.insert(v.end(),humfour.begin(),humfour.end());return;} 172 | if(comdoublethree.size()>0||humdoublethree.size()>0) {v=comdoublethree;v.insert(v.end(),humdoublethree.begin(),humdoublethree.end());return;} 173 | v=comthree; 174 | v.insert(v.end(),humthree.begin(),humthree.end()); 175 | v.insert(v.end(),comtwo.begin(),comtwo.end()); 176 | v.insert(v.end(),humtwo.begin(),humtwo.end()); 177 | v.insert(v.end(),others.begin(),others.end()); 178 | return; 179 | } 180 | 181 | int scoretable(int number,int empty1) 182 | { 183 | if(number>=5) return 100000; 184 | else if(number==4) 185 | { 186 | if(empty1==2) return 10000; 187 | else if(empty1==1) return 1000; 188 | } 189 | else if(number==3) 190 | { 191 | if(empty1==2) return 1000; 192 | else if(empty1==1) return 100; 193 | } 194 | else if(number==2) 195 | { 196 | if(empty1==2) return 100; 197 | else if(empty1==1) return 10; 198 | } 199 | else if(number==1&&empty1==2) return 10; 200 | return 0; 201 | } 202 | 203 | struct Node 204 | { 205 | int x; 206 | int y; 207 | int s; 208 | Node(int i,int j,int k):x(i),y(j),s(k){} 209 | }; 210 | vector min_kill(int turn,int depth,int x,int y,bool &tmp ,bool &flagWin); 211 | vector max_kill(int turn,int depth,int x,int y,bool &tmp , bool &flagWin); 212 | void generatepoint_2(int turn,int scoree,vector &v); 213 | bool cmp(Node a,Node b) 214 | { 215 | return a.s>b.s; 216 | } 217 | 218 | void generatepoint_2(int turn,int scoree,vector &v) 219 | { 220 | for(int i=0;i<16;++i) 221 | for(int j=0;j<16;++j) 222 | if(chessBoard[i][j]==0&&hasne(i,j)) 223 | if(turn==0)//轮到玩家落子,玩家需要找到黑子最有利的空子+白子最有危险的空子,然后攻守随玩家 224 | { 225 | int comscore=evaluate_point(i,j,2); 226 | int humscore=evaluate_point(i,j,1); 227 | if(comscore+humscore>scoree) 228 | { 229 | Node p(i,j,comscore+humscore); 230 | v.push_back(p); 231 | } 232 | } 233 | else//轮到电脑落子,电脑只管找杀招 234 | { 235 | int s=evaluate_point(i,j,turn); 236 | if(s>scoree) 237 | { 238 | Node p(i,j,s); 239 | v.push_back(p); 240 | } 241 | } 242 | sort(v.begin(),v.end(),cmp);//空子按优先级排序 243 | } 244 | 245 | vector min_kill(int turn,int depth,int x,int y,bool &tmp,bool &winFlag) 246 | { 247 | cout< v; 249 | ChessAI cc; 250 | cc.chess_isover(x,y,2); //上一步是机器落子,落子的地方才有可能产生输赢 251 | if(isover==2) //电脑赢了 252 | { 253 | winFlag = true; 254 | isover=0; 255 | tmp=true; 256 | return v; 257 | } 258 | if(depth<0) //depth步内,玩家守的住了 259 | { 260 | tmp=false; 261 | return v; 262 | } 263 | vector p; 264 | generatepoint_2(0,1000,p);//找出所有大于活三的空子。玩家防守的话,可以是占电脑连成活四的空子,也可以是自己出击先成死四什么的。所以传的是0 265 | int len=p.size(); 266 | if(len==0) //如果没有这样的空子,表示玩家到这一步就守住了 267 | { 268 | tmp=false; 269 | return v; 270 | } 271 | vector< vector > cands; 272 | for(int i=0;i kk; 282 | kk.push_back(p[i]); 283 | v.insert(v.begin(),kk.begin(),kk.end()); 284 | cands.push_back(v); 285 | continue;//继续找可以防守住的空子 286 | } 287 | else 288 | { 289 | tmp=false; 290 | return v;//这个空子可以防守住,那就直接返回 291 | } 292 | } 293 | int i=rand()%cands.size(); 294 | return cands[i];//所有空子挨个占,depth内没一个能防住的,随机抽一个 295 | } 296 | 297 | vector max_kill(int turn,int depth,int x,int y,bool &tmp,bool &winFlag) 298 | { 299 | cout< v; 301 | ChessAI cc; 302 | cc.chess_isover(x,y,1);//上一步是玩家落子,落子的地方才有可能产生输赢 303 | if(isover==1)//玩家不仅守住了,还赢了 304 | { 305 | isover=0; 306 | tmp=false; 307 | return v; 308 | } 309 | if(depth<0)//玩家守住了 310 | { 311 | winFlag = false; 312 | tmp=false; 313 | return v; 314 | } 315 | vector p; 316 | generatepoint_2(0,2000,p);//产生所有杀招空子队列 317 | if(p.size()==0)//没有这样的空子,玩家守住了 318 | { 319 | tmp=false; 320 | return v; 321 | } 322 | int len=p.size(); 323 | for(int i=0;i kk; 333 | kk.push_back(p[i]); 334 | v.insert(v.begin(),kk.begin(),kk.end()); 335 | return v; 336 | } 337 | } 338 | tmp=false; 339 | return v; 340 | } 341 | 342 | void ChessAI::chess_ai_killcount(int &x,int &y,bool &winFlag,int depth) 343 | { 344 | vector< pair > v; 345 | generatepoint(v); 346 | int len=v.size(); 347 | vector< pair > v2; 348 | for(int i=0;i 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #define BOARD_WIDTH 15 14 | 15 | extern int chessBoard[BOARD_WIDTH][BOARD_WIDTH]; 16 | 17 | namespace ChessEngine { 18 | 19 | 20 | #define UNKNOWN_SCORE (10000001) 21 | #define HASH_ITEM_INDEX_MASK (0xffff) 22 | #define MAX_SCORE (10000000) 23 | #define MIN_SCORE (-10000000) 24 | int DEPTH = 7; 25 | bool winFlag = false; 26 | 27 | //模式 28 | vector paterns = { 29 | "11111", 30 | "011110", 31 | "011100", 32 | "001110", 33 | "011010", 34 | "010110", 35 | "11110", 36 | "01111", 37 | "11011", 38 | "10111", 39 | "11101", 40 | "001100", 41 | "001010", 42 | "010100", 43 | "000100", 44 | "001000" 45 | }; 46 | 47 | //模式相应的分数 48 | vector paternScores = { 49 | 50000, 50 | 4320, 51 | 720, 52 | 720, 53 | 720, 54 | 720, 55 | 720, 56 | 720, 57 | 720, 58 | 720, 59 | 720, 60 | 120, 61 | 120, 62 | 120, 63 | 20, 64 | 20 65 | }; 66 | 67 | //保存棋局的哈希表条目 68 | struct HashItem { 69 | long long checksum; 70 | int depth; 71 | int score; 72 | enum Flag { ALPHA = 0, BETA = 1, EXACT = 2, EMPTY = 3 } flag; 73 | }; 74 | 75 | long long boardZobristValue[2][BOARD_WIDTH][BOARD_WIDTH]; 76 | long long currentZobristValue; 77 | HashItem hashItems[HASH_ITEM_INDEX_MASK + 1]; 78 | int winner = -1; //胜出者 79 | 80 | stack moves; 81 | int scores[2][72]; //保存棋局分数(2个角色72行,包括横竖撇捺) 82 | int allScore[2]; //局面总评分(2个角色) 83 | 84 | //ac算法实现的模式匹配器 85 | ACSearcher acs; 86 | 87 | PossiblePositionManager ppm; 88 | 89 | //记录计算结果在哈希表中 90 | void recordHashItem(int depth, int score, HashItem::Flag flag) { 91 | int index = (int)(currentZobristValue & HASH_ITEM_INDEX_MASK); 92 | HashItem *phashItem = &hashItems[index]; 93 | 94 | if (phashItem->flag != HashItem::EMPTY && phashItem->depth > depth) { 95 | return; 96 | } 97 | 98 | phashItem->checksum = currentZobristValue; 99 | phashItem->score = score; 100 | phashItem->flag = flag; 101 | phashItem->depth = depth; 102 | } 103 | 104 | 105 | //在哈希表中取得计算好的局面的分数 106 | int getHashItemScore(int depth, int alpha, int beta) { 107 | int index = (int)(currentZobristValue & HASH_ITEM_INDEX_MASK); 108 | HashItem *phashItem = &hashItems[index]; 109 | 110 | if (phashItem->flag == HashItem::EMPTY) 111 | return UNKNOWN_SCORE; 112 | 113 | if (phashItem->checksum == currentZobristValue) { 114 | if (phashItem->depth >= depth) { 115 | if (phashItem->flag == HashItem::EXACT) { 116 | return phashItem->score; 117 | } 118 | if (phashItem->flag == HashItem::ALPHA && phashItem->score <= alpha) { 119 | return alpha; 120 | } 121 | if (phashItem->flag == HashItem::BETA && phashItem->score >= beta) { 122 | return beta; 123 | } 124 | } 125 | } 126 | 127 | return UNKNOWN_SCORE; 128 | } 129 | 130 | //生成64位随机数 131 | long long random64() { 132 | return (long long)rand() | ((long long)rand() << 15) | ((long long)rand() << 30) | ((long long)rand() << 45) | ((long long)rand() << 60); 133 | } 134 | 135 | //生成zobrist键值 136 | void randomBoardZobristValue() { 137 | int i, j, k; 138 | for (i = 0; i < 2; i++) { 139 | for (j = 0; j < BOARD_WIDTH; j++) { 140 | for (k = 0; k < BOARD_WIDTH; k++) { 141 | boardZobristValue[i][j][k] = random64(); 142 | } 143 | } 144 | } 145 | } 146 | 147 | //初始化初始局面的zobrist值 148 | void initCurrentZobristValue() { 149 | currentZobristValue = random64(); 150 | } 151 | 152 | //存储搜索结果,即下一步棋子的位置 153 | Position searchResult; 154 | 155 | 156 | //根据位置评分,其中board是当前棋盘,p是位置,role是评分角色,比如role是Human则是相对人类评分,比如role是computer则是对于电脑评分 157 | int evaluatePoint(int chessBoard[BOARD_WIDTH][BOARD_WIDTH], Position p) { 158 | int result; 159 | unsigned int i, j; 160 | int role; 161 | 162 | result = 0; 163 | role = HUMAN; 164 | 165 | 166 | string lines[4]; 167 | string lines1[4]; 168 | for (i = max(0, p.x - 5); i < (unsigned int)min(BOARD_WIDTH, p.x + 6); i++) { 169 | if (i != p.x) { 170 | lines[0].push_back(chessBoard[i][p.y] == role ? '1' : chessBoard[i][p.y] == 0 ? '0' : '2'); 171 | lines1[0].push_back(chessBoard[i][p.y] == role ? '2' : chessBoard[i][p.y] == 0 ? '0' : '1'); 172 | } 173 | else { 174 | lines[0].push_back('1'); 175 | lines1[0].push_back('1'); 176 | } 177 | } 178 | for (i = max(0, p.y - 5); i < (unsigned int)min(BOARD_WIDTH, p.y + 6); i++) { 179 | if (i != p.y) { 180 | lines[1].push_back(chessBoard[p.x][i] == role ? '1' : chessBoard[p.x][i] == 0 ? '0' : '2'); 181 | lines1[1].push_back(chessBoard[p.x][i] == role ? '2' : chessBoard[p.x][i] == 0 ? '0' : '1'); 182 | } 183 | else { 184 | lines[1].push_back('1'); 185 | lines1[1].push_back('1'); 186 | } 187 | } 188 | for (i = p.x - min(min(p.x, p.y), 5), j = p.y - min(min(p.x, p.y), 5); i < (unsigned int)min(BOARD_WIDTH, p.x + 6) && j < (unsigned int)min(BOARD_WIDTH, p.y + 6); i++, j++) { 189 | if (i != p.x) { 190 | lines[2].push_back(chessBoard[i][j] == role ? '1' : chessBoard[i][j] == 0 ? '0' : '2'); 191 | lines1[2].push_back(chessBoard[i][j] == role ? '2' : chessBoard[i][j] == 0 ? '0' : '1'); 192 | } 193 | else { 194 | lines[2].push_back('1'); 195 | lines1[2].push_back('1'); 196 | } 197 | } 198 | for (i = p.x + min(min(p.y, BOARD_WIDTH - 1 - p.x), 5), j = p.y - min(min(p.y, BOARD_WIDTH - 1 - p.x), 5); i >= (unsigned int)max(0, p.x - 5) && i tmp = acs.ACSearch(lines[i]); 211 | for (j = 0; j < tmp.size(); j++) { 212 | result += paternScores[tmp[j]]; 213 | } 214 | 215 | tmp = acs.ACSearch(lines1[i]); 216 | for (j = 0; j < tmp.size(); j++) { 217 | result += paternScores[tmp[j]]; 218 | } 219 | } 220 | //在边界情况下分值变动 221 | if(p.x == 0 || p.x == 14 || p.y == 0 || p.y == 14){ 222 | if(result <= 2000){ 223 | result = 0; 224 | } 225 | } 226 | return result; 227 | } 228 | 229 | 230 | //局面评估函数,给一个局面评分 231 | int evaluate(int chessBoard[BOARD_WIDTH][BOARD_WIDTH], int role) { 232 | 233 | if (role == COMPUTOR) { 234 | return allScore[1]; 235 | } 236 | else if (role == HUMAN) { 237 | return allScore[0]; 238 | } 239 | 240 | cout << "error" << endl; 241 | 242 | return 0; 243 | } 244 | 245 | 246 | void updateScore(int chessBoard[BOARD_WIDTH][BOARD_WIDTH], Position p) { 247 | 248 | string lines[4]; 249 | string lines1[4]; 250 | unsigned int i, j; 251 | int role = HUMAN; 252 | 253 | //竖 254 | for (i = 0; i < BOARD_WIDTH; i++) { 255 | 256 | lines[0].push_back(chessBoard[i][p.y] == role ? '1' : chessBoard[i][p.y] == 0 ? '0' : '2'); 257 | lines1[0].push_back(chessBoard[i][p.y] == role ? '2' : chessBoard[i][p.y] == 0 ? '0' : '1'); 258 | 259 | 260 | } 261 | //横 262 | for (i = 0; i < BOARD_WIDTH; i++) { 263 | 264 | lines[1].push_back(chessBoard[p.x][i] == role ? '1' : chessBoard[p.x][i] == 0 ? '0' : '2'); 265 | lines1[1].push_back(chessBoard[p.x][i] == role ? '2' : chessBoard[p.x][i] == 0 ? '0' : '1'); 266 | 267 | } 268 | //反斜杠 269 | for (i = p.x - min(p.x, p.y), j = p.y - min(p.x, p.y); i < BOARD_WIDTH && j < BOARD_WIDTH; i++, j++) { 270 | 271 | lines[2].push_back(chessBoard[i][j] == role ? '1' : chessBoard[i][j] == 0 ? '0' : '2'); 272 | lines1[2].push_back(chessBoard[i][j] == role ? '2' : chessBoard[i][j] == 0 ? '0' : '1'); 273 | 274 | } 275 | //斜杠 276 | for (i = p.x + min(p.y, BOARD_WIDTH - 1 - p.x), j = p.y - min(p.y, BOARD_WIDTH - 1 - p.x); i >= 0 && i< BOARD_WIDTH && j < BOARD_WIDTH; i--, j++) { 277 | 278 | 279 | lines[3].push_back(chessBoard[i][j] == role ? '1' : chessBoard[i][j] == 0 ? '0' : '2'); 280 | lines1[3].push_back(chessBoard[i][j] == role ? '2' : chessBoard[i][j] == 0 ? '0' : '1'); 281 | 282 | } 283 | 284 | int lineScore[4]; 285 | int line1Score[4]; 286 | memset(lineScore, 0, sizeof(lineScore)); 287 | memset(line1Score, 0, sizeof(line1Score)); 288 | 289 | //计算分数 290 | for (i = 0; i < 4; i++) { 291 | vector result = acs.ACSearch(lines[i]); 292 | for (j = 0; j < result.size(); j++) { 293 | lineScore[i] += paternScores[result[j]]; 294 | } 295 | 296 | result = acs.ACSearch(lines1[i]); 297 | for (j = 0; j < result.size(); j++) { 298 | line1Score[i] += paternScores[result[j]]; 299 | } 300 | } 301 | 302 | int a = p.y; 303 | int b = BOARD_WIDTH + p.x; 304 | int c = 2 * BOARD_WIDTH + (p.y - p.x + 10); 305 | int d = 2 * BOARD_WIDTH + 21 + (p.x + p.y - 4); 306 | //减去以前的记录 307 | for (i = 0; i < 2; i++) { 308 | allScore[i] -= scores[i][a]; 309 | allScore[i] -= scores[i][b]; 310 | } 311 | 312 | //scores顺序 竖、横、\、/ 313 | scores[0][a] = lineScore[0]; 314 | scores[1][a] = line1Score[0]; 315 | scores[0][b] = lineScore[1]; 316 | scores[1][b] = line1Score[1]; 317 | 318 | 319 | //加上新的记录 320 | for (i = 0; i < 2; i++) { 321 | allScore[i] += scores[i][a]; 322 | allScore[i] += scores[i][b]; 323 | } 324 | 325 | if (p.y - p.x >= -10 && p.y - p.x <= 10) { 326 | 327 | for (i = 0; i < 2; i++) 328 | allScore[i] -= scores[i][c]; 329 | 330 | 331 | scores[0][c] = lineScore[2]; 332 | scores[1][c] = line1Score[2]; 333 | 334 | for (i = 0; i < 2; i++) 335 | allScore[i] += scores[i][c]; 336 | 337 | } 338 | 339 | if (p.x + p.y >= 4 && p.x + p.y <= 24) { 340 | 341 | for (i = 0; i < 2; i++) 342 | allScore[i] -= scores[i][d]; 343 | 344 | scores[0][d] = lineScore[3]; 345 | scores[1][d] = line1Score[3]; 346 | 347 | for (i = 0; i < 2; i++) 348 | allScore[i] += scores[i][d]; 349 | } 350 | } 351 | 352 | //alpha-beta剪枝 353 | int abSearch(int chessBoard[BOARD_WIDTH][BOARD_WIDTH], int depth, int alpha, int beta, Role currentSearchRole) { 354 | HashItem::Flag flag = HashItem::ALPHA; 355 | int score = getHashItemScore(depth, alpha, beta); 356 | if (score != UNKNOWN_SCORE && depth != DEPTH) { 357 | return score; 358 | } 359 | 360 | int score1 = evaluate(chessBoard, currentSearchRole); 361 | int score2 = evaluate(chessBoard, currentSearchRole == HUMAN ? COMPUTOR : HUMAN); 362 | 363 | 364 | if (score1 >= 50000) { 365 | return MAX_SCORE - 1000 - (DEPTH - depth); 366 | } 367 | if (score2 >= 50000) { 368 | return MIN_SCORE + 1000 + (DEPTH - depth); 369 | } 370 | 371 | 372 | if (depth == 0) { 373 | recordHashItem(depth, score1 - score2, HashItem::EXACT); 374 | return score1 - score2; 375 | } 376 | 377 | //set possiblePossitions = createPossiblePosition(board); 378 | 379 | 380 | int count = 0; 381 | set possiblePositions; 382 | set tmpPossiblePositions = ppm.GetCurrentPossiblePositions(); 383 | 384 | //对当前可能出现的位置进行粗略评分 385 | set::iterator iter; 386 | for (iter = tmpPossiblePositions.begin(); iter != tmpPossiblePositions.end(); iter++) { 387 | possiblePositions.insert(Position(iter->x, iter->y, evaluatePoint(chessBoard, *iter))); 388 | } 389 | 390 | while (!possiblePositions.empty()) { 391 | Position p = *possiblePositions.begin(); 392 | 393 | possiblePositions.erase(possiblePositions.begin()); 394 | 395 | //放置棋子 396 | chessBoard[p.x][p.y] = currentSearchRole; 397 | currentZobristValue ^= boardZobristValue[currentSearchRole - 1][p.x][p.y]; 398 | updateScore(chessBoard, p); 399 | 400 | //增加可能出现的位置 401 | p.score = 0; 402 | ppm.AddPossiblePositions(chessBoard, p); 403 | 404 | int val = -abSearch(chessBoard, depth - 1, -beta, -alpha, currentSearchRole == HUMAN ? COMPUTOR : HUMAN); 405 | if (depth == DEPTH) 406 | cout << "score(" << p.x << "," << p.y << "):" << val << endl; 407 | 408 | //取消上一次增加的可能出现的位置 409 | ppm.Rollback(); 410 | 411 | //取消放置 412 | chessBoard[p.x][p.y] = 0; 413 | currentZobristValue ^= boardZobristValue[currentSearchRole - 1][p.x][p.y]; 414 | updateScore(chessBoard, p); 415 | 416 | if (val >= beta) { 417 | recordHashItem(depth, beta, HashItem::BETA); 418 | return beta; 419 | } 420 | if (val > alpha) { 421 | flag = HashItem::EXACT; 422 | alpha = val; 423 | if (depth == DEPTH) { 424 | searchResult = p; 425 | } 426 | } 427 | 428 | count++; 429 | if (count >= 9) { 430 | break; 431 | } 432 | } 433 | 434 | recordHashItem(depth, alpha, flag); 435 | return alpha; 436 | 437 | } 438 | 439 | 440 | //获得下一步的走法 441 | Position getAGoodMove(int chessBoard[BOARD_WIDTH][BOARD_WIDTH]) { 442 | int score = abSearch(chessBoard, DEPTH, MIN_SCORE, MAX_SCORE, COMPUTOR); 443 | if (score >= MAX_SCORE - 1000 - 1) { 444 | winner = COMPUTOR; 445 | } 446 | else if (score <= MIN_SCORE + 1000 + 1) { 447 | winner = HUMAN; 448 | } 449 | return searchResult; 450 | } 451 | 452 | 453 | 454 | //初始化函数,插入特征和分值 455 | void init() { 456 | assert(paterns.size() == paternScores.size()); 457 | 458 | //初始化ACSearcher 459 | acs.LoadPatern(paterns); 460 | acs.BuildGotoTable(); 461 | acs.BuildFailTable(); 462 | 463 | randomBoardZobristValue(); 464 | currentZobristValue = random64(); 465 | winner = -1;//刚开始没有胜者 466 | } 467 | 468 | //输出棋盘 469 | void printBoard(int chessBoard[BOARD_WIDTH][BOARD_WIDTH]) { 470 | int i, j; 471 | for (i = 0; i < BOARD_WIDTH; i++) { 472 | for (j = 0; j < BOARD_WIDTH; j++) { 473 | cout << (int)chessBoard[i][j] << " "; 474 | } 475 | cout << endl; 476 | } 477 | } 478 | 479 | 480 | 481 | ////以下是对外接口的实现 482 | 483 | //在开始之前,一些初始化工作 484 | void beforeStart() { 485 | memset(chessBoard, EMPTY, BOARD_WIDTH * BOARD_WIDTH * sizeof(int)); 486 | memset(scores, 0, sizeof(scores)); 487 | init(); 488 | } 489 | 490 | //判断是否是某一方赢了 491 | int isSomeOneWin() { 492 | if (winner == HUMAN) 493 | return 0; 494 | if (winner == COMPUTOR) 495 | return 1; 496 | 497 | return -1; 498 | } 499 | 500 | //悔棋 501 | string takeBack() { 502 | if (moves.size() < 2) { 503 | cout << "can not take back" << endl; 504 | 505 | string resultStr; 506 | int i, j; 507 | for (i = 0; i < BOARD_WIDTH; i++) { 508 | for (j = 0; j < BOARD_WIDTH; j++) { 509 | resultStr.push_back(chessBoard[i][j] + 48); 510 | } 511 | } 512 | 513 | printBoard(chessBoard); 514 | 515 | return resultStr; 516 | } 517 | 518 | 519 | Position previousPosition = moves.top(); 520 | moves.pop(); 521 | currentZobristValue ^= boardZobristValue[COMPUTOR - 1][previousPosition.x][previousPosition.y]; 522 | chessBoard[previousPosition.x][previousPosition.y] = EMPTY; 523 | updateScore(chessBoard, previousPosition); 524 | 525 | 526 | previousPosition = moves.top(); 527 | moves.pop(); 528 | currentZobristValue ^= boardZobristValue[HUMAN - 1][previousPosition.x][previousPosition.y]; 529 | chessBoard[previousPosition.x][previousPosition.y] = EMPTY; 530 | updateScore(chessBoard, previousPosition); 531 | 532 | ppm.Rollback(); 533 | ppm.Rollback(); 534 | 535 | string resultStr; 536 | int i, j; 537 | for (i = 0; i < BOARD_WIDTH; i++) { 538 | for (j = 0; j < BOARD_WIDTH; j++) { 539 | resultStr.push_back(chessBoard[i][j] + 48); 540 | } 541 | } 542 | 543 | printBoard(chessBoard); 544 | 545 | winner = -1; 546 | 547 | return resultStr; 548 | 549 | } 550 | 551 | //清除之前的记录,重新开局 552 | string reset(int role) { 553 | char chs[15 * 15 + 1]; 554 | memset(chs, '0', 15 * 15); 555 | memset(scores, 0, sizeof(scores)); 556 | memset(allScore, 0, sizeof(allScore)); 557 | 558 | winner = -1; 559 | //初始化局面总分数为0 560 | 561 | while (!moves.empty()) { 562 | moves.pop(); 563 | } 564 | 565 | int i; 566 | for (i = 0; i < HASH_ITEM_INDEX_MASK + 1; i++) { 567 | hashItems[i].flag = HashItem::EMPTY; 568 | } 569 | 570 | //初始化棋盘 571 | memset(chessBoard, EMPTY, BOARD_WIDTH * BOARD_WIDTH * sizeof(int)); 572 | 573 | //清楚上一局可能出现的位置 574 | ppm.RemoveAll(); 575 | 576 | //用户先走 577 | if (role == 0) { 578 | // do nothing 579 | } 580 | //电脑先走 581 | else if (role == 1) { 582 | currentZobristValue ^= boardZobristValue[COMPUTOR - 1][7][7]; 583 | chessBoard[7][7] = COMPUTOR; 584 | updateScore(chessBoard, Position(7, 7)); 585 | 586 | moves.push(Position(7, 7)); 587 | searchResult = Position(7, 7); 588 | 589 | ppm.AddPossiblePositions(chessBoard, Position(7, 7)); 590 | 591 | //第一步默认走7,7的位置 592 | chs[7 + 7 * 15] = '2'; 593 | } 594 | 595 | winner = -1; 596 | 597 | return string(chs); 598 | } 599 | 600 | //重新设置层数 601 | void setLevel(int level) { 602 | DEPTH = level; 603 | } 604 | 605 | //取得刚才电脑下得那一步棋子的位置 606 | Position getLastPosition() { 607 | return searchResult; 608 | } 609 | 610 | //人类下棋,返回棋盘,传给界面 611 | string nextStep(int &x, int &y ) { 612 | ChessAI cc; 613 | bool winFlag = false; 614 | 615 | 616 | moves.push(Position(x, y)); 617 | chessBoard[x][y] = HUMAN; 618 | 619 | currentZobristValue ^= boardZobristValue[HUMAN - 1][x][y]; 620 | updateScore(chessBoard, Position(x, y)); 621 | 622 | ppm.AddPossiblePositions(chessBoard, Position(x, y)); 623 | cc.chess_ai_killcount(x,y,winFlag,16); 624 | //cout<<"$$$"<ChessEngine::evaluatePoint(chessBoard,ChessEngine::Position(result.x,result.y))){ 638 | result.x = killX; 639 | result.y = killY; 640 | } 641 | } 642 | searchResult = result; 643 | //chessBoard[result.y][result.x] = COMPUTOR; 644 | //cout<<"###"< 5 | using namespace std; 6 | 7 | int isover; 8 | int myturn; 9 | int backnum,whitenum; 10 | int preWx,preWy; 11 | int preBx,preBy; 12 | bool winFlag = false; 13 | int countWhoFirst = -1; 14 | int countPlayer1Use = -1; 15 | bool isFirstStep = true; 16 | int gameMode; 17 | extern bool gameState; 18 | extern void gameover(int, int); 19 | int chessBoard[15][15];//棋盘 20 | vectorscore1; 21 | vectorscore2; 22 | 23 | Chess::Chess(QWidget *parent) : 24 | QWidget(parent), 25 | ui(new Ui::Chess) 26 | { 27 | ui->setupUi(this); 28 | //初始化为0,1为白子,2为黑子。 29 | //memeset函数只能对连续的内存空间初始化,new在堆上分的内存可能会不连续。 30 | for(int i = 0; i <15;i++){ 31 | for(int j = 0; j<15 ;j++){ 32 | chessBoard[i][j] = 0; 33 | } 34 | } 35 | cout<<"haha"; 36 | setMouseTracking(true); 37 | step = 0;//步数初始化为0 38 | whoWin = 0;//赢家判断标志初始化为0 39 | ChessEngine::beforeStart(); 40 | ChessEngine::setLevel(9); 41 | } 42 | 43 | Chess::~Chess() 44 | { 45 | delete ui; 46 | countWhoFirst = 0; 47 | } 48 | 49 | void Chess::paintEvent(QPaintEvent *)//绘制事件 50 | { 51 | QPainter *paint=new QPainter; 52 | paint->begin(this);//开始绘制 53 | paint->setRenderHint(QPainter::Antialiasing, true);//抗锯齿 54 | paint->setPen(QPen(Qt::black,2,Qt::SolidLine)); 55 | paint->fillRect(QRect(10,10,590,590), QBrush(QColor(215,156,80))); 56 | 57 | //绘制棋盘线条 58 | for(int i = 0;i<15;i++){ 59 | paint->drawLine(25+40*i,25,25+40*i,585); 60 | } 61 | for(int i = 0;i<15 ;i++){ 62 | paint->drawLine(25,25+40*i,585,25+40*i); 63 | } 64 | 65 | //绘制五个棋盘黑点 66 | QBrush *brush = new QBrush(); 67 | brush->setStyle(Qt::SolidPattern); 68 | brush->setColor(Qt::black); 69 | paint->setBrush(*brush); 70 | paint->drawRect(140,140,10,10); 71 | paint->drawRect(460,460,10,10); 72 | paint->drawRect(140,460,10,10); 73 | paint->drawRect(460,140,10,10); 74 | paint->drawRect(300,300,10,10); 75 | 76 | //test 77 | /* 78 | chessBoard[0][0] = 2; 79 | chessBoard[8][8] = 1; 80 | chessBoard[11][8] = 1; 81 | chessBoard[14][8] = 1; 82 | chessBoard[7][2] = 1;*/ 83 | 84 | //绘制棋子 85 | if(gameMode == 1){ 86 | for(int i = 0; i < 15;i++){ 87 | for(int j = 0; j< 15 ;j++){ 88 | if(chessBoard[i][j] == 2){//黑子 89 | brush->setColor(Qt::black); 90 | paint->setPen(Qt::NoPen); 91 | paint->setBrush(*brush); 92 | paint->drawEllipse(11+j*40,11+i*40,28,28); 93 | } 94 | else if(chessBoard[i][j] == 1){//白子 95 | brush->setColor(Qt::white); 96 | paint->setPen(QPen(Qt::black,2,Qt::SolidLine)); 97 | paint->setBrush(*brush); 98 | paint->drawEllipse(11+j*40,11+i*40,28,28); 99 | } 100 | } 101 | } 102 | } 103 | else if(gameMode == 2){ 104 | if((countWhoFirst == 0 && countPlayer1Use == 0)||(countWhoFirst == 1 && countPlayer1Use == 0)){ 105 | for(int i = 0; i < 15;i++){ 106 | for(int j = 0; j< 15 ;j++){ 107 | if(chessBoard[i][j] == 1){//黑子 108 | brush->setColor(Qt::black); 109 | paint->setPen(Qt::NoPen); 110 | paint->setBrush(*brush); 111 | paint->drawEllipse(11+j*40,11+i*40,28,28); 112 | } 113 | else if(chessBoard[i][j] == 2){//白子 114 | brush->setColor(Qt::white); 115 | paint->setPen(QPen(Qt::black,2,Qt::SolidLine)); 116 | paint->setBrush(*brush); 117 | paint->drawEllipse(11+j*40,11+i*40,28,28); 118 | } 119 | } 120 | } 121 | } 122 | else{ 123 | for(int i = 0; i < 15;i++){ 124 | for(int j = 0; j< 15 ;j++){ 125 | if(chessBoard[i][j] == 2){//黑子 126 | brush->setColor(Qt::black); 127 | paint->setPen(Qt::NoPen); 128 | paint->setBrush(*brush); 129 | paint->drawEllipse(11+j*40,11+i*40,28,28); 130 | } 131 | else if(chessBoard[i][j] == 1){//白子 132 | brush->setColor(Qt::white); 133 | paint->setPen(QPen(Qt::black,2,Qt::SolidLine)); 134 | paint->setBrush(*brush); 135 | paint->drawEllipse(11+j*40,11+i*40,28,28); 136 | } 137 | } 138 | } 139 | } 140 | } 141 | QPen *pen = new QPen(Qt::red); 142 | pen->setWidth(2); 143 | paint->setPen(*pen); 144 | if(step!=0){ 145 | paint->drawLine(preY*40+25-10,preX*40+25,preY*40+25+10,preX*40+25); 146 | paint->drawLine(preY*40+25,preX*40+25-10,preY*40+25,preX*40+25+10); 147 | } 148 | 149 | 150 | if(moveX*40+25 >=20 && moveX*40 +25 <= 600 && moveY*40+25 >=20 && moveY*40 +25 <= 600 && getChessBoard(moveX,moveY)==0){ 151 | 152 | // paint->drawRect(moveX*40+25-15,moveY*40+25-15,30,30); 153 | paint->drawLine(moveX*40+25-15,moveY*40+25-15,moveX*40+25-5,moveY*40+25-15); 154 | paint->drawLine(moveX*40+25-15,moveY*40+25-15,moveX*40+25-15,moveY*40+25-5); 155 | paint->drawLine(moveX*40+25+15,moveY*40+25+15,moveX*40+25+5,moveY*40+25+15); 156 | paint->drawLine(moveX*40+25+15,moveY*40+25+15,moveX*40+25+15,moveY*40+25+5); 157 | 158 | paint->drawLine(moveX*40+25-15,moveY*40+25+15,moveX*40+25-5,moveY*40+25+15); 159 | paint->drawLine(moveX*40+25-15,moveY*40+25+15,moveX*40+25-15,moveY*40+25+5); 160 | paint->drawLine(moveX*40+25+15,moveY*40+25-15,moveX*40+25+5,moveY*40+25-15); 161 | paint->drawLine(moveX*40+25+15,moveY*40+25-15,moveX*40+25+15,moveY*40+25-5); 162 | } 163 | 164 | 165 | paint->end();//结束绘制 166 | 167 | } 168 | 169 | void Chess::mouseMoveEvent(QMouseEvent *event) { 170 | moveX = (event->x()-5)/40; 171 | moveY = (event->y()-5)/40; 172 | update(); 173 | } 174 | 175 | void Chess::mouseReleaseEvent(QMouseEvent* event){ 176 | if(gameState == true){ 177 | moveY = (event->x()-5)/40; 178 | moveX = (event->y()-5)/40; 179 | if(chessBoard[moveX][moveY] == 0){ 180 | if(gameMode == 1){//pvp 181 | if((step + countWhoFirst )%2 == 0){ 182 | //黑子回合 183 | step++; 184 | chessBoard[moveX][moveY] = 2; 185 | cout<processEvents(QEventLoop::ExcludeUserInputEvents);//它可以忽略用户的输入(鼠标和键盘事件) 248 | ChessEngine::nextStep(moveX,moveY); 249 | chessBoard[moveX][moveY] = 2; 250 | qApp->processEvents(QEventLoop::ExcludeUserInputEvents);//它可以忽略用户的输入(鼠标和键盘事件) 251 | step++; 252 | addChessBoardXY(moveX,moveY); 253 | emit start_emit(step,ChessEngine::evaluate(chessBoard,1),ChessEngine::evaluate(chessBoard,2)); 254 | score1.push_back(ChessEngine::evaluate(chessBoard,1)); 255 | score2.push_back(ChessEngine::evaluate(chessBoard,2)); 256 | if(isWin(moveX,moveY)== true){//满足胜利条件 257 | whoWin = 2;//电脑获胜 258 | qDebug("%d %d",gameMode,whoWin); 259 | gameOver(gameMode,whoWin); 260 | } 261 | else if(step == 255){//平局 262 | gameOver(gameMode,3); 263 | } 264 | } 265 | qDebug("score:%d",ChessEngine::evaluate(chessBoard,2)); 266 | preX = moveX; 267 | preY = moveY; 268 | } 269 | 270 | else if(countPlayer1Use == 1){//黑子先手 白子玩家 271 | qDebug("sssssscore:%d",countPlayer1Use); 272 | chessBoard[moveX][moveY] = 1; 273 | addChessBoardXY(moveX,moveY); 274 | step++; 275 | emit start_emit(step,ChessEngine::evaluate(chessBoard,2),ChessEngine::evaluate(chessBoard,1)); 276 | score1.push_back(ChessEngine::evaluate(chessBoard,1)); 277 | score2.push_back(ChessEngine::evaluate(chessBoard,2)); 278 | repaint(); 279 | if(isWin(moveX,moveY)== true){//满足胜利条件 280 | whoWin = 1;//玩家获胜 281 | qDebug("%d %d",gameMode,whoWin); 282 | gameOver(gameMode,whoWin); 283 | } 284 | else if(step == 255){//平局 285 | gameOver(gameMode,3); 286 | } 287 | 288 | if(gameState){ 289 | qApp->processEvents(QEventLoop::ExcludeUserInputEvents);//它可以忽略用户的输入(鼠标和键盘事件) 290 | ChessEngine::nextStep(moveX,moveY); 291 | chessBoard[moveX][moveY] = 2; 292 | qApp->processEvents(QEventLoop::ExcludeUserInputEvents);//它可以忽略用户的输入(鼠标和键盘事件) 293 | step++; 294 | addChessBoardXY(moveX,moveY); 295 | emit start_emit(step,ChessEngine::evaluate(chessBoard,2),ChessEngine::evaluate(chessBoard,1)); 296 | score1.push_back(ChessEngine::evaluate(chessBoard,1)); 297 | score2.push_back(ChessEngine::evaluate(chessBoard,2)); 298 | if(isWin(moveX,moveY)== true){//满足胜利条件 299 | whoWin = 2;//电脑获胜 300 | qDebug("%d %d",gameMode,whoWin); 301 | gameOver(gameMode,whoWin); 302 | } 303 | else if(step == 255){//平局 304 | gameOver(gameMode,3); 305 | } 306 | } 307 | preX = moveX; 308 | preY = moveY; 309 | } 310 | } 311 | else if(countWhoFirst == 1) { 312 | if(countPlayer1Use == 1){//白子先手 白子玩家 313 | chessBoard[moveX][moveY] = 1; 314 | addChessBoardXY(moveX,moveY); 315 | step++; 316 | emit start_emit(step,ChessEngine::evaluate(chessBoard,2),ChessEngine::evaluate(chessBoard,1)); 317 | score1.push_back(ChessEngine::evaluate(chessBoard,1)); 318 | score2.push_back(ChessEngine::evaluate(chessBoard,2)); 319 | repaint(); 320 | if(isWin(moveX,moveY)== true){//满足胜利条件 321 | whoWin = 1;//玩家获胜 322 | qDebug("%d %d",gameMode,whoWin); 323 | gameOver(gameMode,whoWin); 324 | 325 | } 326 | else if(step == 255){//平局 327 | gameOver(gameMode,3); 328 | } 329 | if(gameState){ 330 | qApp->processEvents(QEventLoop::ExcludeUserInputEvents);//它可以忽略用户的输入(鼠标和键盘事件) 331 | ChessEngine::nextStep(moveX,moveY); 332 | chessBoard[moveX][moveY] = 2; 333 | qApp->processEvents(QEventLoop::ExcludeUserInputEvents);//它可以忽略用户的输入(鼠标和键盘事件) 334 | step++; 335 | addChessBoardXY(moveX,moveY); 336 | emit start_emit(step,ChessEngine::evaluate(chessBoard,2),ChessEngine::evaluate(chessBoard,1)); 337 | score1.push_back(ChessEngine::evaluate(chessBoard,1)); 338 | score2.push_back(ChessEngine::evaluate(chessBoard,2)); 339 | if(isWin(moveX,moveY)== true){//满足胜利条件 340 | whoWin = 2;//电脑获胜 341 | qDebug("%d %d",gameMode,whoWin); 342 | gameOver(gameMode,whoWin); 343 | 344 | } 345 | else if(step == 255){//平局 346 | gameOver(gameMode,3); 347 | } 348 | } 349 | preX = moveX; 350 | preY = moveY; 351 | } 352 | else if(countPlayer1Use == 0){//白子先手 黑子玩家 353 | chessBoard[moveX][moveY] = 1; 354 | addChessBoardXY(moveX,moveY); 355 | step++; 356 | emit start_emit(step,ChessEngine::evaluate(chessBoard,1),ChessEngine::evaluate(chessBoard,2)); 357 | score1.push_back(ChessEngine::evaluate(chessBoard,1)); 358 | score2.push_back(ChessEngine::evaluate(chessBoard,2)); 359 | repaint(); 360 | if(isWin(moveX,moveY)== true){//满足胜利条件 361 | whoWin = 1;//玩家获胜 362 | qDebug("%d %d",gameMode,whoWin); 363 | gameOver(gameMode,whoWin); 364 | 365 | } 366 | else if(step == 255){//平局 367 | gameOver(gameMode,3); 368 | } 369 | if(gameState){ 370 | qApp->processEvents(QEventLoop::ExcludeUserInputEvents);//它可以忽略用户的输入(鼠标和键盘事件) 371 | ChessEngine::nextStep(moveX,moveY); 372 | chessBoard[moveX][moveY] = 2; 373 | qApp->processEvents(QEventLoop::ExcludeUserInputEvents);//它可以忽略用户的输入(鼠标和键盘事件) 374 | step++; 375 | addChessBoardXY(moveX,moveY); 376 | emit start_emit(step,ChessEngine::evaluate(chessBoard,1),ChessEngine::evaluate(chessBoard,2)); 377 | score1.push_back(ChessEngine::evaluate(chessBoard,1)); 378 | score2.push_back(ChessEngine::evaluate(chessBoard,2)); 379 | if(isWin(moveX,moveY)== true){//满足胜利条件 380 | whoWin = 2;//电脑获胜 381 | qDebug("%d %d",gameMode,whoWin); 382 | gameOver(gameMode,whoWin); 383 | } 384 | else if(step == 255){//平局 385 | gameOver(gameMode,3); 386 | } 387 | 388 | } 389 | } 390 | preX = moveX; 391 | preY = moveY; 392 | } 393 | 394 | update(); 395 | } 396 | } 397 | 398 | 399 | } 400 | } 401 | 402 | 403 | 404 | int Chess::getChessBoard(int x,int y){ 405 | return chessBoard[x][y]; 406 | } 407 | 408 | void Chess::setChessBoard(int x,int y,int value){ 409 | if(x >= 0 && x < 15 && y >= 0 && y < 15 && value<= 2 && value >= 0){ 410 | chessBoard[x][y] = value; 411 | } 412 | } 413 | 414 | bool Chess:: deleteChessBoardXY(){ 415 | if(chessBoardX.empty() || chessBoardY.empty()){ 416 | return false; 417 | } 418 | else{ 419 | chessBoard[chessBoardX.back()][chessBoardY.back()] = 0; 420 | 421 | if(gameMode == 1){ 422 | step--; 423 | emit start_emit(step,0,0); 424 | } 425 | else{ 426 | if(step - 2 >= 0){ 427 | step = step-2; 428 | } 429 | score1.pop_back(); 430 | score2.pop_back(); 431 | if(!score1.empty() && !score2.empty()){ 432 | if(countPlayer1Use == 0){ 433 | emit start_emit(step,score1.back(),score2.back()); 434 | } 435 | else if(countPlayer1Use == 1){ 436 | emit start_emit(step,score2.back(),score1.back()); 437 | } 438 | } 439 | } 440 | 441 | chessBoardX.pop_back(); 442 | chessBoardY.pop_back(); 443 | preX = chessBoardX.back(); 444 | preY = chessBoardY.back(); 445 | return true; 446 | } 447 | } 448 | 449 | void Chess::clearChessBoard(){ 450 | chessBoardX.clear(); 451 | chessBoardY.clear(); 452 | score1.clear(); 453 | score2.clear(); 454 | for(int i = 0; i < 15 ;i++){ 455 | for(int j = 0; j < 15 ;j++){ 456 | setChessBoard(i,j,0); 457 | } 458 | } 459 | step = 0; 460 | } 461 | 462 | void Chess::addChessBoardXY(int x,int y){ 463 | chessBoardX.push_back(x); 464 | chessBoardY.push_back(y); 465 | } 466 | 467 | void Chess::setStep(int step){ 468 | this->step = step; 469 | } 470 | 471 | int Chess::getStep(){ 472 | return this->step; 473 | } 474 | 475 | void Chess::setWhoWin(int num){ 476 | this->whoWin = num; 477 | } 478 | 479 | bool Chess::isWin(int row, int col) 480 | { 481 | // 横竖斜四种大情况,每种情况都根据当前落子往后遍历5个棋子,有一种符合就算赢 482 | // 水平方向 483 | for (int i = 0; i < 5; i++) 484 | { 485 | // 往左5个,往右匹配4个子,20种情况 486 | if (col - i >= 0 && 487 | col - i + 4 < 15 && 488 | getChessBoard(row,col - i) == getChessBoard(row,col - i + 1) && 489 | getChessBoard(row,col - i) == getChessBoard(row,col - i + 2) && 490 | getChessBoard(row,col - i) == getChessBoard(row,col - i + 3) && 491 | getChessBoard(row,col - i) == getChessBoard(row,col - i + 4)) 492 | return true; 493 | } 494 | 495 | // 竖直方向(上下延伸4个) 496 | for (int i = 0; i < 5; i++) 497 | { 498 | if (row - i >= 0 && 499 | row - i + 4 < 15 && 500 | getChessBoard(row - i,col) == getChessBoard(row - i + 1,col) && 501 | getChessBoard(row - i,col) == getChessBoard(row - i + 2,col) && 502 | getChessBoard(row - i,col) == getChessBoard(row - i + 3,col) && 503 | getChessBoard(row - i,col) == getChessBoard(row - i + 4,col)) 504 | return true; 505 | } 506 | 507 | // 左斜方向 508 | for (int i = 0; i < 5; i++) 509 | { 510 | if (row + i <15 && 511 | row + i - 4 >= 0 && 512 | col - i >= 0 && 513 | col - i + 4 < 15 && 514 | getChessBoard(row + i,col - i) == getChessBoard(row + i - 1,col - i + 1) && 515 | getChessBoard(row + i,col - i) == getChessBoard(row + i - 2,col - i + 2) && 516 | getChessBoard(row + i,col - i) == getChessBoard(row + i - 3,col - i + 3) && 517 | getChessBoard(row + i,col - i) == getChessBoard(row + i - 4,col - i + 4)) 518 | return true; 519 | } 520 | 521 | // 右斜方向 522 | for (int i = 0; i < 5; i++) 523 | { 524 | if (row - i >= 0 && 525 | row - i + 4 < 15 && 526 | col - i >= 0 && 527 | col - i + 4 < 15 && 528 | getChessBoard(row - i,col - i) == getChessBoard(row - i + 1,col - i + 1) && 529 | getChessBoard(row - i,col - i) == getChessBoard(row - i + 2,col - i + 2) && 530 | getChessBoard(row - i,col - i) == getChessBoard(row - i + 3,col - i + 3) && 531 | getChessBoard(row - i,col - i) == getChessBoard(row - i + 4,col - i + 4)) 532 | return true; 533 | } 534 | 535 | return false; 536 | } 537 | 538 | void Chess::gameOver(int gameMode , int whoWin){ 539 | if(whoWin == 1){ 540 | //玩家1胜利 541 | if(gameMode == 1){//pvp 542 | DialogGameOver *dialogGameOver = new DialogGameOver(this); 543 | dialogGameOver->setLabelText(QString("玩家1获胜!")); 544 | dialogGameOver->show(); 545 | } 546 | else if(gameMode == 2){//pvm 547 | DialogGameOver *dialogGameOver = new DialogGameOver(this); 548 | dialogGameOver->setLabelText(QString("玩家获胜!")); 549 | dialogGameOver->show(); 550 | } 551 | } 552 | else if(whoWin == 2){ 553 | //玩家2胜利 554 | if(gameMode == 1){//pvp 555 | DialogGameOver *dialogGameOver = new DialogGameOver(this); 556 | dialogGameOver->setLabelText(QString("玩家2获胜!")); 557 | dialogGameOver->show(); 558 | } 559 | else if(gameMode == 2){//pvm 560 | DialogGameOver *dialogGameOver = new DialogGameOver(this); 561 | dialogGameOver->setLabelText(QString("电脑获胜!")); 562 | dialogGameOver->show(); 563 | } 564 | } 565 | else if(whoWin == 3){ 566 | //平局 567 | DialogGameOver *dialogGameOver = new DialogGameOver(); 568 | dialogGameOver->setLabelText(QString("平局!")); 569 | } 570 | gameState = false; 571 | } 572 | 573 | 574 | 575 | 576 | -------------------------------------------------------------------------------- /RicardoGoBang/RicardoGoBang.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {7851c84a-d43c-41af-bd01-62b29f6f2e32} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | true 41 | false 42 | 0 43 | true 44 | true 45 | 0 46 | 8 47 | true 48 | 1 49 | true 50 | true 51 | true 52 | false 53 | 54 | 55 | 56 | ProjectExplorer.Project.PluginSettings 57 | 58 | 59 | 60 | ProjectExplorer.Project.Target.0 61 | 62 | Desktop Qt 5.10.1 clang 64bit 63 | Desktop Qt 5.10.1 clang 64bit 64 | qt.qt5.5101.clang_64_kit 65 | 1 66 | 0 67 | 0 68 | 69 | /Users/apple/RicardoGoBang/build-RicardoGoBang-Desktop_Qt_5_10_1_clang_64bit-Debug 70 | 71 | 72 | true 73 | qmake 74 | 75 | QtProjectManager.QMakeBuildStep 76 | true 77 | 78 | false 79 | false 80 | false 81 | 82 | 83 | true 84 | Make 85 | 86 | Qt4ProjectManager.MakeStep 87 | 88 | -w 89 | -r 90 | 91 | false 92 | 93 | 94 | 95 | 2 96 | 构建 97 | 98 | ProjectExplorer.BuildSteps.Build 99 | 100 | 101 | 102 | true 103 | Make 104 | 105 | Qt4ProjectManager.MakeStep 106 | 107 | -w 108 | -r 109 | 110 | true 111 | clean 112 | 113 | 114 | 1 115 | 清理 116 | 117 | ProjectExplorer.BuildSteps.Clean 118 | 119 | 2 120 | false 121 | 122 | Debug 123 | 124 | Qt4ProjectManager.Qt4BuildConfiguration 125 | 2 126 | true 127 | 128 | 129 | /Users/apple/RicardoGoBang/release 130 | 131 | 132 | true 133 | qmake 134 | 135 | QtProjectManager.QMakeBuildStep 136 | false 137 | 138 | false 139 | false 140 | false 141 | 142 | 143 | true 144 | Make 145 | 146 | Qt4ProjectManager.MakeStep 147 | 148 | -w 149 | -r 150 | 151 | false 152 | 153 | 154 | 155 | 2 156 | 构建 157 | 158 | ProjectExplorer.BuildSteps.Build 159 | 160 | 161 | 162 | true 163 | Make 164 | 165 | Qt4ProjectManager.MakeStep 166 | 167 | -w 168 | -r 169 | 170 | true 171 | clean 172 | 173 | 174 | 1 175 | 清理 176 | 177 | ProjectExplorer.BuildSteps.Clean 178 | 179 | 2 180 | false 181 | 182 | Release 183 | 184 | Qt4ProjectManager.Qt4BuildConfiguration 185 | 0 186 | true 187 | 188 | 189 | /Users/apple/RicardoGoBang/build-RicardoGoBang-Desktop_Qt_5_10_1_clang_64bit-Profile 190 | 191 | 192 | true 193 | qmake 194 | 195 | QtProjectManager.QMakeBuildStep 196 | true 197 | 198 | false 199 | true 200 | false 201 | 202 | 203 | true 204 | Make 205 | 206 | Qt4ProjectManager.MakeStep 207 | 208 | -w 209 | -r 210 | 211 | false 212 | 213 | 214 | 215 | 2 216 | 构建 217 | 218 | ProjectExplorer.BuildSteps.Build 219 | 220 | 221 | 222 | true 223 | Make 224 | 225 | Qt4ProjectManager.MakeStep 226 | 227 | -w 228 | -r 229 | 230 | true 231 | clean 232 | 233 | 234 | 1 235 | 清理 236 | 237 | ProjectExplorer.BuildSteps.Clean 238 | 239 | 2 240 | false 241 | 242 | Profile 243 | 244 | Qt4ProjectManager.Qt4BuildConfiguration 245 | 0 246 | true 247 | 248 | 3 249 | 250 | 251 | 0 252 | 部署 253 | 254 | ProjectExplorer.BuildSteps.Deploy 255 | 256 | 1 257 | 在本地部署 258 | 259 | ProjectExplorer.DefaultDeployConfiguration 260 | 261 | 1 262 | 263 | 264 | false 265 | false 266 | 1000 267 | 268 | true 269 | 270 | false 271 | false 272 | false 273 | false 274 | true 275 | 0.01 276 | 10 277 | true 278 | 1 279 | 25 280 | 281 | 1 282 | true 283 | false 284 | true 285 | valgrind 286 | 287 | 0 288 | 1 289 | 2 290 | 3 291 | 4 292 | 5 293 | 6 294 | 7 295 | 8 296 | 9 297 | 10 298 | 11 299 | 12 300 | 13 301 | 14 302 | 303 | 2 304 | 305 | RicardoGoBang 306 | 307 | Qt4ProjectManager.Qt4RunConfiguration:/Users/apple/RicardoGoBang/RicardoGoBang/RicardoGoBang.pro 308 | true 309 | 310 | RicardoGoBang.pro 311 | false 312 | 313 | /Users/apple/RicardoGoBang/release/RicardoGoBang.app/Contents/MacOS 314 | 3768 315 | false 316 | true 317 | false 318 | false 319 | true 320 | 321 | 1 322 | 323 | 324 | 325 | ProjectExplorer.Project.TargetCount 326 | 1 327 | 328 | 329 | ProjectExplorer.Project.Updater.FileVersion 330 | 18 331 | 332 | 333 | Version 334 | 18 335 | 336 | 337 | --------------------------------------------------------------------------------