From 0b188d87e2295448b7d291258d505bacbf71f000 Mon Sep 17 00:00:00 2001 From: XMuli Date: Thu, 14 Dec 2023 20:39:18 +0800 Subject: [PATCH] feat: network matchmaking implementation and optimization --- AboutAuthor.cpp | 2 +- AboutAuthor.h | 14 ++--- AboutAuthor.ui | 23 +++++--- CMakeLists.txt | 6 +- ChessBoard.cpp | 62 +++++++------------- ChessBoard.h | 118 +++++++++++++++++-------------------- ChessBoard.ui | 102 +++++++++++++++++++++++++++----- ChessPieces.cpp | 2 +- ChessPieces.h | 16 ++--- ChessStep.cpp | 2 +- ChessStep.h | 14 ++--- ChessVoice.h | 12 ++-- ChooseMainWindow.cpp | 26 ++++---- ChooseMainWindow.h | 6 +- MachineGame.cpp | 2 +- MachineGame.h | 24 ++++---- NetworkGame.cpp | 137 ++++++++++++++++++++++++++++++++----------- NetworkGame.h | 8 +-- build.bat | 31 ++++++++++ main.cpp | 10 +--- 20 files changed, 375 insertions(+), 242 deletions(-) create mode 100644 build.bat diff --git a/AboutAuthor.cpp b/AboutAuthor.cpp index fa67a48..bf94a26 100755 --- a/AboutAuthor.cpp +++ b/AboutAuthor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * diff --git a/AboutAuthor.h b/AboutAuthor.h index 293bc89..1336aef 100755 --- a/AboutAuthor.h +++ b/AboutAuthor.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * @@ -25,8 +25,9 @@ #include #include -namespace Ui { -class AboutAuthor; +namespace Ui +{ + class AboutAuthor; } class AboutAuthor : public QDialog @@ -34,15 +35,14 @@ class AboutAuthor : public QDialog Q_OBJECT public: - explicit AboutAuthor(QWidget *parent = 0); + explicit AboutAuthor(QWidget* parent = 0); ~AboutAuthor(); protected: - virtual void paintEvent(QPaintEvent *event) override; + virtual void paintEvent(QPaintEvent* event) override; private: - Ui::AboutAuthor *ui; - QWidget * QDialog; + Ui::AboutAuthor* ui; }; #endif // ABOUTAUTHOR_H diff --git a/AboutAuthor.ui b/AboutAuthor.ui index ee579f2..83debfb 100755 --- a/AboutAuthor.ui +++ b/AboutAuthor.ui @@ -62,7 +62,7 @@ - :/images/Alipay.png + :/images/Alipay.png true @@ -106,7 +106,7 @@ - :/images/WeChat.png + :/images/WeChat.png true @@ -145,11 +145,14 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;"> +hr { height: 1px; border-width: 0; } +li.unchecked::marker { content: "\2610"; } +li.checked::marker { content: "\2612"; } +</style></head><body style=" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'华文楷体';">作者:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'华文楷体';"> </span><a href="https://github.com/XMuli"><span style=" font-family:'华文楷体'; text-decoration: underline; color:#007af4;">偕臧</span></a><span style=" font-family:'华文楷体';"> Copyri © 2019-2022</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'华文楷体';"> </span><a href="https://github.com/XMuli"><span style=" font-family:'华文楷体'; text-decoration: underline; color:#007af4;">偕臧</span></a><span style=" font-family:'华文楷体';"> Copyri © 2019-2024</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'华文楷体'; text-decoration: underline; color:#007af4;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'FangSong';">贡献者: </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'FangSong';"> - </span><a href="https://github.com/Bruce-Ch"><span style=" font-family:'FangSong'; text-decoration: underline; color:#007af4;">Bruce-Ch</span></a></p> @@ -157,7 +160,10 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'FangSong';"> - </span><a href="https://github.com/Ubuntuser2012"><span style=" font-family:'FangSong'; text-decoration: underline; color:#007af4;">Ubuntuser2012</span></a></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'FangSong';"> - </span><a href="https://github.com/kira-yamatoo"><span style=" font-family:'FangSong'; text-decoration: underline; color:#007af4;">kira-yamatoo</span></a></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'FangSong';"> - </span><a href="https://github.com/hmsjy2017"><span style=" font-family:'FangSong'; text-decoration: underline; color:#007af4;">hmsjy2017</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'FangSong';"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'FangSong';"> - </span><a href="https://github.com/zjuyk"><span style=" text-decoration: underline; color:#007af4;">zjuyk</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'FangSong';"> - </span><a href="https://github.com/ryanfortner"><span style=" text-decoration: underline; color:#007af4;">ryanfortner</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; text-decoration: underline; color:#007af4;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'FangSong'; text-decoration: underline; color:#007af4;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'FangSong';"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'FangSong';">项目:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'FangSong';"> 关于 </span><a href="https://github.com/XMuli/chineseChess"><span style=" font-family:'FangSong'; text-decoration: underline; color:#007af4;">ChinessChess</span></a><span style=" font-family:'FangSong';"> 此开源项目,兴趣之做;说明都在这里 [</span><a href="https://github.com/XMuli/chineseChess/blob/master/README.zh_CN.md"><span style=" font-family:'FangSong'; text-decoration: underline; color:#007af4;">中文</span></a><span style=" font-family:'FangSong';"> | </span><a href="https://github.com/XMuli/chineseChess/blob/master/README.md"><span style=" font-family:'FangSong'; text-decoration: underline; color:#007af4;">English</span></a><span style=" font-family:'FangSong';">]</span></p> @@ -169,7 +175,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'FangSong';"> 所有参与贡献的,亦都会留名在此。​热爱开源,热爱生命,热爱生活。</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'FangSong';"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'FangSong';"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'FangSong';">Bolg: </span><a href="https://ifmet.cn"><span style=" font-family:'FangSong'; text-decoration: underline; color:#007af4;">ifmet.cn</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'FangSong';">Bolg: </span><a href="https://xmuli.tech"><span style=" text-decoration: underline; color:#007af4;">xmuli.tech</span></a></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'FangSong'; text-decoration: underline; color:#007af4;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'FangSong';">Gmail: xmulitech@gmail.com</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'FangSong'; text-decoration: underline; color:#007af4;"><br /></p> @@ -187,8 +193,7 @@ p, li { white-space: pre-wrap; } - - + diff --git a/CMakeLists.txt b/CMakeLists.txt index cbab394..b65c7ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,13 +19,13 @@ cmake_minimum_required(VERSION 3.5) set(project_name ChineseChess) -set(project_version_major 7) -set(project_version_minor 0) +set(project_version_major 6) +set(project_version_minor 2) set(project_version_path 0) set(project_version ${project_version_major}.${project_version_minor}.${project_version_path}) project(${project_name} VERSION ${project_version} LANGUAGES CXX) -add_definitions(-DXBUILD_TIME="2023.12.13") +add_definitions(-DXBUILD_TIME="2023.12.14") set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) diff --git a/ChessBoard.cpp b/ChessBoard.cpp index 8b8b8c2..4b7de51 100644 --- a/ChessBoard.cpp +++ b/ChessBoard.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * @@ -21,6 +21,7 @@ */ #include "ChessBoard.h" #include "ui_ChessBoard.h" +#include ChessBoard::ChessBoard(QWidget *parent) : QMainWindow(parent), @@ -409,31 +410,11 @@ bool ChessBoard:: isGeneral() return false; } -void ChessBoard::setNetworkGroupShow(const bool &show) +void ChessBoard::showNetworkGui(const bool &show) { ui->networkGroup->setVisible(show); } -/*! - * \brief ChessBoard::setNetworkGroupText - * \param group group的名称 - * \param input 输入栏 IP+prot - * \param btn 按钮的名称,监听或者连接 - * \param statue 连接结果的名称 - */ -void ChessBoard::setNetworkGroupText(const QString &group, const QString &input, const QString &btn, const QString &statue) -{ - ui->networkGroup->setTitle(group); - ui->lineEdit->setText(input); - ui->btnTcpConnect->setText(btn); - ui->labConnectStatus->setText(statue); -} - -void ChessBoard::setstatusText(const QString &statue) -{ - ui->labConnectStatus->setText(statue); -} - //鼠标按下事件 //void ChessBoard::mousePressEvent(QMouseEvent *ev) //{ @@ -810,6 +791,13 @@ void ChessBoard::clickPieces(int id, int &row, int &col) else { tryMoveStone(id, row, col); } + + // 初次按下时,自启动计时器 + std::once_flag flag; + std::call_once(flag, [&]() { + m_bIsStart = false; + on_pushButton_start_clicked(); + }); } void ChessBoard::trySelectStone(int id) @@ -948,17 +936,17 @@ void ChessBoard::updateTime() void ChessBoard::on_pushButton_start_clicked() { if(!m_bIsStart) //尚未开始 开始计时 - { - m_timer->start(1000); - ui->pushButton_start->setText("暂停"); - } - else //已经开始,暂停 - { - m_timer->stop(); - ui->pushButton_start->setText("继续"); - } + { + m_timer->start(1000); + ui->pushButton_start->setText("暂停"); + } + else //已经开始,暂停 + { + m_timer->stop(); + ui->pushButton_start->setText("继续"); + } - m_bIsStart = !m_bIsStart; + m_bIsStart = !m_bIsStart; } void ChessBoard::on_pushButton_reset_clicked() @@ -1001,14 +989,4 @@ void ChessBoard::on_pushButton_toMenu_clicked() emit this->toMenu(); } -void ChessBoard::on_lineEdit_textChanged(const QString &arg1) -{ - emit sigLineEditTextChanged(arg1); -} - - -void ChessBoard::on_btnTcpConnect_released() -{ - emit sigBtnTcpConnectReleased(); -} diff --git a/ChessBoard.h b/ChessBoard.h index 0259ad6..d311ba6 100644 --- a/ChessBoard.h +++ b/ChessBoard.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * @@ -75,43 +75,38 @@ class ChessBoard : public QMainWindow bool isRed(int id); bool isDead(int id); - void killStone(int id); //吃子 - void reliveStone(int id); //死者苏生 - void moveStone(int moveid, int row, int col); //移动棋子 - bool sameColor(int moveId, int killId); //棋子是否同色 + void killStone(int id); // 吃子 + void reliveStone(int id); // 死者苏生 + void moveStone(int moveid, int row, int col); // 移动棋子 + bool sameColor(int moveId, int killId); // 棋子是否同色 int getStoneId(int row, int col); // 车、炮的功能辅助函数 判断两个点是否在一个直线上面,且返回直线之间的棋子个数 int getStoneCountAtLine(int row1, int col1, int row2, int col2); - void whoWin(); //谁胜谁负 - bool isChecked(QPoint pt, int& row, int& col); //是否选中该枚棋子。pt为输入参数; row, col为输出参数 - int relation(int row1, int col1, int row2, int col2); //计算选中的棋子的位置和要移动的位置之间的位置关系 - QPoint getRealPoint(QPoint pt); // 使mouseMoveEvent取得的坐标同Painter的坐标一致 - bool isGeneral(); //校验将移动后位置是否将死 - void setNetworkGroupShow(const bool& show = false); - -protected: - // 仅网络对战才需要的接口 - void setNetworkGroupText(const QString& group, const QString& input, const QString &btn, const QString& statue); - void setstatusText(const QString& statue); + void whoWin(); // 谁胜谁负 + bool isChecked(QPoint pt, int& row, int& col); // 是否选中该枚棋子。pt为输入参数; row, col为输出参数 + int relation(int row1, int col1, int row2, int col2); // 计算选中的棋子的位置和要移动的位置之间的位置关系 + QPoint getRealPoint(QPoint pt); // 使mouseMoveEvent取得的坐标同Painter的坐标一致 + bool isGeneral(); // 校验将移动后位置是否将死 + void showNetworkGui(const bool& show = false); private: - bool hongMenFeast(); // 鸿门宴:对将 - bool havePieces(int row, int col); // 判断某一格子,是否有棋子 - void reset(); // 胜负已分,重置 + bool hongMenFeast(); // 鸿门宴:对将 + bool havePieces(int row, int col); // 判断某一格子,是否有棋子 + void reset(); // 胜负已分,重置 void winMessageBox(QString title, QString msg); public: //视图相关 - QPoint center(int row, int col); //象棋的棋盘的坐标转换成界面坐标 + QPoint center(int row, int col); // 象棋的棋盘的坐标转换成界面坐标 QPoint center(int id); - virtual void paintEvent(QPaintEvent *); //绘画棋盘 - void drawChessPieces(QPainter& painter, int id); //绘画单个具体的棋子 - void drawLastStep(QPainter &painter, QVector& steps); //绘制上次移动棋子的起止位置 - void drawTextStep(); //绘制文本棋谱 -// virtual void mousePressEvent(QMouseEvent *); //鼠标点击事件 + virtual void paintEvent(QPaintEvent *); // 绘画棋盘 + void drawChessPieces(QPainter& painter, int id); // 绘画单个具体的棋子 + void drawLastStep(QPainter &painter, QVector& steps); // 绘制上次移动棋子的起止位置 + void drawTextStep(); // 绘制文本棋谱 +// virtual void mousePressEvent(QMouseEvent *); // 鼠标点击事件 // virtual void clickPieces(int checkedID, int& row, int& col); - //象棋移动的规则[将 士 象 马 车 炮 兵] + // 象棋移动的规则[将 士 象 马 车 炮 兵] bool canMove(int moveId, int killId, int row, int col); bool canMoveJIANG(int moveId, int killId, int row, int col); bool canMoveSHI(int moveId, int killId, int row, int col); @@ -120,41 +115,39 @@ class ChessBoard : public QMainWindow bool canMoveCHE(int moveId, int killId, int row, int col); bool canMovePAO(int moveId, int killId, int row, int col); bool canMoveBING(int moveId, int killId, int row, int col); - bool canSelect(int id); //是否允许红方或黑方选棋 - + bool canSelect(int id); void init(); //移动相关 - virtual void mouseReleaseEvent(QMouseEvent *ev); // 鼠标释放事件 - void click(QPoint pt); //点击转换像素 - virtual void clickPieces(int id, int& row, int& col); //点击选棋 - void trySelectStone(int id); //尝试选棋 - void tryMoveStone(int killid, int row, int col); //尝试移动 - void doMoveStone(int moveid, int killid, int row, int col); //执行移动棋子 - void saveStep(int moveid, int killid, int row, int col, QVector& steps); //保存步数 - QString textStep(int moveid, int row, int col); //文本棋谱 - - void backOne(); //悔棋一子 - void back(ChessStep* step); //悔棋到指定步数 - virtual void back(); //悔棋 - - ChessPieces m_ChessPieces[32]; //所有棋子 - QVector m_ChessSteps; // 悔棋步数 - ChessVoice m_Chessvoice; //下棋音效 - int m_nR; //棋子半径 - int m_nOffSet; //距离界面的边距 - int m_nD; //间距为50px - int m_nSelectID; //选中棋子[-1:选棋子 || 非-1:走棋子] - int m_nCheckedID; //将要被击杀的棋子ID - bool m_bIsRed; //是否是红方回合 + virtual void mouseReleaseEvent(QMouseEvent *ev); // 鼠标释放事件 + void click(QPoint pt); // 点击转换像素 + virtual void clickPieces(int id, int& row, int& col); // 点击选棋 + void trySelectStone(int id); // 尝试选棋 + void tryMoveStone(int killid, int row, int col); // 尝试移动 + void doMoveStone(int moveid, int killid, int row, int col); // 执行移动棋子 + void saveStep(int moveid, int killid, int row, int col, QVector& steps); // 保存步数 + QString textStep(int moveid, int row, int col); // 文本棋谱 + + void backOne(); // 悔棋一子 + void back(ChessStep* step); // 悔棋到指定步数 + virtual void back(); // 悔棋 + + ChessPieces m_ChessPieces[32]; // 所有棋子 + QVector m_ChessSteps; // 悔棋步数 + ChessVoice m_Chessvoice; // 下棋音效 + int m_nR; // 棋子半径 + int m_nOffSet; // 距离界面的边距 + int m_nD; // 间距为50px + int m_nSelectID; // 选中棋子[-1:选棋子 || 非-1:走棋子] + int m_nCheckedID; // 将要被击杀的棋子ID + bool m_bIsRed; // 是否是红方回合 bool m_bIsTcpServer; - bool m_bIsOver; //是否已经游戏结束 - bool m_bIsShowStep; //是否显示步数 - QString textStepRecord; //文本棋谱字符串 + bool m_bIsOver; // 是否已经游戏结束 + bool m_bIsShowStep; // 是否显示步数 + QString textStepRecord; // 文本棋谱字符串 signals: - void sigLineEditTextChanged(const QString &arg1); - void sigBtnTcpConnectReleased(); + void toMenu(); private slots: void updateTime(); @@ -165,20 +158,15 @@ private slots: void on_pushButton_back_clicked(); void on_pushButton_showStep_clicked(); void on_pushButton_toMenu_clicked(); - void on_lineEdit_textChanged(const QString &arg1); - void on_btnTcpConnect_released(); - -private: +protected: Ui::ChessBoard *ui; - QTimer * m_timer; //定时器 每秒更新时间 - QTime * m_timeRecord; //记录时间 - bool m_bIsStart; //记录是否已经开始计时 +private: + QTimer* m_timer; // 定时器 每秒更新时间 + QTime* m_timeRecord; // 记录时间 + bool m_bIsStart; // 记录是否已经开始计时 AboutAuthor* m_pAbout; - -signals: - void toMenu(); }; #endif // CHESSBOARD_H diff --git a/ChessBoard.ui b/ChessBoard.ui index 7551018..b761310 100644 --- a/ChessBoard.ui +++ b/ChessBoard.ui @@ -177,9 +177,59 @@ border-image: url(:/images/b.jpg); 请输入服务器IP和prot: - - - + + + 0 + + + + + <html><head/><body><p><a href="https://github.com/XMuli/ChineseChess/wiki/%E7%BD%91%E7%BB%9C%E5%AF%B9%E6%88%98%E6%A8%A1%E5%BC%8F%E8%AE%BE%E7%BD%AE"><span style=" text-decoration: underline; color:#007af4;">📖 Wiki</span></a></p></body></html> + + + true + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 60 + 16777215 + + + + 连接 + + + + + + + + 0 + 0 + + + + + 0 + 0 + + @@ -193,21 +243,45 @@ border-image: url(:/images/b.jpg); - 127.0.0.1:9999 + + + + + + + + 等待操作中 + + + true + + + + + + + IP: - + + + Port: + + + + + - + 0 0 - 60 + 0 0 @@ -217,15 +291,11 @@ border-image: url(:/images/b.jpg); 16777215 - - 连接 + + 65535 - - - - - - 连接状态: + + 9999 @@ -289,7 +359,7 @@ border-image: url(:/images/b.jpg); 0 0 1156 - 21 + 17 diff --git a/ChessPieces.cpp b/ChessPieces.cpp index 4fb15e3..3d4e51f 100755 --- a/ChessPieces.cpp +++ b/ChessPieces.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * diff --git a/ChessPieces.h b/ChessPieces.h index 34beb81..68a753d 100755 --- a/ChessPieces.h +++ b/ChessPieces.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * @@ -30,7 +30,7 @@ class ChessPieces ChessPieces(); ~ChessPieces(); - void init(int id); //初始化 + void init(int id); //初始化 QString getnName(bool isRedSide); //棋子对应的汉字 QString getColText(int col); QString getRowText(int rowTo); @@ -38,12 +38,12 @@ class ChessPieces enum m_emTYPE{JIANG, SHI, XIANG, MA, CHE, PAO, BING}; - int m_nRow; //行 - int m_nCol; //列 - int m_nID; //ID号 - bool m_bDead; //死亡状态 - bool m_bRed; //是否是红方 - m_emTYPE m_emType; //具体哪一个棋子 + int m_nRow; // 行 + int m_nCol; // 列 + int m_nID; // ID号 + bool m_bDead; // 死亡状态 + bool m_bRed; // 是否是红方 + m_emTYPE m_emType; // 具体哪一个棋子 QString colTextRed[9]={"九", "八", "七", "六", "五", "四", "三", "二", "一"}; QString colTextBlack[9]={"1", "2", "3", "4", "5", "6", "7", "8", "9"}; diff --git a/ChessStep.cpp b/ChessStep.cpp index 566f571..8ffeccf 100755 --- a/ChessStep.cpp +++ b/ChessStep.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * diff --git a/ChessStep.h b/ChessStep.h index 41235d5..5d013d6 100755 --- a/ChessStep.h +++ b/ChessStep.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * @@ -31,12 +31,12 @@ class ChessStep : public QObject explicit ChessStep(QObject *parent = 0); ~ChessStep(); - int m_nMoveID; //移动棋子ID - int m_nKillID; //将要被击杀的棋子ID - int m_nRowFrom; //原位置的行 - int m_nColFrom; //原位置的列 - int m_nRowTo; //目的位置的行 - int m_nnColTo; //目的位置的列 + int m_nMoveID; // 移动棋子ID + int m_nKillID; // 将要被击杀的棋子ID + int m_nRowFrom; // 原位置的行 + int m_nColFrom; // 原位置的列 + int m_nRowTo; // 目的位置的行 + int m_nnColTo; // 目的位置的列 }; #endif // CHESSSTEP_H diff --git a/ChessVoice.h b/ChessVoice.h index 4e10f45..ac820c9 100644 --- a/ChessVoice.h +++ b/ChessVoice.h @@ -37,12 +37,12 @@ class ChessVoice : public QObject QSound *m_back =new QSound(":/sound/backChess.wav",this); QSound *m_general =new QSound(":/sound/generalSound.wav",this); - void voiceWin(); //胜利音效 - void voiceSelect(); //选棋音效 - void voiceMove(); //移动音效 - void voiceEat(); //吃子音效 - void voiceBack(); //悔棋音效 - void voiceGeneral();//将军音效 + void voiceWin(); // 胜利音效 + void voiceSelect(); // 选棋音效 + void voiceMove(); // 移动音效 + void voiceEat(); // 吃子音效 + void voiceBack(); // 悔棋音效 + void voiceGeneral(); // 将军音效 }; diff --git a/ChooseMainWindow.cpp b/ChooseMainWindow.cpp index 9c45846..e06988d 100755 --- a/ChooseMainWindow.cpp +++ b/ChooseMainWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * @@ -43,7 +43,7 @@ ChooseMainWindow::ChooseMainWindow(QWidget *parent) : QDialog(parent) connect(m_buttons[0], &QPushButton::clicked,[=](){ this->hide(); m_pAgainstYourself = new ChessBoard(); - m_pAgainstYourself->setNetworkGroupShow(false); + m_pAgainstYourself->showNetworkGui(false); m_pAgainstYourself->setWindowTitle("玩家自己对战"); m_pAgainstYourself->show(); @@ -59,7 +59,7 @@ ChooseMainWindow::ChooseMainWindow(QWidget *parent) : QDialog(parent) this->hide(); m_pMachineGame = new MachineGame(); - m_pMachineGame->setNetworkGroupShow(false); + m_pMachineGame->showNetworkGui(false); m_pMachineGame->setWindowTitle("玩家和AI对战"); m_pMachineGame->show(); @@ -70,15 +70,25 @@ ChooseMainWindow::ChooseMainWindow(QWidget *parent) : QDialog(parent) }); }); - /*游戏方式三: 双人局域网下棋【可在局域网下不同台PC机器】*/ + /*游戏方式三: 双人网络对战下棋【可在局域网/广域网的不同台PC机器】 + - 一台实体主机: 一台主机,一台虚拟机,网络桥接模式 + - 两台实体主机: 同一局域网,或者都具有公网IP的广域网*/ connect(m_buttons[2], &QPushButton::clicked,[=](){ this->hide(); + QMessageBox::StandardButtons ret = QMessageBox::question( + this, + "提示", + "是否作为[服务器]启动?
" + "- Yes: 服务器, 属红方
" + "- No: 客户端, 属黑方

