From b95e6b276b40faafd3b22e4261def5dd38ca1c56 Mon Sep 17 00:00:00 2001 From: liuweilhy Date: Sun, 10 Jun 2018 01:47:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=91=BD=E4=BB=A4=E8=A1=8C?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E5=92=8C=E7=94=9F=E6=88=90=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Licence.txt | 4 +- NineChess/ninechess.vcxproj | 6 +- NineChess/src/gamecontroller.cpp | 50 +++++++----- NineChess/src/gamecontroller.h | 9 ++- NineChess/src/ninechess.cpp | 122 ++++++++++++++++++++++++------ NineChess/src/ninechess.h | 47 ++++++------ NineChess/src/ninechesswindow.cpp | 56 +++++++++----- NineChess/src/ninechesswindow.h | 5 ++ 8 files changed, 209 insertions(+), 90 deletions(-) diff --git a/Licence.txt b/Licence.txt index b88b4f01..a931f7d5 100644 --- a/Licence.txt +++ b/Licence.txt @@ -1,10 +1,10 @@ -本软件代码遵循LGPL协议,其中: +本软件代码遵循LGPL v3协议,其中: 1. 对于Qt库,遵循GPL协议。任何人都可以免费使用,但必须保持其开源; 2. 对于原作者自行开发的代码: 2.1 未经原作者书面授权,任何人不得修改、传播; 2.2 获得原作者书面授权免费使用者: 2.2.1 其修改版必须对原作者开源; - 2.2.2 其修改版必须完整保留本Licence文件,如需新增内容,只能在原版Licence文件末尾追加; + 2.2.2 其修改版必须完整保留本Licence文件,如需新增内容,只能在原版Licence文件中追加; 2.2.3 原作者对其修改版在保留修改者署名情况下,有修改、传播及无偿商业化使用的权利; 2.3 获得原作者书面授权收费使用者,按照双方书面协议执行。 diff --git a/NineChess/ninechess.vcxproj b/NineChess/ninechess.vcxproj index 4ae1ba4c..53151cf3 100644 --- a/NineChess/ninechess.vcxproj +++ b/NineChess/ninechess.vcxproj @@ -109,7 +109,7 @@ $(QTDIR) .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - UNICODE;_UNICODE;WIN32;WIN64;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_CORE_LIB + _WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_CORE_LIB;NDEBUG;%(PreprocessorDefinitions) msvc $(Configuration)/moc_predefs.h Moc'ing %(Identity)... @@ -161,7 +161,7 @@ true $(OutDir)\NineChess.exe true - Windows + Console true @@ -183,7 +183,7 @@ $(QTDIR) .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - UNICODE;_UNICODE;WIN32;WIN64;QT_MULTIMEDIA_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_CORE_LIB + _WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;QT_MULTIMEDIA_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) msvc $(Configuration)/moc_predefs.h Moc'ing %(Identity)... diff --git a/NineChess/src/gamecontroller.cpp b/NineChess/src/gamecontroller.cpp index 98accb2b..ade82c81 100644 --- a/NineChess/src/gamecontroller.cpp +++ b/NineChess/src/gamecontroller.cpp @@ -69,8 +69,11 @@ const QMap GameController::getActions() void GameController::gameStart() { + chess.start(); // 每隔100毫秒调用一次定时器处理函数 - timeID = startTimer(100); + if (timeID == 0) { + timeID = startTimer(100); + } } void GameController::gameReset() @@ -147,14 +150,11 @@ void GameController::setRule(int ruleNo) timeID = 0; // 更新规则,原限时和限步不变 - struct NineChess::Rule rule; - if (ruleNo >= 0 && ruleNo < NineChess::RULENUM) - rule = NineChess::RULES[ruleNo]; - rule.maxSteps = stepsLimit; - rule.maxTime = timeLimit; - + // 更新规则,原限时和限步不变 + if (ruleNo < 0 || ruleNo >= NineChess::RULENUM) + return; // 设置模型规则,重置游戏 - chess.setRule(&rule); + chess.setData(&NineChess::RULES[ruleNo], stepsLimit, timeLimit); // 清除棋子 qDeleteAll(pieceList); @@ -193,13 +193,12 @@ void GameController::setRule(int ruleNo, int stepLimited, int timeLimited) timeID = 0; // 更新规则,原限时和限步不变 - struct NineChess::Rule rule; - if (ruleNo >= 0 && ruleNo < NineChess::RULENUM) - rule = NineChess::RULES[ruleNo]; - stepsLimit = rule.maxSteps = stepLimited; - timeLimit = rule.maxTime = timeLimited; + if (ruleNo < 0 || ruleNo >= NineChess::RULENUM) + return; + stepsLimit = stepLimited; + timeLimit = timeLimited; // 设置模型规则,重置游戏 - chess.setRule(&rule); + chess.setData(&NineChess::RULES[ruleNo], stepsLimit, timeLimit); // 清除棋子 qDeleteAll(pieceList); @@ -329,7 +328,10 @@ bool GameController::actionPiece(QPointF pos) case NineChess::GAME_NOTSTARTED: // 如果未开局则开局,这里还要继续判断,不可break gameStart(); - chess.start(); + manualListModel.setStringList(QStringList()); + manualListModel.insertRow(0); + manualListModel.setData(manualListModel.index(0), chess.getCmdLine()); + case NineChess::GAME_OPENING: // 如果是开局阶段(轮流落下新子),落子 if (chess.getAction() == NineChess::ACTION_PLACE) { @@ -342,6 +344,7 @@ bool GameController::actionPiece(QPointF pos) if (chess.getPhase() == NineChess::GAME_MID && chess.getRule()->hasForbidden) cleanForbidden(); break; + case NineChess::GAME_MID: // 如果是中局阶段(轮流移子) // 选子 @@ -357,15 +360,28 @@ bool GameController::actionPiece(QPointF pos) result = removePiece(pos); } break; - // 如果是结局状态,不做任何响应 + default: + // 如果是结局状态,不做任何响应 break; } + if (result) { - if (chess.whoWin() != NineChess::NOBODY) + manualListModel.insertRow(manualListModel.rowCount()); + int row = manualListModel.rowCount(); + manualListModel.setData(manualListModel.index(row-1), chess.getCmdLine()); + if (chess.whoWin() != NineChess::NOBODY) { + // 取胜时,会连续出2个命令行,需要将前一个插入 + if (row < chess.getCmdList()->size()) { + manualListModel.insertRow(row-1); + auto i = (chess.getCmdList())->rbegin(); + manualListModel.setData(manualListModel.index(row - 1), (*(++i)).c_str()); + } playSound(soundWin); + } } + return result; } diff --git a/NineChess/src/gamecontroller.h b/NineChess/src/gamecontroller.h index 5448b209..d6da04ad 100644 --- a/NineChess/src/gamecontroller.h +++ b/NineChess/src/gamecontroller.h @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include "gamescene.h" #include "ninechess.h" @@ -28,6 +30,10 @@ public: const QMap getActions(); int getTimeLimit() { return timeLimit; } int getStepsLimit() { return stepsLimit; } + // 文本流 + QTextStream textStream; + // 棋谱字符串列表模型 + QStringListModel manualListModel; signals: // 玩家1(先手)用时改变的信号 @@ -112,8 +118,7 @@ private: int time2; // 用于主窗口状态栏显示的字符串 QString message; - // 文字棋谱 - QStringList manual; + // 各个音效文件路径 QString soundNewgame; QString soundChoose; diff --git a/NineChess/src/ninechess.cpp b/NineChess/src/ninechess.cpp index 8c7bb150..b6aacc98 100644 --- a/NineChess/src/ninechess.cpp +++ b/NineChess/src/ninechess.cpp @@ -117,11 +117,17 @@ NineChess::~NineChess() { } -bool NineChess::setData(const struct Rule *rule, int step, int flags, const char *boardsource, +bool NineChess::setData(const struct Rule *rule, int s, int t, int step, int flags, const char *boardsource, int p1_InHand, int p2_InHand, int num_NeedRemove) { + // 有效性判断 + if (s < 0 || t < 0 || step < 0 || p1_InHand < 0 || p2_InHand < 0 || num_NeedRemove < 0) + return false; + // 根据规则 this->rule = *rule; + this->rule.maxSteps = s; + this->rule.maxTime = t; // 设置步数 this->step = step; // 设置状态 @@ -286,13 +292,10 @@ bool NineChess::setData(const struct Rule *rule, int step, int flags, const char // 用时置零 player1_MS = player2_MS = 0; - setTip(); - return true; -} -bool NineChess::setRule(const struct Rule *rule) -{ - setData(rule); + // 提示 + setTip(); + return true; } @@ -315,15 +318,38 @@ bool NineChess::reset() bool NineChess::start() { + // 如果游戏已经开始,则返回false + if (phase == GAME_OPENING || phase == GAME_MID) + return false; + + // 如果游戏结束,则重置游戏,进入未开始状态 if (phase == GAME_OVER) reset(); - update(); - if (phase == GAME_NOTSTARTED) + + // 如果游戏处于未开始状态 + if (phase == GAME_NOTSTARTED) { phase = GAME_OPENING; - ftime(&startTimeb); - // 用时置零 - player1_MS = player2_MS = 0; - return true; + // 启动计时器 + ftime(&startTimeb); + // 计棋谱 + cmdlist.clear(); + int i; + for (i = 0; i < RULENUM; i++) { + if (strcmp(rule.name, RULES[i].name) == 0) + break; + } + if (sprintf(cmdline, "r%1d s%03d t%02d", i + 1, rule.maxSteps, rule.maxTime) > 0) { + cmdlist.push_back(string(cmdline)); + return true; + } + else { + cmdline[0] = '\0'; + return false; + } + } + + // 其它情况 + return false; } int NineChess::cp2pos(int c, int p) @@ -366,6 +392,8 @@ bool NineChess::place(int c, int p) player2_InHand--; player2_Remain++; } + sprintf(cmdline, "(%1d,%1d)", c, p); + cmdlist.push_back(string(cmdline)); posOfSelected = pos; step++; // 如果决出胜负 @@ -431,11 +459,14 @@ bool NineChess::place(int c, int p) return false; } // 移子 + sprintf(cmdline, "(%1d,%1d)->(%1d,%1d)", posOfSelected / RING, posOfSelected % RING + 1, c, p); + cmdlist.push_back(string(cmdline)); board[pos] = board[posOfSelected]; board[posOfSelected] = '\x00'; posOfSelected = pos; step++; n = addMills(posOfSelected); + // 中局阶段未成三 if (n == 0) { // 进入选子状态 @@ -497,6 +528,8 @@ bool NineChess::remove(int c, int p) player2_Remain--; else if (turn == PLAYER2) player1_Remain--; + sprintf(cmdline, "-(%1d,%1d)", c, p); + cmdlist.push_back(string(cmdline)); posOfSelected = 0; num_NeedRemove--; step++; @@ -597,6 +630,40 @@ bool NineChess::choose(int c, int p) return false; } +// 打算用个C++的命令行解析库的,简单的没必要,但中文编码有极小 +bool NineChess::command(const char *cmd) +{ + int r, s, t; + int c1, p1, c2, p2; + + // 设置规则 + if (sscanf(cmd, "r%d s%d t%d", &r, &s, &t) == 3) { + if (r <= 0 || r > RULENUM) + return false; + return setData(&NineChess::RULES[r - 1], s, t); + } + + // 选子移动 + else if (sscanf(cmd, "(%d,%d)->(%d,%d)", &c1, &p1, &c2, &p2) == 4) { + if (choose(c1, p1)) + return place(c2, p2); + else + return false; + } + + // 去子 + else if (sscanf(cmd, "-(%d,%d)", &c1, &p1) == 2) { + return remove(c1, p1); + } + + // 落子 + else if (sscanf(cmd, "(%d,%d)", &c1, &p1) == 2) { + return place(c1, p1); + } + + return false; +} + inline bool NineChess::update() { // 根据局面调整计时器 @@ -605,7 +672,7 @@ inline bool NineChess::update() case NineChess::GAME_OPENING: case NineChess::GAME_MID: ftime(¤tTimeb); - // 在时间更新时增添一套胜负判断的代码,以免频繁调用win()带来的效率问题 + // 超时胜负判断 if (turn == PLAYER1) { player1_MS = (long)(currentTimeb.time - startTimeb.time) * 1000 + (currentTimeb.millitm - startTimeb.millitm) - player2_MS; @@ -650,8 +717,11 @@ bool NineChess::win() if (rule.maxTime > 0) { // 更新时间,判断胜负 update(); - if (winner != NOBODY) + if (winner != NOBODY) { + sprintf(cmdline, "Time over. Player%1d win!", winner == PLAYER1 ? 1 : 2); + cmdlist.push_back(string(cmdline)); return true; + } } // 如果有步数限定 @@ -659,6 +729,8 @@ bool NineChess::win() if (step > rule.maxSteps) { winner = DRAW; phase = GAME_OVER; + sprintf(cmdline, "Steps over. In draw!"); + cmdlist.push_back(string(cmdline)); return true; } } @@ -667,12 +739,16 @@ bool NineChess::win() if (player1_Remain + player1_InHand < rule.numAtLest) { winner = PLAYER2; phase = GAME_OVER; + sprintf(cmdline, "Player2 win!"); + cmdlist.push_back(string(cmdline)); return true; } // 如果玩家2子数小于赛点,则玩家1获胜 else if (player2_Remain + player2_InHand < rule.numAtLest) { winner = PLAYER1; phase = GAME_OVER; + sprintf(cmdline, "Player1 win!"); + cmdlist.push_back(string(cmdline)); return true; } // 如果摆满了,根据规则判断胜负 @@ -680,12 +756,16 @@ bool NineChess::win() if (rule.isFullLose) { winner = PLAYER2; phase = GAME_OVER; + sprintf(cmdline, "Player2 win!"); + cmdlist.push_back(string(cmdline)); return true; } else { winner = DRAW; phase = GAME_OVER; + sprintf(cmdline, "Full. In draw!"); + cmdlist.push_back(string(cmdline)); return true; } } @@ -696,6 +776,8 @@ bool NineChess::win() if (rule.isNoWayLose) { winner = (turn == PLAYER1) ? PLAYER2 : PLAYER1; phase = GAME_OVER; + sprintf(cmdline, "Surrounded. Player%1d win!", winner == PLAYER1 ? 1 : 2); + cmdlist.push_back(string(cmdline)); return true; } // 否则让棋,由对手走 @@ -709,16 +791,6 @@ bool NineChess::win() return false; } -bool NineChess::command(const char *cmd) -{ - return true; -} - -void NineChess::setCmdline() -{ - -} - int NineChess::isInMills(int pos) { int n = 0; diff --git a/NineChess/src/ninechess.h b/NineChess/src/ninechess.h index 01dce4d1..b26464b9 100644 --- a/NineChess/src/ninechess.h +++ b/NineChess/src/ninechess.h @@ -59,6 +59,7 @@ public: GAME_MID = 0x00000004, // 中局(走棋) GAME_OVER = 0x00000008 // 结局 }; + // 玩家标识,轮流状态,胜负标识 enum Player { PLAYER1 = 0x00000010, // 玩家1 @@ -66,6 +67,7 @@ public: DRAW = 0x00000040, // 双方和棋 NOBODY = 0x00000080 // 胜负未分 }; + // 动作状态标识 enum Actions { ACTION_CHOOSE = 0x00000100, // 选子 @@ -88,15 +90,16 @@ public: ~NineChess(); // 设置棋局状态和棋盘数据,用于初始化 bool setData(const struct Rule *rule, - int step = 0, // 默认起始步数为0 - int flags = GAME_NOTSTARTED | PLAYER1 | ACTION_PLACE | NOBODY, // 默认状态 - const char *boardsource = NULL, // 默认空棋盘 - int p1_InHand = 12, // 玩家1剩余未放置子数 - int p2_InHand = 12, // 玩家2剩余未放置子数 - int num_NeedRemove = 0 // 尚待去除的子数 - ); - // 设置规则 - bool setRule(const struct Rule *rule); + int s = 0, // 限制步数 + int t = 0, // 限制时间 + int step = 0, // 默认起始步数为0 + int flags = GAME_NOTSTARTED | PLAYER1 | ACTION_PLACE | NOBODY, // 默认状态 + const char *boardsource = NULL, // 默认空棋盘 + int p1_InHand = 12, // 玩家1剩余未放置子数 + int p2_InHand = 12, // 玩家2剩余未放置子数 + int num_NeedRemove = 0 // 尚待去除的子数 + ); + // 获取棋局状态和棋盘数据 void getData(struct Rule &rule, int &step, int &flags, const char *&boardsource, int &p1_InHand, int &p2_InHand, int &num_NeedRemove); // 获取当前规则 @@ -111,14 +114,18 @@ public: enum Actions getAction() { return action; } // 判断胜负 enum Player whoWin() { return winner; } - // 获取当前招法 - const char *getCmdline() { return cmdline; } + // 玩家1和玩家2的用时 + void getPlayer_TimeMS(int &p1_ms, int &p2_ms); // 获取棋局的字符提示 const string getTip() { return tip; } // 获取位置点棋子的归属人 enum Player getWhosPiece(int c, int p); // 获取位置点棋子的序号 int getPieceNum(int c, int p); + // 获取当前招法 + const char *getCmdLine() { return cmdline; } + // 获得棋谱 + const list * getCmdList() { return &cmdlist; } // 玩家1剩余未放置子数 int getPlayer1_InHand() { return player1_InHand; } @@ -130,10 +137,8 @@ public: int getPlayer2_Remain() { return player2_Remain; } // 尚待去除的子数 int getNum_NeedRemove() { return num_NeedRemove; } - // 玩家1和玩家2的用时 - void getPlayer_TimeMS(int &p1_ms, int &p2_ms); - // 游戏清空 + // 游戏重置 bool reset(); // 游戏开始 bool start(); @@ -147,8 +152,6 @@ public: bool command(const char *cmd); protected: - // 设置当前招法的命令行指令,即一招棋谱 - void setCmdline(); // 判断棋盘pos处的棋子处于几个“三连”中 int isInMills(int pos); // 判断玩家的所有棋子是否都处于“三连”状态 @@ -214,15 +217,15 @@ private: * 判断棋子是先手的用(board[i] & 0x10) * 判断棋子是后手的用(board[i] & 0x20) */ - char board[(RING+2)*SEAT]; + char board[(RING + 2)*SEAT]; // 选中的棋子在board中的位置 int posOfSelected; // 空棋盘点位,用于判断一个棋子位置是否在棋盘上 - static const char inBoard[(RING+2)*SEAT]; + static const char inBoard[(RING + 2)*SEAT]; // 招法表,每个位置有最多4种走法:顺时针、逆时针、向内、向外 - static char moveTable[(RING+2)*SEAT][4]; + static char moveTable[(RING + 2)*SEAT][4]; // 成三表,表示棋盘上各个位置有成三关系的对应位置表 - static char millTable[(RING+2)*SEAT][3][2]; + static char millTable[(RING + 2)*SEAT][3][2]; /* 本打算用如下的结构体来表示“三连” struct Mill { @@ -242,10 +245,10 @@ private: // 当前招法的命令行指令,即一招棋谱 char cmdline[32]; + // 棋谱 + list cmdlist; // 当前棋局的字符提示 string tip; - // 招法不用结构体表示了,用int表示=原位置*256+新位置,落子没有原位置的计为0xff - short move; }; #endif diff --git a/NineChess/src/ninechesswindow.cpp b/NineChess/src/ninechesswindow.cpp index 8ac0b89f..1a90784e 100644 --- a/NineChess/src/ninechesswindow.cpp +++ b/NineChess/src/ninechesswindow.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -35,15 +36,28 @@ NineChessWindow::NineChessWindow(QWidget *parent) // 设置场景 scene = new GameScene(this); + // 初始化各个控件 + // 关联视图和场景 ui.gameView->setScene(scene); // 视图反走样 ui.gameView->setRenderHint(QPainter::Antialiasing, true); - - // 初始化各个控件 // 视图反锯齿 ui.gameView->setRenderHint(QPainter::Antialiasing); + // 因功能限制,使部分功能不可用 + ui.actionViewText_V->setDisabled(true); + ui.actionPrevious_B->setDisabled(true); + ui.actionNext_F->setDisabled(true); + ui.actionEnd_E->setDisabled(true); + ui.actionAutoRun_A->setDisabled(true); + ui.actionEngine_E->setDisabled(true); + ui.actionInternet_I->setDisabled(true); + ui.actionEngine1_T->setDisabled(true); + ui.actionEngine2_R->setDisabled(true); + ui.actionSetting_O->setDisabled(true); + ui.actionAnimation_A->setDisabled(true); + // 关联既有动作信号和主窗口槽 // 视图上下翻转 connect(ui.actionFlip_F, &QAction::triggered, @@ -58,23 +72,6 @@ NineChessWindow::NineChessWindow(QWidget *parent) connect(ui.actionTurnLeftt_L, &QAction::triggered, ui.gameView, &GameView::turnLeft); - // 因功能限制,使部分功能不可用 - ui.actionNew_N->setDisabled(true); - ui.actionOpen_O->setDisabled(true); - ui.actionSave_S->setDisabled(true); - ui.actionSaveAs_A->setDisabled(true); - ui.actionViewText_V->setDisabled(true); - ui.actionPrevious_B->setDisabled(true); - ui.actionNext_F->setDisabled(true); - ui.actionEnd_E->setDisabled(true); - ui.actionAutoRun_A->setDisabled(true); - ui.actionEngine_E->setDisabled(true); - ui.actionInternet_I->setDisabled(true); - ui.actionEngine1_T->setDisabled(true); - ui.actionEngine2_R->setDisabled(true); - ui.actionSetting_O->setDisabled(true); - ui.actionAnimation_A->setDisabled(true); - // 初始化游戏规则菜单 ui.menu_R->installEventFilter(this); // 安装一次性定时器,执行初始化 @@ -86,6 +83,7 @@ NineChessWindow::~NineChessWindow() if (game != NULL) delete game; qDeleteAll(ruleActionList); + ; } bool NineChessWindow::eventFilter(QObject *watched, QEvent *event) @@ -180,6 +178,9 @@ void NineChessWindow::initialize() QString tip_Rule = QString("%1\n%2").arg(tr(NineChess::RULES[ruleNo].name)) .arg(tr(NineChess::RULES[ruleNo].info)); ui.tab_Rule->setPlainText(tip_Rule); + + // 关联列表视图和字符串列表模型 + ui.tab_Manual->setModel(& game->manualListModel); } void NineChessWindow::actionRules_triggered() @@ -208,7 +209,24 @@ void NineChessWindow::on_actionNew_N_triggered() void NineChessWindow::on_actionOpen_O_triggered() { + QString path = QFileDialog::getOpenFileName(this, "open", "../", "TXT(*.txt)"); + if (path.isEmpty() == false) + { + //文件对象 + QFile file(path); + //打开文件,只读方式打开 + bool isok = file.open(QIODevice::ReadOnly); + if (isok = true) + { + //读文件 + QByteArray array = file.readAll(); + qDebug() << array; + + } + //文件关闭 + file.close(); + } } void NineChessWindow::on_actionSave_S_triggered() diff --git a/NineChess/src/ninechesswindow.h b/NineChess/src/ninechesswindow.h index c5fd15c4..87b19d96 100644 --- a/NineChess/src/ninechesswindow.h +++ b/NineChess/src/ninechesswindow.h @@ -2,6 +2,9 @@ #define NINECHESSWINDOW_H #include +#include +#include +#include #include "ui_ninechesswindow.h" class GameScene; @@ -29,6 +32,8 @@ private: QList ruleActionList; // 游戏的规则号,涉及菜单项和对话框,所以要有 int ruleNo; + // 文件 + QFile file; private slots: // 初始化