From 2f8fbab50a9dd5d6cae3e8700c6db1d23be9fd53 Mon Sep 17 00:00:00 2001 From: liuweilhy Date: Sun, 1 Jul 2018 20:31:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=91=BD=E4=BB=A4=E8=A1=8C?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E5=8F=82=E6=95=B0=EF=BC=8C=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E7=95=8C=E9=9D=A2tabWidget?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- History.txt | 16 ++- Licence.txt | 11 +- NineChess/ninechess.pro | 3 +- NineChess/ninechess.vcxproj | 1 - NineChess/ninechess.vcxproj.filters | 3 - NineChess/ninechesswindow.ui | 60 ++-------- NineChess/src/gamecontroller.cpp | 81 ++++---------- NineChess/src/gamecontroller.h | 6 +- NineChess/src/ninechess.cpp | 165 ++++++++++++++++++---------- NineChess/src/ninechess.h | 6 +- NineChess/src/ninechesswindow.cpp | 12 +- NineChess/src/sizehintlistview.h | 13 ++- NineChess/src/sizehinttextedit.h | 28 ----- Readme.md | 70 ++++++------ 14 files changed, 205 insertions(+), 270 deletions(-) delete mode 100644 NineChess/src/sizehinttextedit.h diff --git a/History.txt b/History.txt index 2b55b41d..b224c7bd 100644 --- a/History.txt +++ b/History.txt @@ -1,8 +1,12 @@ -九连棋 NineChess -更新历史: -2018/5/19 V1.0 - 1. Qt5.10.1+MSVC2017重构; - 2. 游戏可以正确运行,实现本机对战功能,其它功能待完善。 +涔濊繛妫?NineChess +鏇存柊鍘嗗彶锛? +2018/6/10 V0.3 + 1. 淇敼绠楁硶涓婄殑bug锛? + 2. 娣诲姞鍛戒护琛岃В鏋愬姛鑳姐€? + +2018/5/19 V0.2 + 1. Qt5.10.1+MSVC2017閲嶆瀯锛? + 2. 娓告垙鍙互姝g‘杩愯锛屽疄鐜版湰鏈哄鎴樺姛鑳斤紝鍏跺畠鍔熻兘寰呭畬鍠勩€? 2015/11/6 V0.1 - 1. 无算法只有界面的程序。 + 1. 鏃犵畻娉曞彧鏈夌晫闈㈢殑绋嬪簭銆? diff --git a/Licence.txt b/Licence.txt index a931f7d5..1635e3b0 100644 --- a/Licence.txt +++ b/Licence.txt @@ -1,15 +1,10 @@ 本软件代码遵循LGPL v3协议,其中: 1. 对于Qt库,遵循GPL协议。任何人都可以免费使用,但必须保持其开源; 2. 对于原作者自行开发的代码: - 2.1 未经原作者书面授权,任何人不得修改、传播; - 2.2 获得原作者书面授权免费使用者: - 2.2.1 其修改版必须对原作者开源; - 2.2.2 其修改版必须完整保留本Licence文件,如需新增内容,只能在原版Licence文件中追加; - 2.2.3 原作者对其修改版在保留修改者署名情况下,有修改、传播及无偿商业化使用的权利; - 2.3 获得原作者书面授权收费使用者,按照双方书面协议执行。 + 2.1 任何人可以不经原作者授权,使用、修改和分发此代码,但必须保持LGPL v3协议; + 2.2 获得原作者商业授权者,按照双方书面协议执行。 本软件的可执行文件: 1. Qt库文件归Qt版权方所有; -2. 原作者、代码免费使用者的可执行文件,任何人可以免费使用、传播,但不得反汇编、修改,不得商用及其它违法用途。 -3. 获得原作者书面授权收费使用者,按照双方书面协议执行。 +2. 其余可执行文件,任何人可以免费使用、传播,但不得反汇编、修改,不得商用及其它违法用途。 —— by liuweilhy 2018.05.21 diff --git a/NineChess/ninechess.pro b/NineChess/ninechess.pro index 8b5cc1be..c0e74b07 100644 --- a/NineChess/ninechess.pro +++ b/NineChess/ninechess.pro @@ -1,4 +1,4 @@ -#------------------------------------------------- +#------------------------------------------------- # # Project created by QtCreator 2015-11-03T22:30:34 # @@ -31,7 +31,6 @@ HEADERS += \ src\boarditem.h \ src\gameview.h \ src\ninechess.h \ - src\sizehinttextedit.h \ src\sizehintlistview.h \ src\gamescene.h diff --git a/NineChess/ninechess.vcxproj b/NineChess/ninechess.vcxproj index 53151cf3..174a3303 100644 --- a/NineChess/ninechess.vcxproj +++ b/NineChess/ninechess.vcxproj @@ -240,7 +240,6 @@ release\moc_predefs.h;%(Outputs) true - diff --git a/NineChess/ninechess.vcxproj.filters b/NineChess/ninechess.vcxproj.filters index 012ffbd3..d170f3dc 100644 --- a/NineChess/ninechess.vcxproj.filters +++ b/NineChess/ninechess.vcxproj.filters @@ -110,9 +110,6 @@ Header Files - - Header Files - diff --git a/NineChess/ninechesswindow.ui b/NineChess/ninechesswindow.ui index 801a3e30..7ef9e535 100644 --- a/NineChess/ninechesswindow.ui +++ b/NineChess/ninechesswindow.ui @@ -379,54 +379,17 @@ + + + + + 7 + + + + - - - - 0 - 0 - - - - QTabWidget::South - - - 0 - - - - - 1 - 0 - - - - - 8 - - - - true - - - 规则 - - - - - - - 1 - 0 - - - - 棋谱 - - - - @@ -855,11 +818,6 @@ QListView
sizehintlistview.h
- - SizeHintTextEdit - QPlainTextEdit -
sizehinttextedit.h
-
diff --git a/NineChess/src/gamecontroller.cpp b/NineChess/src/gamecontroller.cpp index ade82c81..47af7361 100644 --- a/NineChess/src/gamecontroller.cpp +++ b/NineChess/src/gamecontroller.cpp @@ -141,7 +141,7 @@ void GameController::setInvert(bool arg) } } -void GameController::setRule(int ruleNo) +void GameController::setRule(int ruleNo, int stepLimited /*= -1*/, int timeLimited /*= -1*/) { // 停止计时器 if (timeID != 0) @@ -149,10 +149,13 @@ void GameController::setRule(int ruleNo) // 定时器ID为0 timeID = 0; - // 更新规则,原限时和限步不变 // 更新规则,原限时和限步不变 if (ruleNo < 0 || ruleNo >= NineChess::RULENUM) return; + if (stepLimited != -1 && timeLimited != -1) { + stepsLimit = stepLimited; + timeLimit = timeLimited; + } // 设置模型规则,重置游戏 chess.setData(&NineChess::RULES[ruleNo], stepsLimit, timeLimit); @@ -177,50 +180,10 @@ void GameController::setRule(int ruleNo) QTime qtime = QTime(0, 0, 0, 0).addMSecs(time1); emit time1Changed(qtime.toString("mm:ss.zzz")); emit time2Changed(qtime.toString("mm:ss.zzz")); - // 发信号更新状态栏 - message = QString::fromStdString(chess.getTip()); - emit statusBarChanged(message); - // 播放音效 - playSound(soundNewgame); -} - -void GameController::setRule(int ruleNo, int stepLimited, int timeLimited) -{ - // 停止计时器 - if (timeID != 0) - killTimer(timeID); - // 定时器ID为0 - timeID = 0; - - // 更新规则,原限时和限步不变 - if (ruleNo < 0 || ruleNo >= NineChess::RULENUM) - return; - stepsLimit = stepLimited; - timeLimit = timeLimited; - // 设置模型规则,重置游戏 - chess.setData(&NineChess::RULES[ruleNo], stepsLimit, timeLimit); - - // 清除棋子 - qDeleteAll(pieceList); - pieceList.clear(); - piece = NULL; - // 重新绘制棋盘 - scene.setDiagonal(chess.getRule()->hasObliqueLine); - - // 如果规则不要求计时,则time1和time2表示已用时间 - if (timeLimit <= 0) { - // 将玩家的已用时间清零 - time1 = time2 = 0; - } - else - { - // 将玩家的剩余时间置为限定时间 - time1 = time2 = timeLimit * 60000; - } - // 发出信号通知主窗口更新LCD显示 - QTime qtime = QTime(0, 0, 0, 0).addMSecs(time1); - emit time1Changed(qtime.toString("mm:ss.zzz")); - emit time2Changed(qtime.toString("mm:ss.zzz")); + // 更新棋谱 + manualListModel.removeRows(0, manualListModel.rowCount()); + manualListModel.insertRow(0); + manualListModel.setData(manualListModel.index(0), chess.getCmdLine()); // 发信号更新状态栏 message = QString::fromStdString(chess.getTip()); emit statusBarChanged(message); @@ -328,9 +291,6 @@ bool GameController::actionPiece(QPointF pos) case NineChess::GAME_NOTSTARTED: // 如果未开局则开局,这里还要继续判断,不可break gameStart(); - manualListModel.setStringList(QStringList()); - manualListModel.insertRow(0); - manualListModel.setData(manualListModel.index(0), chess.getCmdLine()); case NineChess::GAME_OPENING: // 如果是开局阶段(轮流落下新子),落子 @@ -353,7 +313,8 @@ bool GameController::actionPiece(QPointF pos) }// 移子 else if (chess.getAction() == NineChess::ACTION_PLACE) { // 如果移子不成功,尝试重新选子 - if (!movePiece(pos)) + result = movePiece(pos); + if (!result) result = choosePiece(pos); }// 去子 else if (chess.getAction() == NineChess::ACTION_REMOVE) { @@ -368,18 +329,16 @@ bool GameController::actionPiece(QPointF pos) if (result) { - 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); + int size = chess.getCmdList()->size(); + auto i = (chess.getCmdList())->rbegin(); + // 输出命令行 + for (int n = size - row; n > 0; n--) { + manualListModel.insertRow(row); + manualListModel.setData(manualListModel.index(row), (*(i++)).c_str()); } + if (chess.whoWin() != NineChess::NOBODY) + playSound(soundWin); } return result; @@ -536,7 +495,7 @@ bool GameController::removePiece(QPointF pos) bool GameController::cleanForbidden() { - foreach (PieceItem *p, pieceList) + foreach(PieceItem *p, pieceList) { if (p->isDeleted()) { pieceList.removeOne(p); diff --git a/NineChess/src/gamecontroller.h b/NineChess/src/gamecontroller.h index d6da04ad..8f9bd6c2 100644 --- a/NineChess/src/gamecontroller.h +++ b/NineChess/src/gamecontroller.h @@ -52,10 +52,8 @@ public slots: void setEditing(bool arg = true); // 设置黑白反转状态 void setInvert(bool arg = true); - // 设置规则,不改变限时限步 - void setRule(int ruleNo); - // 设置规则,改变限时限步 - void setRule(int ruleNo, int stepLimited, int timeLimited); + // 设置规则 + void setRule(int ruleNo, int stepLimited = -1, int timeLimited = -1); // 让电脑执先手 void setEngine1(bool arg = true); // 让电脑执后手 diff --git a/NineChess/src/ninechess.cpp b/NineChess/src/ninechess.cpp index b6aacc98..623b74dd 100644 --- a/NineChess/src/ninechess.cpp +++ b/NineChess/src/ninechess.cpp @@ -296,6 +296,22 @@ bool NineChess::setData(const struct Rule *rule, int s, int t, int step, int fla // 提示 setTip(); + // 计棋谱 + cmdlist.clear(); + int i; + for (i = 0; i < RULENUM; i++) { + if (strcmp(this->rule.name, RULES[i].name) == 0) + break; + } + if (sprintf(cmdline, "r%1u s%03u t%02u", i + 1, s, t) > 0) { + cmdlist.push_back(string(cmdline)); + return true; + } + else { + cmdline[0] = '\0'; + return false; + } + return true; } @@ -331,21 +347,6 @@ bool NineChess::start() phase = GAME_OPENING; // 启动计时器 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; - } } // 其它情况 @@ -359,7 +360,7 @@ int NineChess::cp2pos(int c, int p) return c * SEAT + p - 1; } -bool NineChess::place(int c, int p) +bool NineChess::place(int c, int p, long time_p /* = -1*/) { // 如果局面为"未开局"或“结局”,返回false if (phase == GAME_NOTSTARTED || phase == GAME_OVER) @@ -371,6 +372,8 @@ bool NineChess::place(int c, int p) int pos = cp2pos(c, p); if (!inBoard[pos] || board[pos]) return false; + // 时间的临时变量 + long player_ms = -1; // 对于开局落子 char piece = '\x00'; @@ -392,7 +395,8 @@ bool NineChess::place(int c, int p) player2_InHand--; player2_Remain++; } - sprintf(cmdline, "(%1d,%1d)", c, p); + player_ms = update(time_p); + sprintf(cmdline, "(%1u,%1u) %02u:%02u.%03u", c, p, player_ms / 60000, player_ms / 1000, player_ms % 1000); cmdlist.push_back(string(cmdline)); posOfSelected = pos; step++; @@ -438,7 +442,6 @@ bool NineChess::place(int c, int p) num_NeedRemove = rule.removeMore ? n : 1; // 进入去子状态 action = ACTION_REMOVE; - setTip(); } setTip(); return true; @@ -459,7 +462,9 @@ bool NineChess::place(int c, int p) return false; } // 移子 - sprintf(cmdline, "(%1d,%1d)->(%1d,%1d)", posOfSelected / RING, posOfSelected % RING + 1, c, p); + player_ms = update(time_p); + sprintf(cmdline, "(%1u,%1u)->(%1u,%1u) %02u:%02u.%03u", posOfSelected / SEAT, posOfSelected % SEAT + 1, + c, p, player_ms / 60000, player_ms / 1000, player_ms % 1000); cmdlist.push_back(string(cmdline)); board[pos] = board[posOfSelected]; board[posOfSelected] = '\x00'; @@ -494,7 +499,7 @@ bool NineChess::place(int c, int p) return false; } -bool NineChess::remove(int c, int p) +bool NineChess::remove(int c, int p, long time_p /* = -1*/) { // 如果局面为"未开局"或“结局”,返回false if (phase == GAME_NOTSTARTED || phase == GAME_OVER) @@ -505,6 +510,8 @@ bool NineChess::remove(int c, int p) // 如果去子完成,返回false if (num_NeedRemove <= 0) return false; + // 时间的临时变量 + long player_ms = -1; int pos = cp2pos(c, p); // 对手 enum Player opponent = PLAYER2; @@ -528,7 +535,8 @@ bool NineChess::remove(int c, int p) player2_Remain--; else if (turn == PLAYER2) player1_Remain--; - sprintf(cmdline, "-(%1d,%1d)", c, p); + player_ms = update(time_p); + sprintf(cmdline, "-(%1u,%1u) %02u:%02u.%03u", c, p, player_ms / 60000, player_ms / 1000, player_ms % 1000); cmdlist.push_back(string(cmdline)); posOfSelected = 0; num_NeedRemove--; @@ -630,78 +638,101 @@ bool NineChess::choose(int c, int p) return false; } -// 打算用个C++的命令行解析库的,简单的没必要,但中文编码有极小 +// 打算用个C++的命令行解析库的,简单的没必要,但中文编码有极小概率出问题 bool NineChess::command(const char *cmd) { int r, s, t; int c1, p1, c2, p2; + int args = 0; + int mm = 0, ss = 0, mss = 0; + long tm = -1; // 设置规则 - if (sscanf(cmd, "r%d s%d t%d", &r, &s, &t) == 3) { + if (sscanf(cmd, "r%1u s%3u t%2u", &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) { + args = sscanf(cmd, "(%1u,%1u)->(%1u,%1u) %2u:%2u.%3u", &c1, &p1, &c2, &p2, &mm, &ss, &mss); + if (args >= 4) { + if (args == 7) { + if (mm >= 0 && ss >= 0 && mss >= 0) + tm = mm * 60000 + ss * 1000 + mss; + } if (choose(c1, p1)) - return place(c2, p2); + return place(c2, p2, tm); else return false; } // 去子 - else if (sscanf(cmd, "-(%d,%d)", &c1, &p1) == 2) { - return remove(c1, p1); + args = sscanf(cmd, "-(%1u,%1u) %2u:%2u.%3u", &c1, &p1, &mm, &ss, &mss); + if (args >= 2) { + if (args == 5) { + if (mm >= 0 && ss >= 0 && mss >= 0) + tm = mm * 60000 + ss * 1000 + mss; + } + return remove(c1, p1, tm); } // 落子 - else if (sscanf(cmd, "(%d,%d)", &c1, &p1) == 2) { - return place(c1, p1); + args = sscanf(cmd, "(%1u,%1u) %2u:%2u.%3u", &c1, &p1, &mm, &ss, &mss); + if (args >= 2) { + if (args == 5) { + if (mm >= 0 && ss >= 0 && mss >= 0) + tm = mm * 60000 + ss * 1000 + mss; + } + return place(c1, p1, tm); } return false; } -inline bool NineChess::update() +inline long NineChess::update(long time_p /*= -1*/) { + long ret = -1; + long *player_ms = (turn == PLAYER1 ? &player1_MS : &player2_MS); + long playerNext_ms = (turn == PLAYER1 ? player2_MS : player1_MS); + // 根据局面调整计时器 switch (phase) { case NineChess::GAME_OPENING: case NineChess::GAME_MID: ftime(¤tTimeb); - // 超时胜负判断 - if (turn == PLAYER1) { - player1_MS = (long)(currentTimeb.time - startTimeb.time) * 1000 - + (currentTimeb.millitm - startTimeb.millitm) - player2_MS; - // 如果玩家1超时 - if (rule.maxTime > 0 && player1_MS > rule.maxTime * 60000) { - player1_MS = rule.maxTime * 60000; - winner = PLAYER2; - phase = GAME_OVER; - tip = "玩家1超时,恭喜玩家2获胜"; + // 更新时间 + if (time_p >= *player_ms) + { + *player_ms = ret = time_p; + long t = player1_MS + player2_MS; + if (t % 1000 <= currentTimeb.millitm) + { + startTimeb.time = currentTimeb.time - (t / 1000); + startTimeb.millitm = currentTimeb.millitm - (t % 1000); + } + else + { + startTimeb.time = currentTimeb.time - (t / 1000) - 1; + startTimeb.millitm = currentTimeb.millitm + 1000 - (t % 1000); } } - else if (turn == PLAYER2) { - player2_MS = (long)(currentTimeb.time - startTimeb.time) * 1000 - + (currentTimeb.millitm - startTimeb.millitm) - player1_MS; - // 如果玩家2超时 - if (rule.maxTime > 0 && player2_MS > rule.maxTime * 60000) { - player2_MS = rule.maxTime * 60000; - winner = PLAYER1; - phase = GAME_OVER; - tip = "玩家2超时,恭喜玩家1获胜"; - } + else + { + *player_ms = ret = (long)(currentTimeb.time - startTimeb.time) * 1000 + + (currentTimeb.millitm - startTimeb.millitm) - playerNext_ms; } - return true; + // 有限时要求则判断胜负 + if (rule.maxTime > 0) + win(); + return ret; case NineChess::GAME_NOTSTARTED: - return true; + return ret; case NineChess::GAME_OVER: - return true; + return ret; default: - return true; + return ret; } } @@ -715,10 +746,24 @@ bool NineChess::win() // 如果有时间限定 if (rule.maxTime > 0) { - // 更新时间,判断胜负 - update(); - if (winner != NOBODY) { - sprintf(cmdline, "Time over. Player%1d win!", winner == PLAYER1 ? 1 : 2); + // 这里不能update更新时间,否则会形成循环嵌套 + // 如果玩家1超时 + if (player1_MS > rule.maxTime * 60000) { + player1_MS = rule.maxTime * 60000; + winner = PLAYER2; + phase = GAME_OVER; + tip = "玩家1超时,恭喜玩家2获胜!"; + sprintf(cmdline, "Time over. Player2 win!"); + cmdlist.push_back(string(cmdline)); + return true; + } + // 如果玩家2超时 + else if (player2_MS > rule.maxTime * 60000) { + player2_MS = rule.maxTime * 60000; + winner = PLAYER1; + phase = GAME_OVER; + tip = "玩家2超时,恭喜玩家1获胜!"; + sprintf(cmdline, "Time over. Player1 win!"); cmdlist.push_back(string(cmdline)); return true; } @@ -782,7 +827,7 @@ bool NineChess::win() } // 否则让棋,由对手走 else - { + { changeTurn(); return false; } @@ -854,7 +899,7 @@ int NineChess::addMills(int pos) // 迭代器 list::iterator itor; // 遍历 - for ( itor = millList.begin(); itor != millList.end(); itor++) + for (itor = millList.begin(); itor != millList.end(); itor++) { if (mill == *itor) break; diff --git a/NineChess/src/ninechess.h b/NineChess/src/ninechess.h index b26464b9..7517cdcc 100644 --- a/NineChess/src/ninechess.h +++ b/NineChess/src/ninechess.h @@ -145,9 +145,9 @@ public: // 选子,在第c圈第p个位置,为迎合日常,c和p下标都从1开始 bool choose(int c, int p); // 落子,在第c圈第p个位置,为迎合日常,c和p下标都从1开始 - bool place(int c, int p); + bool place(int c, int p, long time_p = -1); // 去子,在第c圈第p个位置,为迎合日常,c和p下标都从1开始 - bool remove(int c, int p); + bool remove(int c, int p, long time_p = -1); // 命令行解析函数 bool command(const char *cmd); @@ -165,7 +165,7 @@ protected: // 将第c圈,第p位转化为棋盘下标形式,c和p下标都从1开始 int cp2pos(int c, int p); // 更新时间和状态,用内联函数以提高效率 - inline bool update(); + inline long update(long time_p = -1); // 是否分出胜负 bool win(); // 清除所有禁点 diff --git a/NineChess/src/ninechesswindow.cpp b/NineChess/src/ninechesswindow.cpp index 1a90784e..52b4c78a 100644 --- a/NineChess/src/ninechesswindow.cpp +++ b/NineChess/src/ninechesswindow.cpp @@ -175,12 +175,11 @@ void NineChessWindow::initialize() // 重置游戏规则 game->setRule(ruleNo); // 规则提示 - 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); + //QString tip_Rule = QString("%1\n%2").arg(tr(NineChess::RULES[ruleNo].name)) + // .arg(tr(NineChess::RULES[ruleNo].info)); // 关联列表视图和字符串列表模型 - ui.tab_Manual->setModel(& game->manualListModel); + ui.listView->setModel(& game->manualListModel); } void NineChessWindow::actionRules_triggered() @@ -196,9 +195,8 @@ void NineChessWindow::actionRules_triggered() // 重置游戏规则 game->setRule(ruleNo); // 规则提示 - 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); + //QString tip_Rule = QString("%1\n%2").arg(tr(NineChess::RULES[ruleNo].name)) + // .arg(tr(NineChess::RULES[ruleNo].info)); } diff --git a/NineChess/src/sizehintlistview.h b/NineChess/src/sizehintlistview.h index dc2b3fb2..a3f487cf 100644 --- a/NineChess/src/sizehintlistview.h +++ b/NineChess/src/sizehintlistview.h @@ -16,12 +16,23 @@ class SizeHintListView : public QListView { public: SizeHintListView(QWidget * parent = 0) {} - QSize sizeHint() const{ + QSize sizeHint() const { QSize size = QListView::sizeHint(); // 缺省宽度设为128,这样就不太宽了 size.setWidth(128); return size; } + +protected: + // 屏蔽掉双击编辑功能 + void mouseDoubleClickEvent(QMouseEvent *event) {} + // 插入新行后自动选中最后一个 + void rowsInserted(const QModelIndex &parent, int start, int end) { + QModelIndex id = model()->index(model()->rowCount()-1, 0); + setCurrentIndex(id); + update(); + scrollToBottom(); + } }; #endif // SIZEHINTLISTVIEW diff --git a/NineChess/src/sizehinttextedit.h b/NineChess/src/sizehinttextedit.h deleted file mode 100644 index 90d0e6c4..00000000 --- a/NineChess/src/sizehinttextedit.h +++ /dev/null @@ -1,28 +0,0 @@ -/* QPlainTextEdit派生类 - * 之所以要派生这个类,重载sizeHint函数 - * 只是为了让停靠栏(父窗口)在初始时不至于过宽难看 - * QDockWidget没有很好的控制初始大小的方法,resize函数没效果 - * 如果不用派生类,使用固定宽度也可以,如下所示 - * this->setFixedWidth(108); - * 但调节停靠栏宽度后就不好看了 - */ - -#ifndef SIZEHINTTEXTEDIT -#define SIZEHINTTEXTEDIT - -#include - -class SizeHintTextEdit : public QPlainTextEdit -{ -public: - SizeHintTextEdit(QWidget * parent = 0) {} - QSize sizeHint() const{ - QSize size = QPlainTextEdit::sizeHint(); - // 缺省宽度设为128,这样就不太宽了 - size.setWidth(128); - return size; - } -}; - -#endif // SIZEHINTTEXTEDIT - diff --git a/Readme.md b/Readme.md index 9ee5edb2..5fff8f2a 100644 --- a/Readme.md +++ b/Readme.md @@ -1,43 +1,43 @@ -# 九联棋 NineChess +# 涔濊仈妫?NineChess -#### 项目介绍: -本游戏根据作者儿时游戏——“九联棋”编制,加上“成三棋”、“打三棋”和“莫里斯九子棋”,共三种规则玩法。 -三种规则略有差异,鼠标放在相应菜单项有会有详细的规则提示。 +#### 椤圭洰浠嬬粛锛? +鏈父鎴忔牴鎹綔鑰呭効鏃舵父鎴忊€斺€斺€滀節鑱旀鈥濈紪鍒讹紝鍔犱笂鈥滄垚涓夋鈥濄€佲€滄墦涓夋鈥濆拰鈥滆帿閲屾柉涔濆瓙妫嬧€濓紝鍏变笁绉嶈鍒欑帺娉曘€? +涓夌瑙勫垯鐣ユ湁宸紓锛岄紶鏍囨斁鍦ㄧ浉搴旇彍鍗曢」鏈変細鏈夎缁嗙殑瑙勫垯鎻愮ず銆? -#### 软件构架: -+ GUI框架:Qt5.10,Qt5大版本下均可通用。 -+ 编译器:MSVC2017,MSVC2013及以上版本可用。 -+ 源文件编码:所有头文件(*.h)和源文件(*.cpp)采用UTF-8+BOM编码格式。pro文件等采用UTF-8无BOM编码。 -+ 本程序采用MVC(模型——视图——控制器)设计规范,对应类如下: +#### 杞欢鏋勬灦锛? ++ GUI妗嗘灦锛歈t5.10锛孮t5澶х増鏈笅鍧囧彲閫氱敤銆? ++ 缂栬瘧鍣細MSVC2017锛孧SVC2013鍙婁互涓婄増鏈彲鐢ㄣ€? ++ 婧愭枃浠剁紪鐮侊細鎵€鏈夊ご鏂囦欢(*.h)鍜屾簮鏂囦欢(*.cpp)閲囩敤UTF-8+BOM缂栫爜鏍煎紡銆俻ro鏂囦欢绛夐噰鐢║TF-8鏃燘OM缂栫爜銆? ++ 鏈▼搴忛噰鐢∕VC锛堟ā鍨嬧€斺€旇鍥锯€斺€旀帶鍒跺櫒锛夎璁¤鑼冿紝瀵瑰簲绫诲涓嬶細 ``` MVC - ├─Model - │ └─NineChess:用标准C++写的棋类模型,处理下棋过程 - ├─View - │ ├─NineChessWindow:从QMainWindow派生的主窗口类,由Qt自动生成 - │ ├─SizeHintListView:从QListView派生的列表框 - │ ├─GameScene:从QGraphicsScene派生的场景类 - │ ├─GameView:从QGraphicsView派生的视图框 - │ ├─BoardItem:从QGraphicsItem派生的棋盘图形类 - │ └─PiecedItem:从QGraphicsItem派生的棋子图形类 - └─Controller - └─GameController:从QObject派生的控制类 + 鈹溾攢Model + 鈹? 鈹斺攢NineChess锛氱敤鏍囧噯C++鍐欑殑妫嬬被妯″瀷锛屽鐞嗕笅妫嬭繃绋? + 鈹溾攢View + 鈹? 鈹溾攢NineChessWindow锛氫粠QMainWindow娲剧敓鐨勪富绐楀彛绫伙紝鐢盦t鑷姩鐢熸垚 + 鈹? 鈹溾攢SizeHintListView锛氫粠QListView娲剧敓鐨勫垪琛ㄦ + 鈹? 鈹溾攢GameScene锛氫粠QGraphicsScene娲剧敓鐨勫満鏅被 + 鈹? 鈹溾攢GameView锛氫粠QGraphicsView娲剧敓鐨勮鍥炬 + 鈹? 鈹溾攢BoardItem锛氫粠QGraphicsItem娲剧敓鐨勬鐩樺浘褰㈢被 + 鈹? 鈹斺攢PiecedItem锛氫粠QGraphicsItem娲剧敓鐨勬瀛愬浘褰㈢被 + 鈹斺攢Controller + 鈹斺攢GameController锛氫粠QObject娲剧敓鐨勬帶鍒剁被 ``` -+ 这个程序用到了很多Qt特性,其模式后期可以扩展到各种棋类游戏,适合初学者一看。 ++ 杩欎釜绋嬪簭鐢ㄥ埌浜嗗緢澶歈t鐗规€э紝鍏舵ā寮忓悗鏈熷彲浠ユ墿灞曞埌鍚勭妫嬬被娓告垙锛岄€傚悎鍒濆鑰呬竴鐪嬨€? -#### 许可协议 -参见Licence.txt +#### 璁稿彲鍗忚 +鍙傝Licence.txt -#### 更新历史 -参见History.txt +#### 鏇存柊鍘嗗彶 +鍙傝History.txt -#### 作者声明: -多年前上大学那会儿,笔者就打算做这么个程序出来。然而,条件比较艰苦: -一来没有老师教,课上只学了C语言和VB,C++是笔者自学的,一个人啃晦涩过时的MFC; -二来我穷到连个电脑都没有…… -三嘛,就是贪玩…… -工作之后有条件了,我又自学了C#和Qt,但都很肤浅,没深入学,只用来做几个小工具而已。 -从5月末开始消沉到后来步入人生低谷,我终于有大把的时间来思考人生。 -风雨过后,我想起把时间用在兴趣爱好上。于是,这个小游戏诞生了! -如果你发现本程序有什么问题或好的建议,请与本人联系。我的邮箱是:liuweilhy@163.com ->          ——by liuweilhy 2015年11月6日 \ No newline at end of file +#### 浣滆€呭0鏄庯細 +澶氬勾鍓嶄笂澶у閭d細鍎匡紝绗旇€呭氨鎵撶畻鍋氳繖涔堜釜绋嬪簭鍑烘潵銆傜劧鑰岋紝鏉′欢姣旇緝鑹拌嫤锛? +涓€鏉ユ病鏈夎€佸笀鏁欙紝璇句笂鍙浜咰璇█鍜孷B锛孋++鏄瑪鑰呰嚜瀛︾殑锛屼竴涓汉鍟冩櫐娑╄繃鏃剁殑MFC; +浜屾潵鎴戠┓鍒拌繛涓數鑴戦兘娌℃湁鈥︹€? +涓夊槢锛屽氨鏄椽鐜┾€︹€? +宸ヤ綔涔嬪悗鏈夋潯浠朵簡锛屾垜鍙堣嚜瀛︿簡C#鍜孮t锛屼絾閮藉緢鑲ゆ祬锛屾病娣卞叆瀛︼紝鍙敤鏉ュ仛鍑犱釜灏忓伐鍏疯€屽凡銆? +鍚庢潵娑堟矇杩囦竴娈垫椂闂达紝鎴戠粓浜庢湁澶ф妸鐨勬椂闂存潵鎬濊€冧汉鐢熴€? +椋庨洦杩囧悗锛屾垜鎯宠捣鎶婃椂闂寸敤鍦ㄥ叴瓒g埍濂戒笂銆備簬鏄紝杩欎釜灏忔父鎴忚癁鐢熶簡锛? +濡傛灉浣犲彂鐜版湰绋嬪簭鏈変粈涔堥棶棰樻垨濂界殑寤鸿锛岃涓庢湰浜鸿仈绯汇€傛垜鐨勯偖绠辨槸锛歭iuweilhy@163.com +>銆€銆€銆€銆€銆€銆€銆€銆€銆€銆€鈥斺€攂y liuweilhy 2015骞?1鏈?鏃 \ No newline at end of file