" + "📢: 📖 Wiki", + QMessageBox::Yes | QMessageBox::No + ); - QMessageBox::StandardButtons ret = QMessageBox::question(this, "提示", "是否作为[服务器 - 红方]启动?\n- Yes - 服务器,属红方\n- No - 客户端,属黑方"); const bool& bServer = ret == QMessageBox::Yes ? true : false; m_pNetworkGame = new NetworkGame(bServer); - m_pNetworkGame->setNetworkGroupShow(true); + m_pNetworkGame->showNetworkGui(true); const QString& title = QString("双人网络对战 [%1]").arg(bServer ? "服务器 - 红方" : "客户端 - 黑方") ; m_pNetworkGame->setWindowTitle(title); m_pNetworkGame->show(); @@ -91,8 +101,4 @@ ChooseMainWindow::ChooseMainWindow(QWidget *parent) : QDialog(parent) }); } -ChooseMainWindow::~ChooseMainWindow() -{ - -} diff --git a/ChooseMainWindow.h b/ChooseMainWindow.h index ed087f5..4a8c9ca 100755 --- a/ChooseMainWindow.h +++ b/ChooseMainWindow.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * @@ -33,11 +33,11 @@ class ChooseMainWindow : public QDialog Q_OBJECT public: explicit ChooseMainWindow(QWidget *parent = nullptr); - ~ChooseMainWindow(); + virtual ~ChooseMainWindow() = default; private: QPushButton* m_buttons[3]; - ChessBoard* m_pAgainstYourself; + ChessBoard* m_pAgainstYourself; MachineGame* m_pMachineGame; NetworkGame* m_pNetworkGame; }; diff --git a/MachineGame.cpp b/MachineGame.cpp index cfedefa..6292ec3 100755 --- a/MachineGame.cpp +++ b/MachineGame.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * diff --git a/MachineGame.h b/MachineGame.h index 8c06dcd..ebbba3f 100755 --- a/MachineGame.h +++ b/MachineGame.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * @@ -32,21 +32,19 @@ class MachineGame : public ChessBoard MachineGame(); ~MachineGame(); - void chooseOrMovePieces(int tempID, int& row, int& col); //辅助函: 选棋或移动棋子 + void chooseOrMovePieces(int tempID, int& row, int& col); // 辅助函: 选棋或移动棋子 + void saveStep(int moveID, int checkedID, int row, int col, QVector& steps); // 保存棋子步骤 + void getAllPossibleMoveStep(QVector& steps); // 获得所有可能的移动步骤(击杀) + void getAllPossibleMoveStepAndNoKill(QVector& steps); // 获得所有可能的移动步骤(不击杀) - void saveStep(int moveID, int checkedID, int row, int col, QVector& steps); //保存棋子步骤 - void getAllPossibleMoveStep(QVector& steps); //获得所有可能的移动步骤(击杀) - void getAllPossibleMoveStepAndNoKill(QVector& steps); //获得所有可能的移动步骤(不击杀) - - virtual void mousePressEvent(QMouseEvent *); //鼠标点击事件 + virtual void mousePressEvent(QMouseEvent *); // 鼠标点击事件 void clickPieces(int checkedID, int& row, int& col); - void fakeMove(ChessStep* step); //假装移动棋子 - void unFakeMove(ChessStep* step); //撤回先前假装移动棋子的步骤 - int calcScore(); //计算最好的局面分 - ChessStep* getBestMove(); //获得最好的移动步骤 - - void machineChooseAndMovePieces(); //机器 黑方时间: 进行选棋+下棋 + void fakeMove(ChessStep* step); // 假装移动棋子 + void unFakeMove(ChessStep* step); // 撤回先前假装移动棋子的步骤 + int calcScore(); // 计算最好的局面分 + ChessStep* getBestMove(); // 获得最好的移动步骤 + void machineChooseAndMovePieces(); // 机器 黑方时间: 进行选棋+下棋 }; #endif // MACHINEGAME_H diff --git a/NetworkGame.cpp b/NetworkGame.cpp index b4d3db2..5b8a0db 100755 --- a/NetworkGame.cpp +++ b/NetworkGame.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * @@ -20,54 +20,78 @@ * along with this program. If not, see . */ #include "NetworkGame.h" + +#include + +#include "ui_ChessBoard.h" +#include +#include #include #include NetworkGame::NetworkGame(bool isServer) { + m_bIsTcpServer = isServer; m_tcpServer = NULL; m_tcpSocket = NULL; - m_ip = "192.168.31.90"; // "127.0.0.1" "192.168.31.132"; - m_port = "9999"; QNetworkProxyFactory::setUseSystemConfiguration(false); + initUI(); - if(isServer) //作为服务器端 + if(m_bIsTcpServer) //作为服务器端 { - m_bIsTcpServer = true; m_tcpServer = new QTcpServer(this); - setNetworkGroupText("设置服务器的port号:", m_port, "监听", "状态结果:监听中"); - - // 监听指定地址和端口 - if (m_tcpServer->listen(QHostAddress::Any, m_port.toInt())) { - qDebug() << "Server is listening on" << m_tcpServer->serverAddress().toString() - << "port" << m_tcpServer->serverPort(); - } else { - qDebug() << "Server failed to start: " << m_tcpServer->errorString(); - } - + onBtnTryConnect(); connect(m_tcpServer, SIGNAL(newConnection()),this, SLOT(slotNewConnection())); } else //作为客户端 { - m_bIsTcpServer = false; - setNetworkGroupText("将接服务器的 ip 和 port:", m_ip + ":" + m_port, "连接", "状态结果:待操作"); m_tcpSocket = new QTcpSocket(this); - m_tcpSocket->connectToHost(QHostAddress(m_ip), m_port.toInt()); connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(slotRecv())); + } - // 等待连接成功或失败 - if (m_tcpSocket->waitForConnected()) { - qDebug() << "Connected to the server!"; - } else { - qDebug() << "Connection failed: " << m_tcpSocket->errorString(); + connect(ChessBoard::ui->btnTcpConnect, &QPushButton::released, this, &NetworkGame::onBtnTryConnect); +} + +void NetworkGame::initUI() +{ + auto& ui = ChessBoard::ui; + QString& ip = ui->leIp->text(); + QString& port = ui->sbPort->text(); + + if(m_bIsTcpServer) { //作为服务器端 + QList interfaces = QNetworkInterface::allInterfaces(); + + // 遍历每个接口 + foreach (QNetworkInterface interface, interfaces) { + // 如果接口处于活动状态且不是回环接口 + if (interface.isValid() && interface.flags().testFlag(QNetworkInterface::IsUp) && !interface.flags().testFlag(QNetworkInterface::IsLoopBack)) { + foreach (QNetworkAddressEntry entry, interface.addressEntries()) { + // 输出IPv4地址 + if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) { + ip = entry.ip().toString(); + qDebug() << "Interface:" << interface.humanReadableName() << "IPv4 Address:" << entry.ip().toString(); + break; + } + } + } } + ui->networkGroup->setTitle("服务器-红方的IP和Port"); + ui->btnTcpConnect->setText("监听"); + ui->leIp->setText(ip); + ui->sbPort->setValue(port.toLong()); + ui->leIp->setReadOnly(true); + ui->leIp->setDisabled(true); +// ui->lePort->setReadOnly(true); + } else { + ui->networkGroup->setTitle("请输入[服务器]的IP和Port"); + ui->btnTcpConnect->setText("连接"); + ui->btnTcpConnect->show(); + ui->leIp->setText(ip); + ui->sbPort->setValue(port.toLong()); } - - connect(this, &NetworkGame::sigLineEditTextChanged, this, &NetworkGame::onLineEditTextChanged); - connect(this, &NetworkGame::sigBtnTcpConnectReleased, this, &NetworkGame::onBtnTcpConnectReleased); } void NetworkGame::clickPieces(int checkedID, int &row, int &col) @@ -99,16 +123,26 @@ void NetworkGame::clickPieces(int checkedID, int &row, int &col) arry[0] = checkedID; arry[1] = row; arry[2] = col; - m_tcpSocket->write(arry, 3); + + if(m_tcpSocket) + m_tcpSocket->write(arry, 3); } void NetworkGame::slotNewConnection() { - if(m_tcpSocket) - return; + if(m_tcpSocket) return; - m_tcpSocket = m_tcpServer->nextPendingConnection(); - connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(slotRecv())); + static std::once_flag flag; + std::call_once(flag, [&]() { + QString text = QString("Client Connection Successful"); + ui->labConnectStatus->setText(text); + }); + + + if (m_tcpServer) { + m_tcpSocket = m_tcpServer->nextPendingConnection(); + connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(slotRecv())); + } } void NetworkGame::slotRecv() @@ -123,12 +157,45 @@ void NetworkGame::slotRecv() ChessBoard::clickPieces(nCheckedID, nRow, nCol); } -void NetworkGame::onLineEditTextChanged(const QString &arg1) +void NetworkGame::onBtnTryConnect() { + auto& ui = ChessBoard::ui; + QString text; + if (ui->leIp->text().isEmpty() || ui->sbPort->text().isEmpty()) { + text = "IP或Port为空,请设置后重试"; + qDebug() << text; + ui->labConnectStatus->setText(text); + return; + } -} + if(m_bIsTcpServer) { // 服务器-重设端口号 + if (!m_tcpServer) return; + if (m_tcpServer->isListening()) { + qDebug() << "Stopping server..."; + m_tcpServer->close(); + } -void NetworkGame::onBtnTcpConnectReleased() -{ + // 监听指定地址和端口 + if (m_tcpServer->listen(QHostAddress::Any, ui->sbPort->text().toLong())) { + text = QString("Server is listening on \"%1\" port \"%2\"").arg(m_tcpServer->serverAddress().toString()).arg(m_tcpServer->serverPort()); + } else { + text = QString("Server failed to start: %1").arg(m_tcpServer->errorString()); + } + + } else { // 客户端-输入IP+Port尝试连接服务器 + if (!m_tcpSocket) return; + const QString& ip = ui->leIp->text(); + const QString& port = ui->sbPort->text(); + m_tcpSocket->connectToHost(QHostAddress(ip), port.toInt()); + // 等待连接成功或失败 + if (m_tcpSocket->waitForConnected()) { + text = "Server Connection Successful: " + ip + ":" + port; + } else { + text = "Server connection failed: " + m_tcpSocket->errorString(); + } + } + + qDebug() << text; + ui->labConnectStatus->setText(text); } diff --git a/NetworkGame.h b/NetworkGame.h index 6071c9c..209efd1 100755 --- a/NetworkGame.h +++ b/NetworkGame.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * @@ -36,17 +36,15 @@ class NetworkGame : public ChessBoard public: NetworkGame(bool isServer); ~NetworkGame() = default; + void initUI(); void clickPieces(int checkedID, int& row, int& col) override; public slots: void slotNewConnection(); void slotRecv(); - void onLineEditTextChanged(const QString &arg1); - void onBtnTcpConnectReleased(); + void onBtnTryConnect(); private: - QString m_ip; - QString m_port; QTcpServer* m_tcpServer; QTcpSocket* m_tcpSocket; }; diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..8b86c95 --- /dev/null +++ b/build.bat @@ -0,0 +1,31 @@ +@echo off + +setlocal enabledelayedexpansion + +:: Define the new path you want to prepend +set new_path=C:\Qt\5.15.2\msvc2019_64\bin + +:: Check if the path already exists in PATH +echo !PATH! | findstr /C:"%new_path%" > nul +if !errorlevel! == 1 ( + :: If the path doesn't exist, prepend it to PATH + set "PATH=%new_path%;!PATH!" + echo Updated PATH: !PATH! +) else ( + echo PATH already contains %new_path% +) + +::delete build dir +if "%1"=="delete" goto _DEL + +if not exist build md build + +cd build +cmake -G "Visual Studio 17 2022" -A x64 .. +goto _END + +:_DEL +rd build/s/q +goto _END + +:_END \ No newline at end of file diff --git a/main.cpp b/main.cpp index 4b18d46..0fcf101 100755 --- a/main.cpp +++ b/main.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019~2020 偕臧 All rights reserved. + * Copyright (C) 2019~2024 偕臧 All rights reserved. * * Author: xmuli(偕臧) xmulitech@gmail.com * @@ -38,14 +38,6 @@ int main(int argc, char *argv[]) { QApplication a(argc, argv); -// SelectGameMode dlg; -// dlg.setWindowTitle("选择游戏方式"); -// dlg.setFixedSize(200,120); -// dlg.setWindowIcon(QIcon(":/images/chess.svg")); -// if(dlg.exec() != QDialog::Accepted) -// return 0; - -// ChooseMainWindow wnd(dlg.m_nSelect); ChooseMainWindow c; c.show();