完善“历史局面”功能
This commit is contained in:
parent
b3654dd794
commit
2d7a795f97
|
@ -243,6 +243,11 @@
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
|
@ -258,14 +263,14 @@
|
||||||
<widget class="QLabel" name="label1">
|
<widget class="QLabel" name="label1">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>2</horstretch>
|
<horstretch>3</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<family>微软雅黑</family>
|
<family>微软雅黑</family>
|
||||||
<pointsize>10</pointsize>
|
<pointsize>9</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -319,6 +324,11 @@
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
|
@ -334,14 +344,14 @@
|
||||||
<widget class="QLabel" name="label2">
|
<widget class="QLabel" name="label2">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>2</horstretch>
|
<horstretch>3</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<family>微软雅黑</family>
|
<family>微软雅黑</family>
|
||||||
<pointsize>10</pointsize>
|
<pointsize>9</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -379,6 +389,45 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="labelInfo">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>1</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="ninechesswindow.qrc">:/icon/Resources/icon/Help.png</pixmap>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="labelRule">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>8</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>AmdtSymbols</family>
|
||||||
|
<pointsize>7</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>rule</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="SizeHintListView" name="listView">
|
<widget class="SizeHintListView" name="listView">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
|
|
|
@ -109,6 +109,11 @@ QPointF BoardItem::nearestPosition(QPointF const pos)
|
||||||
return nearestPos;
|
return nearestPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPointF BoardItem::cp2pos(int c, int p)
|
||||||
|
{
|
||||||
|
return position[(c-1)*SEAT+p-1];
|
||||||
|
}
|
||||||
|
|
||||||
bool BoardItem::pos2cp(QPointF pos, int &c, int &p)
|
bool BoardItem::pos2cp(QPointF pos, int &c, int &p)
|
||||||
{
|
{
|
||||||
// 寻找最近的落子点
|
// 寻找最近的落子点
|
||||||
|
|
|
@ -20,6 +20,8 @@ public:
|
||||||
void setDiagonal(bool arg = true);
|
void setDiagonal(bool arg = true);
|
||||||
// 返回最近的落子点
|
// 返回最近的落子点
|
||||||
QPointF nearestPosition(QPointF const pos);
|
QPointF nearestPosition(QPointF const pos);
|
||||||
|
// 将模型的圈、位转化为落子点坐标
|
||||||
|
QPointF cp2pos(int c, int p);
|
||||||
// 将落子点坐标转化为模型用的圈、位
|
// 将落子点坐标转化为模型用的圈、位
|
||||||
bool pos2cp(QPointF pos, int &c, int &p);
|
bool pos2cp(QPointF pos, int &c, int &p);
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
#include "boarditem.h"
|
#include "boarditem.h"
|
||||||
#include "pieceitem.h"
|
#include "pieceitem.h"
|
||||||
|
|
||||||
GameController::GameController(GameScene & scene, QObject *parent) : QObject(parent),
|
GameController::GameController(GameScene &scene, QObject *parent) : QObject(parent),
|
||||||
|
// 是否浏览过历史纪录
|
||||||
scene(scene),
|
scene(scene),
|
||||||
piece(NULL),
|
piece(NULL),
|
||||||
isEditing(false),
|
isEditing(false),
|
||||||
|
@ -22,11 +23,10 @@ isEngine2(false),
|
||||||
hasAnimation(true),
|
hasAnimation(true),
|
||||||
hasSound(true),
|
hasSound(true),
|
||||||
timeID(0),
|
timeID(0),
|
||||||
|
ruleNo(-1),
|
||||||
timeLimit(0),
|
timeLimit(0),
|
||||||
stepsLimit(0)
|
stepsLimit(0)
|
||||||
{
|
{
|
||||||
// 设置场景尺寸大小为棋盘大小的1.08倍
|
|
||||||
scene.setSceneRect(-BOARD_SIZE * 0.54, -BOARD_SIZE * 0.54, BOARD_SIZE*1.08, BOARD_SIZE*1.08);
|
|
||||||
// 已在view的样式表中添加背景,scene中不用添加背景
|
// 已在view的样式表中添加背景,scene中不用添加背景
|
||||||
// 区别在于,view中的背景不随视图变换而变换,scene中的背景随视图变换而变换
|
// 区别在于,view中的背景不随视图变换而变换,scene中的背景随视图变换而变换
|
||||||
//scene.setBackgroundBrush(QPixmap(":/image/Resources/image/background.png"));
|
//scene.setBackgroundBrush(QPixmap(":/image/Resources/image/background.png"));
|
||||||
|
@ -85,6 +85,7 @@ void GameController::gameReset()
|
||||||
timeID = 0;
|
timeID = 0;
|
||||||
// 重置游戏
|
// 重置游戏
|
||||||
chess.reset();
|
chess.reset();
|
||||||
|
chessTemp.reset();
|
||||||
|
|
||||||
// 清除棋子
|
// 清除棋子
|
||||||
qDeleteAll(pieceList);
|
qDeleteAll(pieceList);
|
||||||
|
@ -109,6 +110,7 @@ void GameController::gameReset()
|
||||||
manualListModel.removeRows(0, manualListModel.rowCount());
|
manualListModel.removeRows(0, manualListModel.rowCount());
|
||||||
manualListModel.insertRow(0);
|
manualListModel.insertRow(0);
|
||||||
manualListModel.setData(manualListModel.index(0), chess.getCmdLine());
|
manualListModel.setData(manualListModel.index(0), chess.getCmdLine());
|
||||||
|
|
||||||
// 发出信号通知主窗口更新LCD显示
|
// 发出信号通知主窗口更新LCD显示
|
||||||
QTime qtime = QTime(0, 0, 0, 0).addMSecs(time1);
|
QTime qtime = QTime(0, 0, 0, 0).addMSecs(time1);
|
||||||
emit time1Changed(qtime.toString("mm:ss.zzz"));
|
emit time1Changed(qtime.toString("mm:ss.zzz"));
|
||||||
|
@ -129,7 +131,7 @@ void GameController::setInvert(bool arg)
|
||||||
{
|
{
|
||||||
isInverted = arg;
|
isInverted = arg;
|
||||||
// 遍历所有棋子
|
// 遍历所有棋子
|
||||||
foreach(PieceItem * p, pieceList)
|
for (PieceItem * p : pieceList)
|
||||||
{
|
{
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
|
@ -150,12 +152,15 @@ void GameController::setRule(int ruleNo, int stepLimited /*= -1*/, int timeLimit
|
||||||
// 更新规则,原限时和限步不变
|
// 更新规则,原限时和限步不变
|
||||||
if (ruleNo < 0 || ruleNo >= NineChess::RULENUM)
|
if (ruleNo < 0 || ruleNo >= NineChess::RULENUM)
|
||||||
return;
|
return;
|
||||||
|
this->ruleNo = ruleNo;
|
||||||
|
|
||||||
if (stepLimited != -1 && timeLimited != -1) {
|
if (stepLimited != -1 && timeLimited != -1) {
|
||||||
stepsLimit = stepLimited;
|
stepsLimit = stepLimited;
|
||||||
timeLimit = timeLimited;
|
timeLimit = timeLimited;
|
||||||
}
|
}
|
||||||
// 设置模型规则,重置游戏
|
// 设置模型规则,重置游戏
|
||||||
chess.setData(&NineChess::RULES[ruleNo], stepsLimit, timeLimit);
|
chess.setData(&NineChess::RULES[ruleNo], stepsLimit, timeLimit);
|
||||||
|
chessTemp = chess;
|
||||||
|
|
||||||
// 重置游戏
|
// 重置游戏
|
||||||
gameReset();
|
gameReset();
|
||||||
|
@ -253,6 +258,21 @@ void GameController::timerEvent(QTimerEvent *event)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 历史局面
|
||||||
|
void GameController::phaseChange(int row, bool change /*= false*/)
|
||||||
|
{
|
||||||
|
int rows = manualListModel.rowCount();
|
||||||
|
QStringList mlist = manualListModel.stringList();
|
||||||
|
qDebug() << "rows: " << rows;
|
||||||
|
for (int i = 0; i <= row; i++)
|
||||||
|
{
|
||||||
|
qDebug() << mlist.at(i);
|
||||||
|
chessTemp.command(mlist.at(i).toStdString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
updateScence(chessTemp);
|
||||||
|
}
|
||||||
|
|
||||||
// 槽函数,根据QGraphicsScene的信号和状态来执行选子、落子或去子
|
// 槽函数,根据QGraphicsScene的信号和状态来执行选子、落子或去子
|
||||||
bool GameController::actionPiece(QPointF pos)
|
bool GameController::actionPiece(QPointF pos)
|
||||||
{
|
{
|
||||||
|
@ -300,12 +320,13 @@ bool GameController::actionPiece(QPointF pos)
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
int row = manualListModel.rowCount();
|
int row = manualListModel.rowCount();
|
||||||
int size = chess.getCmdList()->size();
|
int c = 0;
|
||||||
auto i = (chess.getCmdList())->rbegin();
|
|
||||||
// 输出命令行
|
// 输出命令行
|
||||||
for (int n = size - row; n > 0; n--) {
|
for (auto i = (chess.getCmdList())->begin(); i != (chess.getCmdList())->end(); ++i) {
|
||||||
manualListModel.insertRow(row);
|
if (++c <= row)
|
||||||
manualListModel.setData(manualListModel.index(row), (*(i++)).c_str());
|
continue;
|
||||||
|
manualListModel.insertRow(c - 1);
|
||||||
|
manualListModel.setData(manualListModel.index(c - 1), (*i).c_str());
|
||||||
}
|
}
|
||||||
if (chess.whoWin() != NineChess::NOBODY)
|
if (chess.whoWin() != NineChess::NOBODY)
|
||||||
playSound(soundWin);
|
playSound(soundWin);
|
||||||
|
@ -314,11 +335,6 @@ bool GameController::actionPiece(QPointF pos)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 历史局面
|
|
||||||
void GameController::phaseChange(const QModelIndex &index)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// 选子
|
// 选子
|
||||||
PieceItem *GameController::choosePiece(QPointF pos)
|
PieceItem *GameController::choosePiece(QPointF pos)
|
||||||
{
|
{
|
||||||
|
@ -470,7 +486,7 @@ bool GameController::removePiece(QPointF pos)
|
||||||
|
|
||||||
bool GameController::cleanForbidden()
|
bool GameController::cleanForbidden()
|
||||||
{
|
{
|
||||||
foreach(PieceItem *p, pieceList)
|
for (PieceItem *p : pieceList)
|
||||||
{
|
{
|
||||||
if (p->isDeleted()) {
|
if (p->isDeleted()) {
|
||||||
pieceList.removeOne(p);
|
pieceList.removeOne(p);
|
||||||
|
@ -479,3 +495,46 @@ bool GameController::cleanForbidden()
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GameController::updateScence(NineChess &chess)
|
||||||
|
{
|
||||||
|
// 清除棋子
|
||||||
|
qDeleteAll(pieceList);
|
||||||
|
pieceList.clear();
|
||||||
|
piece = NULL;
|
||||||
|
|
||||||
|
const char *board = chess.getBoard();
|
||||||
|
|
||||||
|
for (int i = NineChess::SEAT; i < (NineChess::SEAT)*(NineChess::RING + 1); i++) {
|
||||||
|
QPointF pos = scene.cp2pos(i / NineChess::SEAT, i % NineChess::SEAT + 1);
|
||||||
|
if (board[i] & 0x30) {
|
||||||
|
PieceItem *newP = NULL;
|
||||||
|
PieceItem::Models md;
|
||||||
|
if (isInverted)
|
||||||
|
md = (board[i] & 0x10) ? PieceItem::whitePiece : PieceItem::blackPiece;
|
||||||
|
else
|
||||||
|
md = (board[i] & 0x10) ? PieceItem::blackPiece : PieceItem::whitePiece;
|
||||||
|
newP = new PieceItem;
|
||||||
|
newP->setModel(md);
|
||||||
|
newP->setPos(pos);
|
||||||
|
newP->setNum(chess.getPieceNum(i / NineChess::SEAT, i % NineChess::SEAT + 1));
|
||||||
|
// 如果重复三连不可用,则显示棋子序号
|
||||||
|
if (!(chess.getRule()->canRepeated))
|
||||||
|
newP->setShowNum(true);
|
||||||
|
pieceList.append(newP);
|
||||||
|
scene.addItem(newP);
|
||||||
|
}
|
||||||
|
else if (board[i] & 0x0F) {
|
||||||
|
PieceItem *newP = NULL;
|
||||||
|
newP = new PieceItem;
|
||||||
|
newP->setDeleted();
|
||||||
|
newP->setPos(pos);
|
||||||
|
pieceList.append(newP);
|
||||||
|
scene.addItem(newP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scene.clearSelection();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -15,8 +15,9 @@
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QStringListModel>
|
#include <QStringListModel>
|
||||||
#include <QModelIndex>
|
#include <QModelIndex>
|
||||||
#include "gamescene.h"
|
|
||||||
#include "ninechess.h"
|
#include "ninechess.h"
|
||||||
|
#include "gamescene.h"
|
||||||
|
//#include "sizehintlistview.h"
|
||||||
|
|
||||||
class PieceItem;
|
class PieceItem;
|
||||||
|
|
||||||
|
@ -29,6 +30,7 @@ public:
|
||||||
~GameController();
|
~GameController();
|
||||||
//主窗口菜单栏明细
|
//主窗口菜单栏明细
|
||||||
const QMap <int, QStringList> getActions();
|
const QMap <int, QStringList> getActions();
|
||||||
|
int getRuleNo() { return ruleNo; }
|
||||||
int getTimeLimit() { return timeLimit; }
|
int getTimeLimit() { return timeLimit; }
|
||||||
int getStepsLimit() { return stepsLimit; }
|
int getStepsLimit() { return stepsLimit; }
|
||||||
// 文本流
|
// 文本流
|
||||||
|
@ -45,6 +47,8 @@ signals:
|
||||||
void statusBarChanged(const QString & message);
|
void statusBarChanged(const QString & message);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
// 设置规则
|
||||||
|
void setRule(int ruleNo, int stepLimited = -1, int timeLimited = -1);
|
||||||
// 游戏开始
|
// 游戏开始
|
||||||
void gameStart();
|
void gameStart();
|
||||||
// 游戏重置
|
// 游戏重置
|
||||||
|
@ -53,8 +57,6 @@ public slots:
|
||||||
void setEditing(bool arg = true);
|
void setEditing(bool arg = true);
|
||||||
// 设置黑白反转状态
|
// 设置黑白反转状态
|
||||||
void setInvert(bool arg = true);
|
void setInvert(bool arg = true);
|
||||||
// 设置规则
|
|
||||||
void setRule(int ruleNo, int stepLimited = -1, int timeLimited = -1);
|
|
||||||
// 让电脑执先手
|
// 让电脑执先手
|
||||||
void setEngine1(bool arg = true);
|
void setEngine1(bool arg = true);
|
||||||
// 让电脑执后手
|
// 让电脑执后手
|
||||||
|
@ -67,11 +69,12 @@ public slots:
|
||||||
void playSound(QString &soundPath);
|
void playSound(QString &soundPath);
|
||||||
// 根据QGraphicsScene的信号和状态来执行选子、落子或去子
|
// 根据QGraphicsScene的信号和状态来执行选子、落子或去子
|
||||||
bool actionPiece(QPointF p);
|
bool actionPiece(QPointF p);
|
||||||
// 历史局面
|
// 历史局面及局面改变
|
||||||
void phaseChange(const QModelIndex &index);
|
void phaseChange(int row, bool change = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool eventFilter(QObject * watched, QEvent * event);
|
bool eventFilter(QObject * watched, QEvent * event);
|
||||||
|
// 定时器
|
||||||
void timerEvent(QTimerEvent * event);
|
void timerEvent(QTimerEvent * event);
|
||||||
// 选子
|
// 选子
|
||||||
PieceItem *choosePiece(QPointF pos);
|
PieceItem *choosePiece(QPointF pos);
|
||||||
|
@ -83,12 +86,18 @@ protected:
|
||||||
bool removePiece(QPointF pos);
|
bool removePiece(QPointF pos);
|
||||||
// 删除禁止点子
|
// 删除禁止点子
|
||||||
bool cleanForbidden();
|
bool cleanForbidden();
|
||||||
|
// 更新棋局显示
|
||||||
|
bool updateScence(NineChess &chess);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// 棋对象的数据模型
|
// 棋对象的数据模型
|
||||||
NineChess chess;
|
NineChess chess;
|
||||||
|
// 棋对象的数据模型(临时)
|
||||||
|
NineChess chessTemp;
|
||||||
// 棋局的场景类
|
// 棋局的场景类
|
||||||
GameScene &scene;
|
GameScene &scene;
|
||||||
|
// 棋谱列表
|
||||||
|
//SizeHintListView &listView;
|
||||||
// 所有棋子
|
// 所有棋子
|
||||||
QList<PieceItem *> pieceList;
|
QList<PieceItem *> pieceList;
|
||||||
// 当前棋子
|
// 当前棋子
|
||||||
|
@ -109,6 +118,8 @@ private:
|
||||||
bool hasSound;
|
bool hasSound;
|
||||||
// 定时器ID
|
// 定时器ID
|
||||||
int timeID;
|
int timeID;
|
||||||
|
// 规则变化
|
||||||
|
int ruleNo;
|
||||||
// 规则限时(分钟)
|
// 规则限时(分钟)
|
||||||
int timeLimit;
|
int timeLimit;
|
||||||
// 规则限步数
|
// 规则限步数
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "gamescene.h"
|
#include "gamescene.h"
|
||||||
#include "pieceitem.h"
|
#include "pieceitem.h"
|
||||||
#include "boarditem.h"
|
#include "boarditem.h"
|
||||||
#include <QGraphicsItem>
|
#include <QGraphicsItem>
|
||||||
|
@ -50,7 +50,7 @@ void GameScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 取消其它棋子的选中状态
|
// 取消其它棋子的选中状态
|
||||||
//foreach (QGraphicsItem * item, selectedItems())
|
//for (QGraphicsItem * item: selectedItems())
|
||||||
//{
|
//{
|
||||||
// item->setSelected(false);
|
// item->setSelected(false);
|
||||||
//}
|
//}
|
||||||
|
@ -81,12 +81,17 @@ void GameScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPointF GameScene::cp2pos(int c, int p)
|
||||||
|
{
|
||||||
|
return board->cp2pos(c, p);
|
||||||
|
}
|
||||||
|
|
||||||
bool GameScene::pos2cp(QPointF pos, int &c, int &p)
|
bool GameScene::pos2cp(QPointF pos, int &c, int &p)
|
||||||
{
|
{
|
||||||
return board->pos2cp(pos, c, p);
|
return board->pos2cp(pos, c, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameScene::setDiagonal(bool arg)
|
void GameScene::setDiagonal(bool arg /*= true*/)
|
||||||
{
|
{
|
||||||
if (board)
|
if (board)
|
||||||
board->setDiagonal(arg);
|
board->setDiagonal(arg);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef GAMESCENE_H
|
#ifndef GAMESCENE_H
|
||||||
#define GAMESCENE_H
|
#define GAMESCENE_H
|
||||||
|
|
||||||
#include <QGraphicsScene>
|
#include <QGraphicsScene>
|
||||||
|
@ -11,6 +11,8 @@ class GameScene : public QGraphicsScene
|
||||||
public:
|
public:
|
||||||
explicit GameScene(QObject *parent = nullptr);
|
explicit GameScene(QObject *parent = nullptr);
|
||||||
~GameScene();
|
~GameScene();
|
||||||
|
// 将模型的圈、位转化为落子点坐标
|
||||||
|
QPointF cp2pos(int c, int p);
|
||||||
// 将落子点坐标转化为模型用的圈、位
|
// 将落子点坐标转化为模型用的圈、位
|
||||||
bool pos2cp(QPointF pos, int &c, int &p);
|
bool pos2cp(QPointF pos, int &c, int &p);
|
||||||
// 设置棋盘斜线
|
// 设置棋盘斜线
|
||||||
|
|
|
@ -130,7 +130,9 @@ bool NineChess::setData(const struct Rule *rule, int s, int t, int step, int fla
|
||||||
this->rule.maxTime = t;
|
this->rule.maxTime = t;
|
||||||
// 设置步数
|
// 设置步数
|
||||||
this->step = step;
|
this->step = step;
|
||||||
|
|
||||||
// 设置状态
|
// 设置状态
|
||||||
|
|
||||||
// 局面阶段标识
|
// 局面阶段标识
|
||||||
if (flags & GAME_NOTSTARTED)
|
if (flags & GAME_NOTSTARTED)
|
||||||
phase = GAME_NOTSTARTED;
|
phase = GAME_NOTSTARTED;
|
||||||
|
@ -327,9 +329,72 @@ void NineChess::getData(struct Rule &rule, int &step, int &chess, const char *&b
|
||||||
num_NeedRemove = this->num_NeedRemove;
|
num_NeedRemove = this->num_NeedRemove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char * NineChess::getBoard()
|
||||||
|
{
|
||||||
|
return board;
|
||||||
|
}
|
||||||
|
|
||||||
bool NineChess::reset()
|
bool NineChess::reset()
|
||||||
{
|
{
|
||||||
return setData(&rule);
|
if (phase == GAME_NOTSTARTED && player1_MS == player2_MS == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// 步数归零
|
||||||
|
step = 0;
|
||||||
|
|
||||||
|
// 局面阶段标识
|
||||||
|
phase = GAME_NOTSTARTED;
|
||||||
|
|
||||||
|
// 轮流状态标识
|
||||||
|
turn = PLAYER1;
|
||||||
|
|
||||||
|
// 动作状态标识
|
||||||
|
action = ACTION_PLACE;
|
||||||
|
|
||||||
|
// 胜负标识
|
||||||
|
winner = NOBODY;
|
||||||
|
|
||||||
|
// 当前棋局(3×8)
|
||||||
|
memset(board, 0, sizeof(board));
|
||||||
|
|
||||||
|
// 盘面子数归零
|
||||||
|
player1_Remain = player2_Remain = 0;
|
||||||
|
|
||||||
|
// 设置玩家盘面剩余子数和未放置子数
|
||||||
|
player1_InHand = player2_InHand = rule.numOfChess;
|
||||||
|
|
||||||
|
// 设置去子状态时的剩余尚待去除子数
|
||||||
|
num_NeedRemove = 0;
|
||||||
|
|
||||||
|
// 清空成三记录
|
||||||
|
millList.clear();
|
||||||
|
|
||||||
|
// 不选中棋子
|
||||||
|
posOfSelected = 0;
|
||||||
|
|
||||||
|
// 用时置零
|
||||||
|
player1_MS = player2_MS = 0;
|
||||||
|
|
||||||
|
// 提示
|
||||||
|
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, rule.maxSteps, rule.maxTime) > 0) {
|
||||||
|
cmdlist.push_back(string(cmdline));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cmdline[0] = '\0';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NineChess::start()
|
bool NineChess::start()
|
||||||
|
@ -362,9 +427,13 @@ int NineChess::cp2pos(int c, int p)
|
||||||
|
|
||||||
bool NineChess::place(int c, int p, long time_p /* = -1*/)
|
bool NineChess::place(int c, int p, long time_p /* = -1*/)
|
||||||
{
|
{
|
||||||
// 如果局面为"未开局"或“结局”,返回false
|
// 如果局面为“结局”,返回false
|
||||||
if (phase == GAME_NOTSTARTED || phase == GAME_OVER)
|
if (phase == GAME_OVER)
|
||||||
return false;
|
return false;
|
||||||
|
// 如果局面为“未开局”,则开具
|
||||||
|
if (phase == GAME_NOTSTARTED)
|
||||||
|
start();
|
||||||
|
|
||||||
// 如非“落子”状态,返回false
|
// 如非“落子”状态,返回false
|
||||||
if (action != ACTION_PLACE)
|
if (action != ACTION_PLACE)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -102,6 +102,8 @@ public:
|
||||||
|
|
||||||
// 获取棋局状态和棋盘数据
|
// 获取棋局状态和棋盘数据
|
||||||
void getData(struct Rule &rule, int &step, int &flags, const char *&boardsource, int &p1_InHand, int &p2_InHand, int &num_NeedRemove);
|
void getData(struct Rule &rule, int &step, int &flags, const char *&boardsource, int &p1_InHand, int &p2_InHand, int &num_NeedRemove);
|
||||||
|
// 获取棋盘数据
|
||||||
|
const char *getBoard();
|
||||||
// 获取当前规则
|
// 获取当前规则
|
||||||
const struct Rule *getRule() { return &rule; }
|
const struct Rule *getRule() { return &rule; }
|
||||||
// 获取当前步数
|
// 获取当前步数
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#if _MSC_VER >= 1600
|
#if _MSC_VER >= 1600
|
||||||
#pragma execution_character_set("utf-8")
|
#pragma execution_character_set("utf-8")
|
||||||
#endif
|
#endif
|
||||||
#include "ninechesswindow.h"
|
|
||||||
#include "gamecontroller.h"
|
|
||||||
#include "gamescene.h"
|
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
@ -19,6 +16,10 @@
|
||||||
#include <QHelpEvent>
|
#include <QHelpEvent>
|
||||||
#include <QToolTip>
|
#include <QToolTip>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include "ninechesswindow.h"
|
||||||
|
#include "gamecontroller.h"
|
||||||
|
#include "gamescene.h"
|
||||||
|
#include "graphicsconst.h"
|
||||||
|
|
||||||
NineChessWindow::NineChessWindow(QWidget *parent)
|
NineChessWindow::NineChessWindow(QWidget *parent)
|
||||||
: QMainWindow(parent),
|
: QMainWindow(parent),
|
||||||
|
@ -36,6 +37,9 @@ NineChessWindow::NineChessWindow(QWidget *parent)
|
||||||
|
|
||||||
// 设置场景
|
// 设置场景
|
||||||
scene = new GameScene(this);
|
scene = new GameScene(this);
|
||||||
|
// 设置场景尺寸大小为棋盘大小的1.08倍
|
||||||
|
scene->setSceneRect(-BOARD_SIZE * 0.54, -BOARD_SIZE * 0.54, BOARD_SIZE*1.08, BOARD_SIZE*1.08);
|
||||||
|
|
||||||
// 初始化各个控件
|
// 初始化各个控件
|
||||||
|
|
||||||
// 关联视图和场景
|
// 关联视图和场景
|
||||||
|
@ -81,7 +85,6 @@ NineChessWindow::~NineChessWindow()
|
||||||
if (game != NULL)
|
if (game != NULL)
|
||||||
delete game;
|
delete game;
|
||||||
qDeleteAll(ruleActionList);
|
qDeleteAll(ruleActionList);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NineChessWindow::eventFilter(QObject *watched, QEvent *event)
|
bool NineChessWindow::eventFilter(QObject *watched, QEvent *event)
|
||||||
|
@ -142,8 +145,6 @@ void NineChessWindow::initialize()
|
||||||
game, SLOT(setSound(bool)));
|
game, SLOT(setSound(bool)));
|
||||||
connect(ui.actionAnimation_A, SIGNAL(toggled(bool)),
|
connect(ui.actionAnimation_A, SIGNAL(toggled(bool)),
|
||||||
game, SLOT(setAnimation(bool)));
|
game, SLOT(setAnimation(bool)));
|
||||||
connect(ui.listView, SIGNAL(activated(const QModelIndex &index)),
|
|
||||||
game, SLOT(phaseChange(const QModelIndex &index)));
|
|
||||||
|
|
||||||
/* 关联控制器的信号和主窗口控件的槽
|
/* 关联控制器的信号和主窗口控件的槽
|
||||||
注意,采用信号和槽而非采用在GameController中直接控制NineChessWindow
|
注意,采用信号和槽而非采用在GameController中直接控制NineChessWindow
|
||||||
|
@ -169,15 +170,12 @@ void NineChessWindow::initialize()
|
||||||
|
|
||||||
// 默认第2号规则
|
// 默认第2号规则
|
||||||
ruleNo = 2;
|
ruleNo = 2;
|
||||||
|
|
||||||
// 设置选中当前规则的菜单项
|
// 设置选中当前规则的菜单项
|
||||||
ruleActionList.at(ruleNo)->setChecked(true);
|
ruleActionList.at(ruleNo)->setChecked(true);
|
||||||
|
|
||||||
// 重置游戏规则
|
// 重置游戏规则
|
||||||
game->setRule(ruleNo);
|
game->setRule(ruleNo);
|
||||||
// 规则提示
|
// 更新规则显示
|
||||||
//QString tip_Rule = QString("%1\n%2").arg(tr(NineChess::RULES[ruleNo].name))
|
ruleInfo();
|
||||||
// .arg(tr(NineChess::RULES[ruleNo].info));
|
|
||||||
|
|
||||||
// 关联列表视图和字符串列表模型
|
// 关联列表视图和字符串列表模型
|
||||||
ui.listView->setModel(& game->manualListModel);
|
ui.listView->setModel(& game->manualListModel);
|
||||||
|
@ -201,11 +199,33 @@ void NineChessWindow::initialize()
|
||||||
on_actionRowChange();
|
on_actionRowChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NineChessWindow::ruleInfo()
|
||||||
|
{
|
||||||
|
int s = game->getStepsLimit();
|
||||||
|
int t = game->getTimeLimit();
|
||||||
|
QString tl(" 不限时");
|
||||||
|
QString sl(" 不限步");
|
||||||
|
if (s > 0)
|
||||||
|
sl = " 限" + QString::number(s) + "步";
|
||||||
|
if (t > 0)
|
||||||
|
tl = " 限时" + QString::number(s) + "分";
|
||||||
|
|
||||||
|
// 规则显示
|
||||||
|
ui.labelRule->setText(tl + sl);
|
||||||
|
// 规则提示
|
||||||
|
ui.labelInfo->setToolTip(QString(NineChess::RULES[ruleNo].name) + "\n" +
|
||||||
|
NineChess::RULES[ruleNo].info);
|
||||||
|
ui.labelRule->setToolTip(ui.labelInfo->toolTip());
|
||||||
|
|
||||||
|
//QString tip_Rule = QString("%1\n%2").arg(tr(NineChess::RULES[ruleNo].name))
|
||||||
|
// .arg(tr(NineChess::RULES[ruleNo].info));
|
||||||
|
}
|
||||||
|
|
||||||
void NineChessWindow::actionRules_triggered()
|
void NineChessWindow::actionRules_triggered()
|
||||||
{
|
{
|
||||||
// setChecked函数会发出toggled信号,在这里响应toggled信号会陷入死循环
|
// setChecked函数会发出toggled信号,在这里响应toggled信号会陷入死循环
|
||||||
// 取消其它规则的选择
|
// 取消其它规则的选择
|
||||||
foreach(QAction *action, ruleActionList)
|
for(QAction *action: ruleActionList)
|
||||||
action->setChecked(false);
|
action->setChecked(false);
|
||||||
// 选择当前规则
|
// 选择当前规则
|
||||||
QAction *action = dynamic_cast<QAction *>(sender());
|
QAction *action = dynamic_cast<QAction *>(sender());
|
||||||
|
@ -213,9 +233,8 @@ void NineChessWindow::actionRules_triggered()
|
||||||
ruleNo = action->data().toInt();
|
ruleNo = action->data().toInt();
|
||||||
// 重置游戏规则
|
// 重置游戏规则
|
||||||
game->setRule(ruleNo);
|
game->setRule(ruleNo);
|
||||||
// 规则提示
|
// 更新规则显示
|
||||||
//QString tip_Rule = QString("%1\n%2").arg(tr(NineChess::RULES[ruleNo].name))
|
ruleInfo();
|
||||||
// .arg(tr(NineChess::RULES[ruleNo].info));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -292,45 +311,56 @@ void NineChessWindow::on_actionInvert_I_toggled(bool arg1)
|
||||||
// 前后招的公共槽
|
// 前后招的公共槽
|
||||||
void NineChessWindow::on_actionRowChange()
|
void NineChessWindow::on_actionRowChange()
|
||||||
{
|
{
|
||||||
QModelIndex index = ui.listView->currentIndex();
|
QAbstractItemModel * model = ui.listView->model();
|
||||||
int row = index.row();
|
int rows = model->rowCount();
|
||||||
|
int currentRow = ui.listView->currentIndex().row();
|
||||||
|
|
||||||
QObject * const obsender = this->sender();
|
QObject * const obsender = sender();
|
||||||
if (obsender != NULL) {
|
if (obsender != NULL) {
|
||||||
if (obsender == (QObject *)ui.actionBegin_S) {
|
if (obsender == (QObject *)ui.actionBegin_S) {
|
||||||
ui.listView->setCurrentIndex(ui.listView->model()->index(0, 0));
|
ui.listView->setCurrentIndex(model->index(0, 0));
|
||||||
}
|
}
|
||||||
else if (obsender == (QObject *)ui.actionPrevious_B) {
|
else if (obsender == (QObject *)ui.actionPrevious_B) {
|
||||||
if (row > 0) {
|
if (currentRow > 0) {
|
||||||
ui.listView->setCurrentIndex(ui.listView->model()->index(row - 1, 0));
|
ui.listView->setCurrentIndex(model->index(currentRow - 1, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (obsender == (QObject *)ui.actionNext_F) {
|
else if (obsender == (QObject *)ui.actionNext_F) {
|
||||||
if (row < ui.listView->model()->rowCount() - 1) {
|
if (currentRow < rows - 1) {
|
||||||
ui.listView->setCurrentIndex(ui.listView->model()->index(row + 1, 0));
|
ui.listView->setCurrentIndex(model->index(currentRow + 1, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (obsender == (QObject *)ui.actionEnd_E) {
|
else if (obsender == (QObject *)ui.actionEnd_E) {
|
||||||
ui.listView->setCurrentIndex(ui.listView->model()->index(ui.listView->model()->rowCount() - 1, 0));
|
ui.listView->setCurrentIndex(model->index(rows - 1, 0));
|
||||||
}
|
}
|
||||||
|
currentRow = ui.listView->currentIndex().row();
|
||||||
}
|
}
|
||||||
|
|
||||||
index = ui.listView->currentIndex();
|
// 更新动作状态
|
||||||
row = index.row();
|
if (rows <= 1) {
|
||||||
ui.actionBegin_S->setEnabled(true);
|
|
||||||
ui.actionPrevious_B->setEnabled(true);
|
|
||||||
ui.actionNext_F->setEnabled(true);
|
|
||||||
ui.actionEnd_E->setEnabled(true);
|
|
||||||
if (row <= 0) {
|
|
||||||
ui.actionBegin_S->setEnabled(false);
|
ui.actionBegin_S->setEnabled(false);
|
||||||
ui.actionPrevious_B->setEnabled(false);
|
ui.actionPrevious_B->setEnabled(false);
|
||||||
}
|
|
||||||
if (row >= ui.listView->model()->rowCount()-1)
|
|
||||||
{
|
|
||||||
ui.actionNext_F->setEnabled(false);
|
ui.actionNext_F->setEnabled(false);
|
||||||
ui.actionEnd_E->setEnabled(false);
|
ui.actionEnd_E->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if (currentRow <= 0) {
|
||||||
|
ui.actionBegin_S->setEnabled(false);
|
||||||
|
ui.actionPrevious_B->setEnabled(false);
|
||||||
|
ui.actionNext_F->setEnabled(true);
|
||||||
|
ui.actionEnd_E->setEnabled(true);
|
||||||
|
}
|
||||||
|
if (currentRow >= rows - 1)
|
||||||
|
{
|
||||||
|
ui.actionBegin_S->setEnabled(true);
|
||||||
|
ui.actionPrevious_B->setEnabled(true);
|
||||||
|
ui.actionNext_F->setEnabled(false);
|
||||||
|
ui.actionEnd_E->setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新局面
|
||||||
|
game->phaseChange(currentRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NineChessWindow::on_actionAutoRun_A_toggled(bool arg1)
|
void NineChessWindow::on_actionAutoRun_A_toggled(bool arg1)
|
||||||
|
@ -413,6 +443,10 @@ void NineChessWindow::on_actionLimited_T_triggered()
|
||||||
// 重置游戏规则
|
// 重置游戏规则
|
||||||
game->setRule(ruleNo, stepLimited, timeLimited);
|
game->setRule(ruleNo, stepLimited, timeLimited);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新规则显示
|
||||||
|
ruleInfo();
|
||||||
|
|
||||||
// 删除对话框,子控件会一并删除
|
// 删除对话框,子控件会一并删除
|
||||||
delete dialog;
|
delete dialog;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ private:
|
||||||
int ruleNo;
|
int ruleNo;
|
||||||
// 文件
|
// 文件
|
||||||
QFile file;
|
QFile file;
|
||||||
|
// 更新规则标签
|
||||||
|
void ruleInfo();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
// 初始化
|
// 初始化
|
||||||
|
|
|
@ -30,10 +30,14 @@ signals:
|
||||||
// 需要一个currentChanged信号,但默认没有,需要把这个槽改造成信号
|
// 需要一个currentChanged信号,但默认没有,需要把这个槽改造成信号
|
||||||
void currentChangedSignal(const QModelIndex ¤t, const QModelIndex &previous);
|
void currentChangedSignal(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
|
|
||||||
protected:
|
protected slots:
|
||||||
// 屏蔽掉双击编辑功能
|
// 屏蔽掉双击编辑功能
|
||||||
void mouseDoubleClickEvent(QMouseEvent *event) {}
|
void mouseDoubleClickEvent(QMouseEvent *event) {}
|
||||||
// 插入新行后自动选中最后一个
|
|
||||||
|
/* 本来重载rowsInserted函数用于在插入新行后自动选中最后一行,
|
||||||
|
但是,在关联Model的insertRow执行后rowsInserted会被立即执行,
|
||||||
|
此时,Model的setData还未被执行,会选中一个空行。
|
||||||
|
所以不再采用这种方式,而是在控制模块中指定。
|
||||||
void rowsInserted(const QModelIndex &parent, int start, int end) {
|
void rowsInserted(const QModelIndex &parent, int start, int end) {
|
||||||
// 调用父类函数,为使滚动条更新,否则scrollToBottom不能正确执行。
|
// 调用父类函数,为使滚动条更新,否则scrollToBottom不能正确执行。
|
||||||
QListView::rowsInserted(parent, start, end);
|
QListView::rowsInserted(parent, start, end);
|
||||||
|
@ -41,6 +45,21 @@ protected:
|
||||||
setCurrentIndex(id);
|
setCurrentIndex(id);
|
||||||
scrollToBottom();
|
scrollToBottom();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 采用判断最后一个元素是否改变来选中之
|
||||||
|
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
||||||
|
const QVector<int> &roles = QVector<int>()) {
|
||||||
|
QAbstractItemView::dataChanged(topLeft, bottomRight, roles);
|
||||||
|
QModelIndex index = model()->index(model()->rowCount() - 1, 0);
|
||||||
|
if (topLeft == bottomRight) {
|
||||||
|
if (index == bottomRight) {
|
||||||
|
setCurrentIndex(index);
|
||||||
|
scrollToBottom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 需要一个currentChanged信号,但默认没有,需要把这个槽改造成信号
|
// 需要一个currentChanged信号,但默认没有,需要把这个槽改造成信号
|
||||||
// activated信号需要按下回车才发出,selectedChanged和clicked信号也不合适
|
// activated信号需要按下回车才发出,selectedChanged和clicked信号也不合适
|
||||||
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) {
|
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) {
|
||||||
|
|
Loading…
Reference in New Issue