添加命令行时间参数,删除界面tabWidget

This commit is contained in:
liuweilhy 2018-07-01 20:31:39 +08:00
parent b95e6b276b
commit 2f8fbab50a
14 changed files with 205 additions and 270 deletions

View File

@ -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. 鏃犵畻娉曞彧鏈夌晫闈㈢殑绋嬪簭銆?

View File

@ -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

View File

@ -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

View File

@ -240,7 +240,6 @@
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\moc_predefs.h;%(Outputs)</Outputs>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</CustomBuild>
<ClInclude Include="src\sizehinttextedit.h" />
<ClInclude Include="ui_ninechesswindow.h" />
</ItemGroup>
<ItemGroup>

View File

@ -110,9 +110,6 @@
<ClInclude Include="src\sizehintlistview.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\sizehinttextedit.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="debug\moc_predefs.h.cbt">

View File

@ -379,54 +379,17 @@
</property>
</widget>
</item>
<item>
<widget class="SizeHintListView" name="listView">
<property name="font">
<font>
<pointsize>7</pointsize>
</font>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="tabPosition">
<enum>QTabWidget::South</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="SizeHintTextEdit" name="tab_Rule">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<attribute name="title">
<string>规则</string>
</attribute>
<layout class="QFormLayout" name="formLayout"/>
</widget>
<widget class="SizeHintListView" name="tab_Manual">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<attribute name="title">
<string>棋谱</string>
</attribute>
<layout class="QFormLayout" name="formLayout"/>
</widget>
</widget>
</widget>
</item>
</layout>
@ -855,11 +818,6 @@
<extends>QListView</extends>
<header>sizehintlistview.h</header>
</customwidget>
<customwidget>
<class>SizeHintTextEdit</class>
<extends>QPlainTextEdit</extends>
<header>sizehinttextedit.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="ninechesswindow.qrc"/>

View File

@ -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);

View File

@ -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);
// 让电脑执后手

View File

@ -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(&currentTimeb);
// 超时胜负判断
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<long long>::iterator itor;
// 遍历
for ( itor = millList.begin(); itor != millList.end(); itor++)
for (itor = millList.begin(); itor != millList.end(); itor++)
{
if (mill == *itor)
break;

View File

@ -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();
// 清除所有禁点

View File

@ -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));
}

View File

@ -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

View File

@ -1,28 +0,0 @@
/* QPlainTextEdit派生类
* sizeHint函数
*
* QDockWidget没有很好的控制初始大小的方法resize函数没效果
* 使
* this->setFixedWidth(108);
*
*/
#ifndef SIZEHINTTEXTEDIT
#define SIZEHINTTEXTEDIT
#include <QPlainTextEdit>
class SizeHintTextEdit : public QPlainTextEdit
{
public:
SizeHintTextEdit(QWidget * parent = 0) {}
QSize sizeHint() const{
QSize size = QPlainTextEdit::sizeHint();
// 缺省宽度设为128这样就不太宽了
size.setWidth(128);
return size;
}
};
#endif // SIZEHINTTEXTEDIT

View File

@ -1,43 +1,43 @@
# 九联棋 NineChess
# 涔濊仈妫?NineChess
#### 项目介绍:
本游戏根据作者儿时游戏——“九联棋”编制,加上“成三棋”、“打三棋”和“莫里斯九子棋”,共三种规则玩法。
三种规则略有差异,鼠标放在相应菜单项有会有详细的规则提示。
#### 椤圭洰浠嬬粛锛?
鏈父鎴忔牴鎹綔鑰呭効鏃舵父鎴忊€斺€斺€滀節鑱旀鈥濈紪鍒讹紝鍔犱笂鈥滄垚涓夋鈥濄€佲€滄墦涓夋鈥濆拰鈥滆帿閲屾柉涔濆瓙妫嬧€濓紝鍏变笁绉嶈鍒欑帺娉曘€?
涓夌瑙勫垯鐣ユ湁宸紓锛岄紶鏍囨斁鍦ㄧ浉搴旇彍鍗曢」鏈変細鏈夎缁嗙殑瑙勫垯鎻愮ず銆?
#### 软件构架:
+ GUI框架Qt5.10Qt5大版本下均可通用。
+ 编译器MSVC2017MSVC2013及以上版本可用。
+ 源文件编码:所有头文件(*.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语言和VBC++是笔者自学的,一个人啃晦涩过时的MFC;
二来我穷到连个电脑都没有……
三嘛,就是贪玩……
工作之后有条件了我又自学了C#和Qt但都很肤浅没深入学只用来做几个小工具而已。
从5月末开始消沉到后来步入人生低谷我终于有大把的时间来思考人生。
风雨过后,我想起把时间用在兴趣爱好上。于是,这个小游戏诞生了!
如果你发现本程序有什么问题或好的建议请与本人联系。我的邮箱是liuweilhy@163.com
>          ——by liuweilhy 2015年11月6日
#### 浣滆€呭0鏄庯細
澶氬勾鍓嶄笂澶у閭d細鍎匡紝绗旇€呭氨鎵撶畻鍋氳繖涔堜釜绋嬪簭鍑烘潵銆傜劧鑰岋紝鏉′欢姣旇緝鑹拌嫤锛?
涓€鏉ユ病鏈夎€佸笀鏁欙紝璇句笂鍙浜咰璇█鍜孷B锛孋++鏄瑪鑰呰嚜瀛︾殑锛屼竴涓汉鍟冩櫐娑╄繃鏃剁殑MFC;
浜屾潵鎴戠┓鍒拌繛涓數鑴戦兘娌℃湁鈥︹€?
涓夊槢锛屽氨鏄椽鐜┾€︹€?
宸ヤ綔涔嬪悗鏈夋潯浠朵簡锛屾垜鍙堣嚜瀛︿簡C#鍜孮t锛屼絾閮藉緢鑲ゆ祬锛屾病娣卞叆瀛︼紝鍙敤鏉ュ仛鍑犱釜灏忓伐鍏疯€屽凡銆?
鍚庢潵娑堟矇杩囦竴娈垫椂闂达紝鎴戠粓浜庢湁澶ф妸鐨勬椂闂存潵鎬濊€冧汉鐢熴€?
椋庨洦杩囧悗锛屾垜鎯宠捣鎶婃椂闂寸敤鍦ㄥ叴瓒g埍濂戒笂銆備簬鏄紝杩欎釜灏忔父鎴忚癁鐢熶簡锛?
濡傛灉浣犲彂鐜版湰绋嬪簭鏈変粈涔堥棶棰樻垨濂界殑寤鸿锛岃涓庢湰浜鸿仈绯汇€傛垜鐨勯偖绠辨槸锛歭iuweilhy@163.com
>銆€銆€銆€銆€銆€銆€銆€銆€銆€銆€鈥斺€攂y liuweilhy 2015骞?1鏈?鏃