From 4b9c9d4b9c4fb75d23fd98e5a795a5f002900eb8 Mon Sep 17 00:00:00 2001 From: iridiumR Date: Tue, 31 May 2022 17:21:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=82=BB=E9=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Lab5/lab5_1_painter/lab5_1_painter.pro | 24 ++ SoftwareDesign/Lab5/lab5_1_painter/main.cpp | 11 + .../Lab5/lab5_1_painter/mainwindow.cpp | 71 ++++++ .../Lab5/lab5_1_painter/mainwindow.h | 40 +++ .../Lab5/lab5_1_painter/mainwindow.ui | 94 +++++++ .../Lab5/lab5_2_gomoku/boardwidget.cpp | 236 ++++++++++++++++++ .../Lab5/lab5_2_gomoku/boardwidget.h | 59 +++++ .../Lab5/lab5_2_gomoku/gamewidget.cpp | 32 +++ .../Lab5/lab5_2_gomoku/gamewidget.h | 22 ++ .../Lab5/lab5_2_gomoku/lab5_2_gomoku.pro | 33 +++ SoftwareDesign/Lab5/lab5_2_gomoku/main.cpp | 11 + 11 files changed, 633 insertions(+) create mode 100644 SoftwareDesign/Lab5/lab5_1_painter/lab5_1_painter.pro create mode 100644 SoftwareDesign/Lab5/lab5_1_painter/main.cpp create mode 100644 SoftwareDesign/Lab5/lab5_1_painter/mainwindow.cpp create mode 100644 SoftwareDesign/Lab5/lab5_1_painter/mainwindow.h create mode 100644 SoftwareDesign/Lab5/lab5_1_painter/mainwindow.ui create mode 100644 SoftwareDesign/Lab5/lab5_2_gomoku/boardwidget.cpp create mode 100644 SoftwareDesign/Lab5/lab5_2_gomoku/boardwidget.h create mode 100644 SoftwareDesign/Lab5/lab5_2_gomoku/gamewidget.cpp create mode 100644 SoftwareDesign/Lab5/lab5_2_gomoku/gamewidget.h create mode 100644 SoftwareDesign/Lab5/lab5_2_gomoku/lab5_2_gomoku.pro create mode 100644 SoftwareDesign/Lab5/lab5_2_gomoku/main.cpp diff --git a/SoftwareDesign/Lab5/lab5_1_painter/lab5_1_painter.pro b/SoftwareDesign/Lab5/lab5_1_painter/lab5_1_painter.pro new file mode 100644 index 0000000..d01e364 --- /dev/null +++ b/SoftwareDesign/Lab5/lab5_1_painter/lab5_1_painter.pro @@ -0,0 +1,24 @@ +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# You can make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + main.cpp \ + mainwindow.cpp + +HEADERS += \ + mainwindow.h + +FORMS += \ + mainwindow.ui + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/SoftwareDesign/Lab5/lab5_1_painter/main.cpp b/SoftwareDesign/Lab5/lab5_1_painter/main.cpp new file mode 100644 index 0000000..fd3e533 --- /dev/null +++ b/SoftwareDesign/Lab5/lab5_1_painter/main.cpp @@ -0,0 +1,11 @@ +#include "mainwindow.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + return a.exec(); +} diff --git a/SoftwareDesign/Lab5/lab5_1_painter/mainwindow.cpp b/SoftwareDesign/Lab5/lab5_1_painter/mainwindow.cpp new file mode 100644 index 0000000..168c695 --- /dev/null +++ b/SoftwareDesign/Lab5/lab5_1_painter/mainwindow.cpp @@ -0,0 +1,71 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +bool enable = false; +bool drawing = false; +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent), ui(new Ui::MainWindow) { + ui->setupUi(this); + this->setProperty("canMove", false); + resize(600, 500); //窗口大小设置为600*500 + pix = QPixmap(600, 500); + pix.fill(Qt::white); +} + +MainWindow::~MainWindow() { delete ui; } + +void MainWindow::on_styCor_triggered() //边框颜色 +{ + QPainter pp(&pix); // 根据鼠标指针前后两个位置就行绘制直线 + pp.drawLine( + lastPoint, + endPoint); // 让前一个坐标值等于后一个坐标值,这样就能实现画出连续的线 + lastPoint = endPoint; + QPainter painter(this); + painter.drawPixmap(0, 0, pix); +} + +void MainWindow::paintEvent(QPaintEvent *event) { + if (enable) + switch (drawStatus) { + case line: + QPainter pp(&pix); // 根据鼠标指针前后两个位置就行绘制直线 + pp.drawLine( + lastPoint, + endPoint); // 让前一个坐标值等于后一个坐标值,这样就能实现画出连续的线 + enable = false; + } + QPainter painter(this); + painter.drawPixmap(0, 0, pix); + + drawStatus = idle; +} +void MainWindow::drawLineTriger() { drawStatus = line; } + +void MainWindow::on_drawLine_triggered() { + enable = true; + drawStatus = line; +} + +void MainWindow::mousePressEvent(QMouseEvent *event) { + + if (event->button() == Qt::LeftButton) //鼠标左键按下 + if (drawing) { + endPoint = event->pos(); + drawing = false; + enable = true; + update(); + } else { + drawing = true; + lastPoint = event->pos(); + } +} diff --git a/SoftwareDesign/Lab5/lab5_1_painter/mainwindow.h b/SoftwareDesign/Lab5/lab5_1_painter/mainwindow.h new file mode 100644 index 0000000..c82099f --- /dev/null +++ b/SoftwareDesign/Lab5/lab5_1_painter/mainwindow.h @@ -0,0 +1,40 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +enum DS { idle, line, circle, rec, tri, set, clr }; + +QT_BEGIN_NAMESPACE +namespace Ui { +class MainWindow; +} +QT_END_NAMESPACE + +class MainWindow : public QMainWindow { + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +protected: + void paintEvent(QPaintEvent *event); + void drawLineTriger(); + int num1, num2, num3, num4; + void mousePressEvent(QMouseEvent *); + // void mouseMoveEvent(QMouseEvent *); + // void mouseReleaseEvent(QMouseEvent *); + +private slots: + void on_styCor_triggered(); + void on_drawLine_triggered(); + +private: + QPixmap pix; + QPoint lastPoint; + QPoint endPoint; + DS drawStatus = idle; + Ui::MainWindow *ui; +}; +#endif // MAINWINDOW_H diff --git a/SoftwareDesign/Lab5/lab5_1_painter/mainwindow.ui b/SoftwareDesign/Lab5/lab5_1_painter/mainwindow.ui new file mode 100644 index 0000000..d03c876 --- /dev/null +++ b/SoftwareDesign/Lab5/lab5_1_painter/mainwindow.ui @@ -0,0 +1,94 @@ + + + MainWindow + + + + 0 + 0 + 800 + 600 + + + + MainWindow + + + + + + + 0 + 0 + 800 + 30 + + + + + 绘制 + + + + + + + + + 设置 + + + + + + + + + + + + 直线 + + + + + 圆形 + + + + + 矩形 + + + + + 晴空 + + + 清空 + + + + + 边框颜色 + + + + + 边框粗细 + + + + + 边框样式 + + + + + 背景颜色 + + + + + + diff --git a/SoftwareDesign/Lab5/lab5_2_gomoku/boardwidget.cpp b/SoftwareDesign/Lab5/lab5_2_gomoku/boardwidget.cpp new file mode 100644 index 0000000..aca2be3 --- /dev/null +++ b/SoftwareDesign/Lab5/lab5_2_gomoku/boardwidget.cpp @@ -0,0 +1,236 @@ +#include "boardwidget.h" +#include +#include + +/*类静态数据成员定义*/ +const QSize BoardWidget::WIDGET_SIZE(430, 430); +const QSize BoardWidget::CELL_SIZE(25, 25); +const QPoint BoardWidget::START_POS(40, 40); +const QPoint BoardWidget::ROW_NUM_START(15, 45); +const QPoint BoardWidget::CLU_NUM_START(39, 25); +const int BoardWidget::BOARD_WIDTH; +const int BoardWidget::BOARD_HEIGHT; +const int BoardWidget::NO_PIECE; +const int BoardWidget::WHITE_PIECE; +const int BoardWidget::BLACK_PIECE; +const bool BoardWidget::WHITE_PLAYER; +const bool BoardWidget::BLACK_PLAYER; + +BoardWidget::BoardWidget(QWidget *parent) : QWidget(parent) { + setFixedSize(WIDGET_SIZE); + setMouseTracking(true); + + initBoard(); +} + +void BoardWidget::paintEvent(QPaintEvent *event) { + QPainter painter(this); + painter.fillRect(0, 0, width(), height(), Qt::gray); //背景颜色 + + for (int i = 0; i < BOARD_WIDTH; i++) { + painter.drawText(CLU_NUM_START + QPoint(i * CELL_SIZE.width(), 0), + QString::number(i + 1)); + } + for (int i = 0; i < BOARD_HEIGHT; i++) { + painter.drawText(ROW_NUM_START + QPoint(0, i * CELL_SIZE.height()), + QString::number(i + 1)); + } + + for (int i = 0; i < BOARD_WIDTH - 1; i++) //绘制棋盘格子 + { + for (int j = 0; j < BOARD_HEIGHT - 1; j++) { + painter.drawRect(QRect( + START_POS + QPoint(i * CELL_SIZE.width(), j * CELL_SIZE.height()), + CELL_SIZE)); + } + } + + painter.setPen(Qt::red); //落子提示 + QPoint poses[12] = {trackPos + QPoint(0, 8), trackPos, + trackPos + QPoint(8, 0), trackPos + QPoint(17, 0), + trackPos + QPoint(25, 0), trackPos + QPoint(25, 8), + trackPos + QPoint(25, 17), trackPos + QPoint(25, 25), + trackPos + QPoint(17, 25), trackPos + QPoint(8, 25), + trackPos + QPoint(0, 25), trackPos + QPoint(0, 17)}; + painter.drawPolyline(poses, 3); + painter.drawPolyline(poses + 3, 3); + painter.drawPolyline(poses + 6, 3); + painter.drawPolyline(poses + 9, 3); + + painter.setPen(Qt::NoPen); + for (int i = 0; i < BOARD_WIDTH; i++) //绘制棋子 + { + for (int j = 0; j < BOARD_HEIGHT; j++) { + if (board[i][j] != NO_PIECE) { + QColor color = (board[i][j] == WHITE_PIECE) ? Qt::white : Qt::black; + painter.setBrush(QBrush(color)); + painter.drawEllipse( + START_POS.x() - CELL_SIZE.width() / 2 + i * CELL_SIZE.width(), + START_POS.y() - CELL_SIZE.height() / 2 + j * CELL_SIZE.height(), + CELL_SIZE.width(), CELL_SIZE.height()); + } + } + } + + painter.setPen(Qt::red); + if (lastPos.x() != -1) { + QPoint drawPos = START_POS + QPoint(lastPos.x() * CELL_SIZE.width(), + lastPos.y() * CELL_SIZE.height()); + painter.drawLine(drawPos + QPoint(0, 5), drawPos + QPoint(0, -5)); + painter.drawLine(drawPos + QPoint(5, 0), drawPos + QPoint(-5, 0)); + } + + for (QPoint pos : winPoses) { + QPoint drawPos = START_POS + QPoint(pos.x() * CELL_SIZE.width(), + pos.y() * CELL_SIZE.height()); + painter.drawLine(drawPos + QPoint(0, 5), drawPos + QPoint(0, -5)); + painter.drawLine(drawPos + QPoint(5, 0), drawPos + QPoint(-5, 0)); + } +} + +void BoardWidget::mouseReleaseEvent(QMouseEvent *event) { + if (!endGame) { + QPoint pos = event->pos() - START_POS; + int x = pos.x(); + int y = pos.y(); + int pieceX = x / CELL_SIZE.width(); + int pieceY = y / CELL_SIZE.height(); + int offsetX = x % CELL_SIZE.width(); + int offsetY = y % CELL_SIZE.height(); + if (offsetX > CELL_SIZE.width() / 2) { + pieceX++; + } + if (offsetY > CELL_SIZE.height() / 2) { + pieceY++; + } + downPiece(pieceX, pieceY); + } +} + +void BoardWidget::mouseMoveEvent(QMouseEvent *event) { + QPoint pos = event->pos() - START_POS + + QPoint(CELL_SIZE.width() / 2, CELL_SIZE.height() / 2); + int x = pos.x(); + int y = pos.y(); + //超过范围 + if (x < 0 || x >= CELL_SIZE.width() * BOARD_WIDTH || y < 0 || + y >= CELL_SIZE.height() * BOARD_HEIGHT) { + return; + } + int offsetX = x % CELL_SIZE.width(); + int offsetY = y % CELL_SIZE.height(); + setTrackPos(QPoint(x - offsetX, y - offsetY) + START_POS - + QPoint(CELL_SIZE.width() / 2, CELL_SIZE.height() / 2)); +} + +void BoardWidget::initBoard() { + for (int i = 0; i < BOARD_WIDTH; i++) { + for (int j = 0; j < BOARD_HEIGHT; j++) { + board[i][j] = NO_PIECE; + } + } + trackPos = QPoint(28, 28); + lastPos = QPoint(-1, -1); + endGame = false; + winPoses.clear(); + nextPlayer = BLACK_PLAYER; +} + +void BoardWidget::downPiece(int x, int y) { + if (x >= 0 && x < BOARD_WIDTH && y >= 0 && y < BOARD_HEIGHT && + board[x][y] == NO_PIECE) { + board[x][y] = (nextPlayer == WHITE_PLAYER) ? WHITE_PIECE : BLACK_PIECE; + nextPlayer = !nextPlayer; + lastPos = QPoint(x, y); + checkWinner(); + update(); + } +} + +void BoardWidget::checkWinner() { + bool fullPieces = true; + for (int i = 0; i < BOARD_WIDTH; i++) { + for (int j = 0; j < BOARD_HEIGHT; j++) { + if (board[i][j] == NO_PIECE) { + fullPieces = false; + } + if (board[i][j] != NO_PIECE && isFivePieceFrom(i, j)) { + bool winner = + (board[i][j] == WHITE_PIECE) ? WHITE_PLAYER : BLACK_PLAYER; + endGame = true; + emit gameOver(winner); + } + } + } + if (fullPieces) { + endGame = true; + emit gameOver(2); //代表和棋 + } +} + +bool BoardWidget::isFivePieceFrom(int x, int y) { + return isVFivePieceFrom(x, y) || isHFivePieceFrom(x, y) || + isFSFivePieceFrom(x, y) || isBSFivePieceFrom(x, y); +} + +bool BoardWidget::isVFivePieceFrom(int x, int y) { + int piece = board[x][y]; + for (int i = 1; i < 5; i++) { + if (y + i >= BOARD_HEIGHT || board[x][y + i] != piece) { + return false; + } + } + winPoses.clear(); + for (int i = 0; i < 5; i++) { + winPoses.append(QPoint(x, y + i)); + } + return true; +} + +bool BoardWidget::isHFivePieceFrom(int x, int y) { + int piece = board[x][y]; + for (int i = 1; i < 5; i++) { + if (x + i >= BOARD_WIDTH || board[x + i][y] != piece) { + return false; + } + } + winPoses.clear(); + for (int i = 0; i < 5; i++) { + winPoses.append(QPoint(x + i, y)); + } + return true; +} + +bool BoardWidget::isFSFivePieceFrom(int x, int y) { + int piece = board[x][y]; + for (int i = 1; i < 5; i++) { + if (x + i >= BOARD_WIDTH || y - i < 0 || board[x + i][y - i] != piece) { + return false; + } + } + winPoses.clear(); + for (int i = 0; i < 5; i++) { + winPoses.append(QPoint(x + i, y - i)); + } + return true; +} + +bool BoardWidget::isBSFivePieceFrom(int x, int y) { + int piece = board[x][y]; + for (int i = 1; i < 5; i++) { + if (x + i >= BOARD_WIDTH || y + i >= BOARD_HEIGHT || + board[x + i][y + i] != piece) { + return false; + } + } + winPoses.clear(); + for (int i = 0; i < 5; i++) { + winPoses.append(QPoint(x + i, y + i)); + } + return true; +} + +void BoardWidget::setTrackPos(const QPoint &value) { + trackPos = value; + update(); +} diff --git a/SoftwareDesign/Lab5/lab5_2_gomoku/boardwidget.h b/SoftwareDesign/Lab5/lab5_2_gomoku/boardwidget.h new file mode 100644 index 0000000..01618a1 --- /dev/null +++ b/SoftwareDesign/Lab5/lab5_2_gomoku/boardwidget.h @@ -0,0 +1,59 @@ +#ifndef BOARDWIDGET_H +#define BOARDWIDGET_H + +#include +#include +#include + +class BoardWidget : public QWidget +{ + Q_OBJECT +public: + explicit BoardWidget(QWidget *parent = nullptr); + +protected: + void paintEvent(QPaintEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + +private: + void downPiece(int x, int y); + void checkWinner(); + bool isFivePieceFrom(int x, int y); //判断从(x, y)处开始,是否有五个同色棋子在一条线上 + bool isVFivePieceFrom(int x, int y); //判断从(x, y)处开始,向下是否有五个同色棋子 + bool isHFivePieceFrom(int x, int y); //判断从(x, y)处开始,向下是否有五个同色棋子 + bool isFSFivePieceFrom(int x, int y); //判断从(x, y)处开始,右上方向是否有五个同色棋子 + bool isBSFivePieceFrom(int x, int y); //判断(x, y)处开始, 右下方向是否有五个同色棋子 + void setTrackPos(const QPoint &value); + +signals: + void gameOver(int winner); + +public slots: + void initBoard(); + +public: + static const QSize WIDGET_SIZE; //棋盘控件大小 + static const QSize CELL_SIZE; //棋盘单元格大小 + static const QPoint START_POS; //棋盘单元格绘制开始位置 + static const QPoint ROW_NUM_START; //棋盘行号开始位置 + static const QPoint CLU_NUM_START; //棋盘列号开始位置 + static const int BOARD_WIDTH = 15; //棋盘列数 + static const int BOARD_HEIGHT = 15; //棋盘行数 + static const int NO_PIECE = 0; //棋子标志, 无子 + static const int WHITE_PIECE = 1; //棋子标志, 白子 + static const int BLACK_PIECE = 2; //棋子标志, 黑子 + static const bool WHITE_PLAYER = true; //棋手标志, 白方 + static const bool BLACK_PLAYER = false; //棋手标志, 黑方 + + +private: + bool endGame; //游戏结束标志 + int board[BOARD_WIDTH][BOARD_HEIGHT]; //棋盘数据 + int nextPlayer; //下一手棋手 + QPoint lastPos; //上一步位置 + QPoint trackPos; //鼠标在棋盘上的位置 + QVector winPoses; //五个相连的棋子位置 +}; + +#endif // BOARDWIDGET_H diff --git a/SoftwareDesign/Lab5/lab5_2_gomoku/gamewidget.cpp b/SoftwareDesign/Lab5/lab5_2_gomoku/gamewidget.cpp new file mode 100644 index 0000000..99d7d4f --- /dev/null +++ b/SoftwareDesign/Lab5/lab5_2_gomoku/gamewidget.cpp @@ -0,0 +1,32 @@ +#include "gamewidget.h" +#include +#include +#include +#include + +GameWidget::GameWidget(QWidget *parent) + : QWidget(parent) +{ + setWindowTitle("五子棋"); + boardWidget = new BoardWidget(this); + + connect(boardWidget, &BoardWidget::gameOver, this, &GameWidget::showWinner); +} + +GameWidget::~GameWidget() +{ + +} + +void GameWidget::showWinner(int winner) +{ + if (winner != 2) + { + QString playerName = (winner == BoardWidget::WHITE_PLAYER) ? "白方" : "黑方"; + QMessageBox::information(this, "游戏结束", tr("恭喜%1获胜!!").arg(playerName), QMessageBox::Ok); + } + else + { + QMessageBox::information(this, "游戏结束", "和棋!", QMessageBox::Ok); + } +} diff --git a/SoftwareDesign/Lab5/lab5_2_gomoku/gamewidget.h b/SoftwareDesign/Lab5/lab5_2_gomoku/gamewidget.h new file mode 100644 index 0000000..052187f --- /dev/null +++ b/SoftwareDesign/Lab5/lab5_2_gomoku/gamewidget.h @@ -0,0 +1,22 @@ +#ifndef GAMEWIDGET_H +#define GAMEWIDGET_H + +#include +#include "boardwidget.h" + +class GameWidget : public QWidget +{ + Q_OBJECT + +public: + GameWidget(QWidget *parent = 0); + ~GameWidget(); + +private: + void showWinner(int winner); + +private: + BoardWidget *boardWidget; +}; + +#endif // GAMEWIDGET_H diff --git a/SoftwareDesign/Lab5/lab5_2_gomoku/lab5_2_gomoku.pro b/SoftwareDesign/Lab5/lab5_2_gomoku/lab5_2_gomoku.pro new file mode 100644 index 0000000..7466af1 --- /dev/null +++ b/SoftwareDesign/Lab5/lab5_2_gomoku/lab5_2_gomoku.pro @@ -0,0 +1,33 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2018-02-23T15:56:45 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = lab5_2_gomoku +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which as been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + + +SOURCES += \ + main.cpp \ + gamewidget.cpp \ + boardwidget.cpp + +HEADERS += \ + gamewidget.h \ + boardwidget.h diff --git a/SoftwareDesign/Lab5/lab5_2_gomoku/main.cpp b/SoftwareDesign/Lab5/lab5_2_gomoku/main.cpp new file mode 100644 index 0000000..b172bca --- /dev/null +++ b/SoftwareDesign/Lab5/lab5_2_gomoku/main.cpp @@ -0,0 +1,11 @@ +#include "gamewidget.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + GameWidget w; + w.show(); + + return a.exec(); +}