调整代码格式

This commit is contained in:
CalciteM Team 2019-06-28 23:05:28 +08:00
parent ffac849fac
commit be80990f93
12 changed files with 231 additions and 98 deletions

View File

@ -54,6 +54,7 @@ void AiThread::run()
while (!isInterruptionRequested()) {
mutex.lock();
if (chess_->whosTurn() == NineChess::PLAYER1)
i = 1;
else if (chess_->whosTurn() == NineChess::PLAYER2)
@ -74,11 +75,14 @@ void AiThread::run()
ai_ab.alphaBetaPruning(aiDepth);
const char *str = ai_ab.bestMove();
qDebug() << "Computer:" << str << "\n";
if (strcmp(str, "error!"))
emit command(str);
#ifdef DEBUG
qDebug() << "Thread" << id << "run" << ++iTemp << "times";
#endif
emit calcFinished();
// 执行完毕后继续判断

View File

@ -3,40 +3,41 @@
#include <QPainter>
BoardItem::BoardItem(QGraphicsItem *parent) : QGraphicsItem(),
size(BOARD_SIZE),
sizeShadow(5.0),
hasObliqueLine(false)
size(BOARD_SIZE),
sizeShadow(5.0),
hasObliqueLine(false)
{
Q_UNUSED(parent)
// 棋盘中心放在场景中心
setPos(0, 0);
// 初始化24个落子点
for (int i = 0; i < RING; i++) {
for (int i = 0; i < N_RINGS; i++) {
// 内圈的12点钟方向为第一个位置按顺时针方向排序
// 然后是中圈和外圈
qreal a = (i + 1) * LINE_INTERVAL;
position[i * SEAT + 0].rx() = 0;
position[i * SEAT + 0].ry() = -a;
position[i * SEAT + 1].rx() = a;
position[i * SEAT + 1].ry() = -a;
position[i * SEAT + 2].rx() = a;
position[i * SEAT + 2].ry() = 0;
position[i * SEAT + 3].rx() = a;
position[i * SEAT + 3].ry() = a;
position[i * SEAT + 4].rx() = 0;
position[i * SEAT + 4].ry() = a;
position[i * SEAT + 5].rx() = -a;
position[i * SEAT + 5].ry() = a;
position[i * SEAT + 6].rx() = -a;
position[i * SEAT + 6].ry() = 0;
position[i * SEAT + 7].rx() = -a;
position[i * SEAT + 7].ry() = -a;
position[i * N_SEATS + 0].rx() = 0;
position[i * N_SEATS + 0].ry() = -a;
position[i * N_SEATS + 1].rx() = a;
position[i * N_SEATS + 1].ry() = -a;
position[i * N_SEATS + 2].rx() = a;
position[i * N_SEATS + 2].ry() = 0;
position[i * N_SEATS + 3].rx() = a;
position[i * N_SEATS + 3].ry() = a;
position[i * N_SEATS + 4].rx() = 0;
position[i * N_SEATS + 4].ry() = a;
position[i * N_SEATS + 5].rx() = -a;
position[i * N_SEATS + 5].ry() = a;
position[i * N_SEATS + 6].rx() = -a;
position[i * N_SEATS + 6].ry() = 0;
position[i * N_SEATS + 7].rx() = -a;
position[i * N_SEATS + 7].ry() = -a;
}
}
BoardItem::~BoardItem()
{
}
QRectF BoardItem::boundingRect() const
@ -57,19 +58,19 @@ void BoardItem::setDiagonal(bool arg)
update(boundingRect());
}
void BoardItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
Q_UNUSED(widget)
// 填充阴影
painter->fillRect(boundingRect(), QBrush(QColor(64, 64, 64)));
// 填充图片
painter->drawPixmap(-size / 2, -size / 2, size, size, QPixmap(":/image/resources/image/board.png"));
painter->drawPixmap(-size / 2, -size / 2, size, size,
QPixmap(":/image/resources/image/board.png"));
// 黑色实线画笔
QPen pen(QBrush(Qt::black), LINE_WEIGHT, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin);
@ -78,25 +79,26 @@ void BoardItem::paint(QPainter *painter,
// 空画刷
painter->setBrush(Qt::NoBrush);
for (int i = 0; i < RING; i++) {
for (uint8_t i = 0; i < N_RINGS; i++) {
// 画3个方框
painter->drawPolygon(position + i * SEAT, SEAT);
painter->drawPolygon(position + i * N_SEATS, N_SEATS);
}
// 画4条纵横线
painter->drawLine(position[0], position[(RING - 1) * SEAT]);
painter->drawLine(position[2], position[(RING - 1) * SEAT + 2]);
painter->drawLine(position[4], position[(RING - 1) * SEAT + 4]);
painter->drawLine(position[6], position[(RING - 1) * SEAT + 6]);
painter->drawLine(position[0], position[(N_RINGS - 1) * N_SEATS]);
painter->drawLine(position[2], position[(N_RINGS - 1) * N_SEATS + 2]);
painter->drawLine(position[4], position[(N_RINGS - 1) * N_SEATS + 4]);
painter->drawLine(position[6], position[(N_RINGS - 1) * N_SEATS + 6]);
if (hasObliqueLine) {
// 画4条斜线
painter->drawLine(position[1], position[(RING - 1) * SEAT + 1]);
painter->drawLine(position[3], position[(RING - 1) * SEAT + 3]);
painter->drawLine(position[5], position[(RING - 1) * SEAT + 5]);
painter->drawLine(position[7], position[(RING - 1) * SEAT + 7]);
painter->drawLine(position[1], position[(N_RINGS - 1) * N_SEATS + 1]);
painter->drawLine(position[3], position[(N_RINGS - 1) * N_SEATS + 3]);
painter->drawLine(position[5], position[(N_RINGS - 1) * N_SEATS + 5]);
painter->drawLine(position[7], position[(N_RINGS - 1) * N_SEATS + 7]);
}
#ifdef DRAW_SEAT_NUMBER
// 画 Seat 编号
QPen fontPen(QBrush(Qt::white), LINE_WEIGHT, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin);
painter->setPen(fontPen);
@ -109,8 +111,9 @@ void BoardItem::paint(QPainter *painter,
for (int i = 0; i < 8; i++) {
char cSeat = '1' + i;
QString strSeat(cSeat);
painter->drawText(position[(RING - 1) * SEAT + i], strSeat);
painter->drawText(position[(N_RINGS - 1) * N_SEATS + i], strSeat);
}
#endif // DRAW_SEAT_NUMBER
}
QPointF BoardItem::nearestPosition(QPointF const pos)
@ -119,7 +122,7 @@ QPointF BoardItem::nearestPosition(QPointF const pos)
QPointF nearestPos = QPointF(0, 0);
// 寻找最近的落子点
for (int i = 0; i < RING * SEAT; i++) {
for (int i = 0; i < N_RINGS * N_SEATS; i++) {
// 如果鼠标点距离落子点在棋子半径内
if (QLineF(pos, position[i]).length() < PIECE_SIZE / 2) {
nearestPos = position[i];
@ -131,17 +134,17 @@ QPointF BoardItem::nearestPosition(QPointF const pos)
QPointF BoardItem::cp2pos(int c, int p)
{
return position[(c - 1) * SEAT + p - 1];
return position[(c - 1) * N_SEATS + p - 1];
}
bool BoardItem::pos2cp(QPointF pos, int &c, int &p)
{
// 寻找最近的落子点
for (int i = 0; i < RING * SEAT; i++) {
for (int i = 0; i < N_RINGS * N_SEATS; i++) {
// 如果pos点在落子点附近
if (QLineF(pos, position[i]).length() < PIECE_SIZE / 6) {
c = i / SEAT + 1;
p = i % SEAT + 1;
c = i / N_SEATS + 1;
p = i % N_SEATS + 1;
return true;
}
}

View File

@ -10,8 +10,11 @@ class BoardItem : public QGraphicsItem
public:
explicit BoardItem(QGraphicsItem *parent = nullptr);
~BoardItem();
QRectF boundingRect() const;
QPainterPath shape() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget = nullptr);
@ -40,10 +43,10 @@ public:
bool pos2cp(QPointF pos, int &c, int &p);
// 3圈禁止修改
static const int RING = 3;
static const uint8_t N_RINGS = 3;
// 8位禁止修改
static const int SEAT = 8;
static const uint8_t N_SEATS = 8;
private:
// 棋盘尺寸
@ -53,7 +56,7 @@ private:
qreal sizeShadow;
// 24个落子点
QPointF position[RING * SEAT];
QPointF position[N_RINGS * N_SEATS];
// 是否有斜线
bool hasObliqueLine;

View File

@ -11,6 +11,9 @@
//#define AB_RANDOM_SORT_CHILDREN
// 调试博弈树 (耗费大量内存)
#define DEBUG_AB_TREE
//#define DEBUG_AB_TREE
// »æÖÆ SEAT ±àºÅ
#define DRAW_SEAT_NUMBER
#endif // CONFIG_H

View File

@ -48,7 +48,8 @@ GameController::GameController(GameScene & scene, QObject * parent) :
connect(&ai2, SIGNAL(command(const QString &, bool)),
this, SLOT(command(const QString &, bool)));
// 安装事件过滤器监视scene的各个事件由于我重载了QGraphicsScene相关事件在重载函数中已设定不必安装监视器。
// 安装事件过滤器监视scene的各个事件
// 由于我重载了QGraphicsScene相关事件在重载函数中已设定不必安装监视器。
//scene.installEventFilter(this);
}
@ -70,6 +71,7 @@ const QMap<int, QStringList> GameController::getActions()
// 主窗口更新菜单栏
// 之所以不用信号和槽的模式,是因为发信号的时候槽还来不及关联
QMap<int, QStringList> actions;
for (int i = 0; i < NineChess::N_RULES; i++) {
// QMap的key存放int索引值value存放规则名称和规则提示
QStringList strlist;
@ -77,6 +79,7 @@ const QMap<int, QStringList> GameController::getActions()
strlist.append(tr(NineChess::RULES[i].description));
actions.insert(i, strlist);
}
return actions;
}
@ -223,6 +226,7 @@ void GameController::setRule(int ruleNo, int stepLimited /*= -1*/, int timeLimit
stepsLimit = stepLimited;
timeLimit = timeLimited;
}
// 设置模型规则,重置游戏
chess_.setContext(&NineChess::RULES[ruleNo], stepsLimit, timeLimit);
chessTemp = chess_;
@ -368,6 +372,7 @@ void GameController::mirror()
// 更新棋谱
int row = 0;
for (auto str : *(chess_.getCmdList())) {
manualListModel.setData(manualListModel.index(row++), str.c_str());
}
@ -382,9 +387,11 @@ void GameController::mirror()
ai1.setAi(chess_);
ai2.setAi(chess_);
if (isEngine1) {
ai1.start();
}
if (isEngine2) {
ai2.start();
}
@ -407,6 +414,7 @@ void GameController::turnRight()
// 更新棋谱
int row = 0;
for (auto str : *(chess_.getCmdList())) {
manualListModel.setData(manualListModel.index(row++), str.c_str());
}
@ -419,9 +427,11 @@ void GameController::turnRight()
ai1.setAi(chess_);
ai2.setAi(chess_);
if (isEngine1) {
ai1.start();
}
if (isEngine2) {
ai2.start();
}
@ -478,6 +488,7 @@ void GameController::timerEvent(QTimerEvent *event)
qt1 = QTime(0, 0, 0, 0).addMSecs(remainingTime1);
qt2 = QTime(0, 0, 0, 0).addMSecs(remainingTime2);
emit time1Changed(qt1.toString("mm:ss.zzz"));
emit time2Changed(qt2.toString("mm:ss.zzz"));
@ -557,6 +568,7 @@ bool GameController::actionPiece(QPointF pos)
// 如果再决出胜负后悔棋,则重新启动计时
if (chess_.whoWin() == NineChess::NOBODY) {
// 重新启动计时
timeID = startTimer(100);
@ -591,7 +603,7 @@ bool GameController::actionPiece(QPointF pos)
break;
}
// 如果移子不成功尝试重新选子这里不break
// 如果移子不成功尝试重新选子这里不break
case NineChess::ACTION_CHOOSE:
piece = qgraphicsitem_cast<PieceItem *>(item);
@ -687,6 +699,7 @@ bool GameController::giveUp()
// 将新增的棋谱行插入到ListModel
currentRow = manualListModel.rowCount() - 1;
int k = 0;
// 输出命令行
for (auto i = (chess_.getCmdList())->begin(); i != (chess_.getCmdList())->end(); ++i) {
// 跳过已添加的因标准list容器没有下标
@ -698,6 +711,7 @@ bool GameController::giveUp()
if (chess_.whoWin() != NineChess::NOBODY)
playSound(":/sound/resources/sound/loss.wav");
}
return result;
}
@ -706,14 +720,16 @@ bool GameController::command(const QString &cmd, bool update /*= true*/)
{
Q_UNUSED(hasSound)
// 防止接收滞后结束的线程发送的指令
if (sender() == &ai1 && !isEngine1)
return false;
// 防止接收滞后结束的线程发送的指令
if (sender() == &ai1 && !isEngine1)
return false;
if (sender() == &ai2 && !isEngine2)
return false;
// 声音
QString sound;
switch (chess_.getAction()) {
case NineChess::ACTION_CHOOSE:
case NineChess::ACTION_PLACE:

View File

@ -29,14 +29,14 @@ GameScene::~GameScene()
}
// 屏蔽掉Shift和Control按键事实证明没用按键事件未必由视图类处理
/*
#if 0
void GameScene::keyPressEvent(QKeyEvent *keyEvent)
{
if(keyEvent->key() == Qt::Key_Shift || keyEvent->key() == Qt::Key_Control)
return;
QGraphicsScene::keyPressEvent(keyEvent);
}
*/
#endif
void GameScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
@ -47,9 +47,10 @@ void GameScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent)
void GameScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
//屏蔽鼠标按下事件
// 屏蔽鼠标按下事件
mouseEvent->accept();
/*
#if 0
// 只处理左键事件
if(mouseEvent->button() != Qt::LeftButton)
return;
@ -62,7 +63,7 @@ void GameScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
// 调用默认事件处理函数
//QGraphicsScene::mousePressEvent(mouseEvent);
*/
#endif
}
void GameScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)

View File

@ -31,9 +31,11 @@ void GameView::flip()
* 0 -1 0
* 0 0 1
*/
// 方法一: 直接在原变换矩阵基础上乘以上面的矩阵
// QMatrix只对变换矩阵前两列赋值
setMatrix(matrix() * QMatrix(1, 0, 0, -1, 0, 0));
/* 方法二: 人工计算好新的变换矩阵后再对场景赋值
*
QMatrix mt = matrix();
@ -98,6 +100,7 @@ void GameView::resizeEvent(QResizeEvent *event)
scale(sx, sy);
//qDebug() << "scale :" << sx;
*/
// 使用如下形式,更简洁
QGraphicsView::resizeEvent(event);
fitInView(sceneRect(), Qt::KeepAspectRatio);

View File

@ -1,4 +1,5 @@
/* QListView派生类
/*
* QListView派生类
* sizeHint函数
*
* QDockWidget没有很好的控制初始大小的方法resize函数没效果
@ -25,6 +26,7 @@ public:
{
Q_UNUSED(parent)
}
QSize sizeHint() const
{
QSize size = QListView::sizeHint();
@ -55,10 +57,11 @@ protected slots:
newEmptyRow = true;
}
#if 0
/* 本来重载rowsInserted函数用于在插入新行后自动选中最后一行
Model的insertRow执行后rowsInserted会被立即执行
Model的setData还未被执行
*/
void rowsInserted(const QModelIndex &parent, int start, int end) {
// 调用父类函数为使滚动条更新否则scrollToBottom不能正确执行。
QListView::rowsInserted(parent, start, end);
@ -66,7 +69,7 @@ protected slots:
setCurrentIndex(id);
scrollToBottom();
}
*/
#endif
// 采用判断最后一个元素是否改变来选中之
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,

View File

@ -194,14 +194,17 @@ void NineChess::createMoveTable()
for (int s = 0; s < N_SEATS; s++) {
// 顺时针走一步的位置
moveTable[r * N_SEATS + s][0] = r * N_SEATS + (s + 1) % N_SEATS;
// 逆时针走一步的位置
moveTable[r * N_SEATS + s][1] = r * N_SEATS + (s + N_SEATS - 1) % N_SEATS;
// 如果是 0、2、4、6位偶数位或是有斜线
if (!(s & 1) || this->currentRule.hasObliqueLines) {
if (r > 1) {
// 向内走一步的位置
moveTable[r * N_SEATS + s][2] = (r - 1) * N_SEATS + s;
}
if (r < N_RINGS) {
// 向外走一步的位置
moveTable[r * N_SEATS + s][3] = (r + 1) * N_SEATS + s;
@ -1210,15 +1213,15 @@ bool NineChess::choose(int pos)
uint64_t NineChess::chessHash()
{
/*
hash各数据位详解hash
57-640
5601
5501
7-544822448
0b000b010b100b11
5-6232
1-4player1的手棋数player2的
*/
* hash各数据位详解hash
* 57-640
* 5601
* 5501
* 7-544822448
* 0b000b010b100b11
* 5-6232
* 1-4player1的手棋数player2的
*/
uint64_t hash = 0ull;
for (int i = N_SEATS; i < (N_RINGS + 1) * N_SEATS; i++) {
@ -1332,6 +1335,7 @@ bool NineChess::command(int move)
} else {
return place(move & 0x00ff);
}
return false;
}
@ -1346,6 +1350,7 @@ inline long NineChess::update(long time_p /*= -1*/)
case NineChess::GAME_PLACING:
case NineChess::GAME_MOVING:
ftime(&currentTimeb);
// 更新时间
if (time_p >= *player_ms) {
*player_ms = ret = time_p;
@ -1361,14 +1366,19 @@ inline long NineChess::update(long time_p /*= -1*/)
*player_ms = ret = (long)(currentTimeb.time - startTimeb.time) * 1000
+ (currentTimeb.millitm - startTimeb.millitm) - playerNext_ms;
}
// 有限时要求则判断胜负
if (currentRule.maxTimeLedToLose > 0)
win();
return ret;
case NineChess::GAME_NOTSTARTED:
return ret;
case NineChess::GAME_OVER:
return ret;
default:
return ret;
}
@ -1640,20 +1650,23 @@ bool NineChess::isAllSurrounded(char ch)
bool NineChess::isAllSurrounded(enum Player ply)
{
char t = '\x30';
if (ply == PLAYER1)
t &= '\x10';
else if (ply == PLAYER2)
t &= '\x20';
return isAllSurrounded(t);
}
void NineChess::cleanForbiddenPoints()
{
for (int i = 1; i <= N_RINGS; i++)
for (int i = 1; i <= N_RINGS; i++) {
for (int j = 0; j < N_SEATS; j++) {
if (board_[i * N_SEATS + j] == '\x0f')
board_[i * N_SEATS + j] = '\x00';
}
}
}
enum NineChess::Player NineChess::changeTurn()
@ -1669,6 +1682,7 @@ void NineChess::setTips()
case NineChess::GAME_NOTSTARTED:
tips = "轮到黑方落子,剩余" + std::to_string(context.nPiecesInHand_1) + "";
break;
case NineChess::GAME_PLACING:
if (context.action == ACTION_PLACE) {
if (context.turn == PLAYER1) {
@ -1684,6 +1698,7 @@ void NineChess::setTips()
}
}
break;
case NineChess::GAME_MOVING:
if (context.action == ACTION_PLACE || context.action == ACTION_CHOOSE) {
if (context.turn == PLAYER1) {
@ -1699,6 +1714,7 @@ void NineChess::setTips()
}
}
break;
case NineChess::GAME_OVER:
if (winner == DRAW)
tips = "超出限定步数,双方平局";
@ -1714,6 +1730,7 @@ void NineChess::setTips()
tips = "白方获胜!";
}
break;
default:
break;
}
@ -1956,7 +1973,9 @@ void NineChess::turn(bool cmdChange /*= true*/)
int args = 0;
int mm = 0, ss = 0, mss = 0;
args = sscanf(cmdline, "(%1u,%1u)->(%1u,%1u) %2u:%2u.%3u", &c1, &p1, &c2, &p2, &mm, &ss, &mss);
args = sscanf(cmdline, "(%1u,%1u)->(%1u,%1u) %2u:%2u.%3u",
&c1, &p1, &c2, &p2, &mm, &ss, &mss);
if (args >= 4) {
if (c1 == 1)
c1 = N_RINGS;
@ -1989,7 +2008,10 @@ void NineChess::turn(bool cmdChange /*= true*/)
}
for (auto itor = cmdlist.begin(); itor != cmdlist.end(); itor++) {
args = sscanf((*itor).c_str(), "(%1u,%1u)->(%1u,%1u) %2u:%2u.%3u", &c1, &p1, &c2, &p2, &mm, &ss, &mss);
args = sscanf((*itor).c_str(),
"(%1u,%1u)->(%1u,%1u) %2u:%2u.%3u",
&c1, &p1, &c2, &p2, &mm, &ss, &mss);
if (args >= 4) {
if (c1 == 1)
c1 = N_RINGS;
@ -2028,6 +2050,7 @@ void NineChess::rotate(int degrees, bool cmdChange /*= true*/)
{
// 将degrees转化为0~359之间的数
degrees = degrees % 360;
if (degrees < 0)
degrees += 360;

View File

@ -171,7 +171,7 @@ public:
// 尚待去除的子数
int nPiecesNeedRemove;
/*
#if 0
struct Mill {
char piece1; // “三连”中最小的棋子
@ -184,7 +184,8 @@ public:
64
0x 00 00 00 00 00 00 00 00
unused unused piece1 pos1 piece2 pos2 piece3 pos3
*/
#endif
// “三连列表”
list <uint64_t> millList;
};

View File

@ -24,6 +24,7 @@
#include <QScreen>
#include <QDebug>
#include <QDesktopWidget>
#include "ninechesswindow.h"
#include "gamecontroller.h"
#include "gamescene.h"
@ -37,17 +38,22 @@ NineChessWindow::NineChessWindow(QWidget * parent) :
autoRunTimer(this)
{
ui.setupUi(this);
//去掉标题栏
// 去掉标题栏
//setWindowFlags(Qt::FramelessWindowHint);
//设置透明(窗体标题栏不透明,背景透明,如果不去掉标题栏,背景就变为黑色)
// 设置透明(窗体标题栏不透明,背景透明,如果不去掉标题栏,背景就变为黑色)
//setAttribute(Qt::WA_TranslucentBackground);
//设置全体透明度系数
// 设置全体透明度系数
//setWindowOpacity(0.7);
// 设置场景
scene = new GameScene(this);
// 设置场景尺寸大小为棋盘大小的1.08倍
scene->setSceneRect(-BOARD_SIZE * 0.54, -BOARD_SIZE * 0.54, BOARD_SIZE * 1.08, BOARD_SIZE * 1.08);
scene->setSceneRect(-BOARD_SIZE * 0.54, -BOARD_SIZE * 0.54,
BOARD_SIZE * 1.08, BOARD_SIZE * 1.08);
// 初始化各个控件
@ -87,6 +93,7 @@ NineChessWindow::~NineChessWindow()
game->disconnect();
game->deleteLater();
}
qDeleteAll(ruleActionList);
}
@ -97,7 +104,9 @@ void NineChessWindow::closeEvent(QCloseEvent *event)
// 取消自动运行
ui.actionAutoRun_A->setChecked(false);
//qDebug() << "closed";
QMainWindow::closeEvent(event);
}
@ -116,6 +125,7 @@ bool NineChessWindow::eventFilter(QObject *watched, QEvent *event)
break;
}
}
return QMainWindow::eventFilter(watched, event);
}
@ -130,6 +140,7 @@ void NineChessWindow::initialize()
// 添加新菜单栏动作
QMap <int, QStringList> actions = game->getActions();
for (auto i = actions.constBegin(); i != actions.constEnd(); i++) {
// qDebug() << i.key() << i.value();
// QMap的key存放int索引值value存放规则名称和规则提示
@ -151,31 +162,40 @@ void NineChessWindow::initialize()
}
// 关联主窗口动作信号和控制器的槽
connect(ui.actionGiveUp_G, SIGNAL(triggered()),
game, SLOT(giveUp()));
connect(ui.actionEngine1_T, SIGNAL(toggled(bool)),
game, SLOT(setEngine1(bool)));
connect(ui.actionEngine2_R, SIGNAL(toggled(bool)),
game, SLOT(setEngine2(bool)));
connect(ui.actionSound_S, SIGNAL(toggled(bool)),
game, SLOT(setSound(bool)));
connect(ui.actionAnimation_A, SIGNAL(toggled(bool)),
game, SLOT(setAnimation(bool)));
// 视图上下翻转
connect(ui.actionFlip_F, &QAction::triggered,
game, &GameController::flip);
// 视图左右镜像
connect(ui.actionMirror_M, &QAction::triggered,
game, &GameController::mirror);
// 视图须时针旋转90°
connect(ui.actionTurnRight_R, &QAction::triggered,
game, &GameController::turnRight);
// 视图逆时针旋转90°
connect(ui.actionTurnLeftt_L, &QAction::triggered,
game, &GameController::turnLeft);
// 关联控制器的信号和主窗口控件的槽
// 更新LCD1显示玩家1用时
connect(game, SIGNAL(time1Changed(QString)),
ui.lcdNumber_1, SLOT(display(QString)));
@ -211,22 +231,30 @@ void NineChessWindow::initialize()
// 关联列表视图和字符串列表模型
ui.listView->setModel(game->getManualListModel());
// 因为QListView的rowsInserted在setModel之后才能启动
// 第一次需手动初始化选中listView第一项
//qDebug() << ui.listView->model();
ui.listView->setCurrentIndex(ui.listView->model()->index(0, 0));
// 初始局面、前一步、后一步、最终局面的槽
connect(ui.actionBegin_S, &QAction::triggered,
this, &NineChessWindow::on_actionRowChange);
connect(ui.actionPrevious_B, &QAction::triggered,
this, &NineChessWindow::on_actionRowChange);
connect(ui.actionNext_F, &QAction::triggered,
this, &NineChessWindow::on_actionRowChange);
connect(ui.actionEnd_E, &QAction::triggered,
this, &NineChessWindow::on_actionRowChange);
// 手动在listView里选择招法后更新的槽
connect(ui.listView, &ManualListView::currentChangedSignal,
this, &NineChessWindow::on_actionRowChange);
// 更新四个键的状态
on_actionRowChange();
}
@ -235,8 +263,10 @@ 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)
@ -244,22 +274,27 @@ void NineChessWindow::ruleInfo()
// 规则显示
ui.labelRule->setText(tl + sl);
// 规则提示
ui.labelInfo->setToolTip(QString(NineChess::RULES[ruleNo].name) + "\n" +
NineChess::RULES[ruleNo].description);
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));
#if 0
QString tip_Rule = QString("%1\n%2").arg(tr(NineChess::RULES[ruleNo].name))
.arg(tr(NineChess::RULES[ruleNo].info));
#endif
}
void NineChessWindow::on_actionLimited_T_triggered()
{
/* 其实本来可以用设计器做个ui然后从QDialog派生个自己的对话框
*
*
* QDialog界面
*/
/*
* uiQDialog派生个自己的对话框
*
*
* QDialog界面
*/
int gStep = game->getStepsLimit();
int gTime = game->getTimeLimit();
@ -270,6 +305,7 @@ void NineChessWindow::on_actionLimited_T_triggered()
dialog->setWindowTitle(tr("步数和时间限制"));
dialog->resize(256, 108);
dialog->setModal(true);
// 生成各个控件
QFormLayout *formLayout = new QFormLayout(dialog);
QLabel *label_step = new QLabel(dialog);
@ -277,13 +313,15 @@ void NineChessWindow::on_actionLimited_T_triggered()
QComboBox *comboBox_step = new QComboBox(dialog);
QComboBox *comboBox_time = new QComboBox(dialog);
QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
#if 0
// 设置各个控件ObjectName不设也没关系
/*formLayout->setObjectName(QStringLiteral("formLayout"));
formLayout->setObjectName(QStringLiteral("formLayout"));
label_step->setObjectName(QStringLiteral("label_step"));
label_time->setObjectName(QStringLiteral("label_time"));
comboBox_step->setObjectName(QStringLiteral("comboBox_step"));
comboBox_time->setObjectName(QStringLiteral("comboBox_time"));
buttonBox->setObjectName(QStringLiteral("buttonBox"));*/
buttonBox->setObjectName(QStringLiteral("buttonBox"));
#endif
// 设置各个控件数据
label_step->setText(tr("超出限制步数判和:"));
label_time->setText(tr("任意一方超时判负:"));
@ -357,6 +395,7 @@ void NineChessWindow::actionRules_triggered()
// 重置游戏规则
game->setRule(ruleNo);
// 更新规则显示
ruleInfo();
}
@ -365,11 +404,14 @@ void NineChessWindow::on_actionNew_N_triggered()
{
if (file.isOpen())
file.close();
// 取消自动运行
ui.actionAutoRun_A->setChecked(false);
// 取消AI设定
ui.actionEngine1_T->setChecked(false);
ui.actionEngine2_R->setChecked(false);
// 重置游戏规则
game->gameReset();
}
@ -380,26 +422,32 @@ void NineChessWindow::on_actionOpen_O_triggered()
if (path.isEmpty() == false) {
if (file.isOpen())
file.close();
//文件对象
// 文件对象
file.setFileName(path);
// 不支持1MB以上的文件
if (file.size() > 0x100000) {
// 定义新对话框
QMessageBox msgBox(QMessageBox::Warning, tr("文件过大"), tr("不支持1MB以上文件"), QMessageBox::Ok);
QMessageBox msgBox(QMessageBox::Warning,
tr("文件过大"), tr("不支持1MB以上文件"), QMessageBox::Ok);
msgBox.exec();
return;
}
//打开文件,只读方式打开
// 打开文件,只读方式打开
bool isok = file.open(QFileDevice::ReadOnly | QFileDevice::Text);
if (isok) {
// 取消AI设定
ui.actionEngine1_T->setChecked(false);
ui.actionEngine2_R->setChecked(false);
// 读文件
QTextStream textStream(&file);
QString cmd;
cmd = textStream.readLine();
// 读取并显示棋谱时,不必刷新棋局场景
if (!(game->command(cmd, false))) {
// 定义新对话框
@ -407,10 +455,12 @@ void NineChessWindow::on_actionOpen_O_triggered()
msgBox.exec();
return;
}
while (!textStream.atEnd()) {
cmd = textStream.readLine();
game->command(cmd, false);
}
// 最后刷新棋局场景
game->updateScence();
}
@ -421,23 +471,28 @@ void NineChessWindow::on_actionSave_S_triggered()
{
if (file.isOpen()) {
file.close();
//打开文件,只写方式打开
// 打开文件,只写方式打开
bool isok = file.open(QFileDevice::WriteOnly | QFileDevice::Text);
if (isok) {
//写文件
// 写文件
QTextStream textStream(&file);
QStringListModel *strlist = qobject_cast<QStringListModel *>(ui.listView->model());
for (QString cmd : strlist->stringList())
textStream << cmd << endl;
file.flush();
}
} else
} else {
on_actionSaveAs_A_triggered();
}
}
void NineChessWindow::on_actionSaveAs_A_triggered()
{
QString path = QFileDialog::getSaveFileName(this, tr("打开棋谱文件"), QDir::currentPath() + tr("棋谱.txt"), "TXT(*.txt)");
QString path = QFileDialog::getSaveFileName(this,
tr("打开棋谱文件"), QDir::currentPath() + tr("棋谱.txt"), "TXT(*.txt)");
if (path.isEmpty() == false) {
if (file.isOpen())
file.close();
@ -447,8 +502,9 @@ void NineChessWindow::on_actionSaveAs_A_triggered()
// 打开文件,只写方式打开
bool isok = file.open(QFileDevice::WriteOnly | QFileDevice::Text);
if (isok) {
//写文件
// 写文件
QTextStream textStream(&file);
QStringListModel *strlist = qobject_cast<QStringListModel *>(ui.listView->model());
for (QString cmd : strlist->stringList())
@ -456,7 +512,6 @@ void NineChessWindow::on_actionSaveAs_A_triggered()
file.flush();
}
}
}
void NineChessWindow::on_actionEdit_E_toggled(bool arg1)
@ -480,6 +535,7 @@ void NineChessWindow::on_actionInvert_I_toggled(bool arg1)
ui.picLabel1->setPixmap(QPixmap(":/icon/Resources/icon/Black.png"));
ui.picLabel2->setPixmap(QPixmap(":/icon/Resources/icon/White.png"));
}
// 让控制器改变棋子颜色
game->setInvert(arg1);
}
@ -506,6 +562,7 @@ void NineChessWindow::on_actionRowChange()
} else if (obsender == ui.actionEnd_E) {
ui.listView->setCurrentIndex(model->index(rows - 1, 0));
}
currentRow = ui.listView->currentIndex().row();
}
@ -541,7 +598,8 @@ void NineChessWindow::on_actionRowChange()
// 更新局面
game->phaseChange(currentRow);
/* 下面的代码全部取消改用QTimer的方式实现
#if 0
// 下面的代码全部取消改用QTimer的方式实现
// 更新局面
bool changed = game->phaseChange(currentRow);
// 处理自动播放时的动画
@ -559,7 +617,7 @@ void NineChessWindow::on_actionRowChange()
QTimer::singleShot(waitTime, &loop, SLOT(quit()));
loop.exec();
}
*/
#endif // 0
}
void NineChessWindow::onAutoRunTimeOut(QPrivateSignal signal)
@ -578,7 +636,9 @@ void NineChessWindow::onAutoRunTimeOut(QPrivateSignal signal)
if (currentRow < rows - 1) {
ui.listView->setCurrentIndex(ui.listView->model()->index(currentRow + 1, 0));
}
currentRow = ui.listView->currentIndex().row();
// 更新动作状态
if (currentRow <= 0) {
ui.actionBegin_S->setEnabled(false);
@ -614,11 +674,13 @@ void NineChessWindow::on_actionAutoRun_A_toggled(bool arg1)
// 自动运行前禁用控件
ui.dockWidget->setEnabled(false);
ui.gameView->setEnabled(false);
// 启动定时器
autoRunTimer.start(game->getDurationTime() + 50);
} else {
// 关闭定时器
autoRunTimer.stop();
// 自动运行结束后启用控件
ui.dockWidget->setEnabled(true);
ui.gameView->setEnabled(true);
@ -723,7 +785,10 @@ void NineChessWindow::on_actionEngine_E_triggered()
time1_new = spinBox_time1->value();
time2_new = spinBox_time2->value();
if (depth1 != depth1_new || depth2 != depth2_new || time1 != time1_new || time2 != time2_new) {
if (depth1 != depth1_new ||
depth2 != depth2_new ||
time1 != time1_new ||
time2 != time2_new) {
// 重置AI
game->setAiDepthTime(depth1_new, time1_new, depth2_new, time2_new);
}
@ -750,7 +815,7 @@ void NineChessWindow::on_actionAbout_A_triggered()
dialog->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
dialog->setObjectName(QStringLiteral("aboutDialog"));
dialog->setWindowTitle(tr("九连"));
dialog->setWindowTitle(tr(""));
dialog->setModal(true);
// 生成各个控件
@ -771,7 +836,7 @@ void NineChessWindow::on_actionAbout_A_triggered()
label_icon1->setScaledContents(true);
label_icon2->setScaledContents(true);
label_text->setText(tr("支持开源,捐助作者,诚接软件开发项目 —— liuweilhy"));
label_text->setText(tr("Donate"));
label_text->setAlignment(Qt::AlignCenter);
label_image->setPixmap(QPixmap(QString::fromUtf8(":/image/resources/image/donate.png")));
label_image->setAlignment(Qt::AlignCenter);

View File

@ -10,6 +10,7 @@ class PieceItem : public QObject, public QGraphicsItem
{
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
// 位置属性
Q_PROPERTY(QPointF pos READ pos WRITE setPos)
@ -27,6 +28,7 @@ public:
{
Type = UserType + 2
};
int type() const
{
return Type;
@ -44,22 +46,27 @@ public:
{
return model_;
}
void setModel(enum Models model)
{
this->model_ = model;
}
int getNum()
{
return num;
}
void setNum(int n)
{
num = n;
}
bool isDeleted()
{
return deleted_;
}
void setDeleted(bool deleted = true)
{
this->deleted_ = deleted;
@ -67,6 +74,7 @@ public:
this->model_ = noPiece;
update(boundingRect());
}
void setShowNum(bool show = true)
{
this->showNum = show;