当前位置:   article > 正文

C++实现五子棋(含步骤 结尾附完整代码)_五子棋程序c++代码

五子棋程序c++代码

使用C++实现五子棋大概分为以下四个步骤:

1.创建棋盘和游戏界面

2.实现棋子的绘制和落子

3.实现胜负判断和游戏结束

4.实现悔棋和重新开始功能

1.创建棋盘和游戏界面

首先,我们需要创建一个棋盘和游戏界面,可以使用Qt框架来实现。具体步骤如下:

1.1 创建Qt项目,并在主窗口中添加一个QGraphicsView控件,用于显示游戏界面。

1.2 在QGraphicsView中添加一个QGraphicsScene,用于绘制棋盘和棋子。

1.3 在QGraphicsScene中添加一个QPixmapItem,用于显示棋盘的背景图片。

1.4 将棋盘分成15行15列,使用QGraphicsRectItem绘制棋盘的格子。

示例代码如下:

  1. // 创建一个棋盘场景
  2. QGraphicsScene* scene = new QGraphicsScene(this);
  3. // 添加背景图片
  4. QPixmap pixmap(":/images/board.png");
  5. QGraphicsPixmapItem* pixmapItem = new QGraphicsPixmapItem(pixmap);
  6. scene->addItem(pixmapItem);
  7. // 绘制棋盘的格子
  8. const int kBoardSize = 15;
  9. const int kCellSize = 40;
  10. const int kMargin = 20;
  11. for (int i = 0; i < kBoardSize; i++) {
  12. for (int j = 0; j < kBoardSize; j++) {
  13. QGraphicsRectItem* rectItem = new QGraphicsRectItem(
  14. kMargin + i * kCellSize, kMargin + j * kCellSize,
  15. kCellSize, kCellSize);
  16. rectItem->setPen(QPen(Qt::black, 1));
  17. rectItem->setBrush(QBrush(Qt::white));
  18. scene->addItem(rectItem);
  19. }
  20. }
  21. // 将场景添加到视图中
  22. ui->graphicsView->setScene(scene);

2.实现棋子的绘制和落子

在游戏中,玩家需要能够通过鼠标点击来落子,并且需要在棋盘上显示出来。具体步骤如下:

2.1 创建一个QGraphicsEllipseItem,用于绘制棋子。

2.2 响应鼠标点击事件,获取鼠标点击的位置。

2.3 将鼠标点击的位置转换为棋盘上的坐标。

2.4 判断该位置是否已经有棋子,如果没有则在该位置落子。

2.5 落子后,判断游戏是否结束。

示例代码如下:

  1. // 定义棋子的半径和颜色
  2. const int kPieceRadius = 18;
  3. const QColor kBlackPieceColor(Qt::black);
  4. const QColor kWhitePieceColor(Qt::white);
  5. // 创建一个棋子场景
  6. QGraphicsScene* scene = new QGraphicsScene(this);
  7. // 添加背景图片
  8. ...
  9. // 绘制棋盘的格子
  10. ...
  11. // 响应鼠标点击事件
  12. void GameWidget::mousePressEvent(QMouseEvent *event) {
  13. // 获取鼠标点击的位置
  14. QPointF pos = ui->graphicsView->mapToScene(event->pos());
  15. // 将鼠标点击的位置转换为棋盘上的坐标
  16. int x = (pos.x() - kMargin + kCellSize / 2) / kCellSize;
  17. int y = (pos.y() - kMargin + kCellSize / 2) / kCellSize;
  18. // 判断该位置是否已经有棋子
  19. if (board_[x][y] != kEmpty) {
  20. return;
  21. }
  22. // 在该位置落子
  23. board_[x][y] = currentPlayer_;
  24. QGraphicsEllipseItem* pieceItem = new QGraphicsEllipseItem(
  25. kMargin + x * kCellSize - kPieceRadius,
  26. kMargin + y * kCellSize - kPieceRadius,
  27. kPieceRadius * 2, kPieceRadius * 2);
  28. pieceItem->setPen(QPen(Qt::black, 1));
  29. pieceItem->setBrush续上:
  30. (currentPlayer_ == kBlack ? kBlackPieceColor : kWhitePieceColor));
  31. scene->addItem(pieceItem);
  32. // 判断游戏是否结束
  33. if (checkWin(x, y)) {
  34. QMessageBox::information(this, tr("Game Over"),
  35. QString("%1 Win!").arg(currentPlayer_ == kBlack ? tr("Black") : tr("White")));
  36. resetGame();
  37. return;
  38. }
  39. if (checkTie()) {
  40. QMessageBox::information(this, tr("Game Over"), tr("Tie!"));
  41. resetGame();
  42. return;
  43. }
  44. // 切换玩家
  45. currentPlayer_ = (currentPlayer_ == kBlack ? kWhite : kBlack);
  46. }
  47. // 判断是否五子连珠
  48. bool GameWidget::checkWin(int x, int y) {
  49. int count = 1;
  50. int i, j;
  51. // 判断横向是否五子连珠
  52. for (i = x - 1; i >= 0 && board_[i][y] == currentPlayer_; i--) {
  53. count++;
  54. }
  55. for (i = x + 1; i < kBoardSize && board_[i][y] == currentPlayer_; i++) {
  56. count++;
  57. }
  58. if (count >= 5) {
  59. return true;
  60. }
  61. // 判断纵向是否五子连珠
  62. count = 1;
  63. for (j = y - 1; j >= 0 && board_[x][j] == currentPlayer_; j--) {
  64. count++;
  65. }
  66. for (j = y + 1; j < kBoardSize && board_[x][j] == currentPlayer_; j++) {
  67. count++;
  68. }
  69. if (count >= 5) {
  70. return true;
  71. }
  72. // 判断左上到右下是否五子连珠
  73. count = 1;
  74. for (i = x - 1, j = y - 1; i >= 0 && j >= 0 && board_[i][j] == currentPlayer_; i--, j--) {
  75. count++;
  76. }
  77. for (i = x + 1, j = y + 1; i < kBoardSize && j < kBoardSize && board_[i][j] == currentPlayer_; i++, j++) {
  78. count++;
  79. }
  80. if (count >= 5) {
  81. return true;
  82. }
  83. // 判断左下到右上是否五子连珠
  84. count = 1;
  85. for (i = x - 1, j = y + 1; i >= 0 && j < kBoardSize && board_[i][j] == currentPlayer_; i--, j++) {
  86. count++;
  87. }
  88. for (i = x + 1, j = y - 1; i < kBoardSize && j >= 0 && board_[i][j] == currentPlayer_; i++, j--) {
  89. count++;
  90. }
  91. if (count >= 5) {
  92. return true;
  93. }
  94. return false;
  95. }
  96. // 判断是否平局
  97. bool GameWidget::checkTie() {
  98. for (int i = 0; i < kBoardSize; i++) {
  99. for (int j = 0; j < kBoardSize; j++) {
  100. if (board_[i][j] == kEmpty) {
  101. return false;
  102. }
  103. }
  104. }
  105. return true;
  106. }

3.实现胜负判断和游戏结束

在落子后,需要判断游戏是否结束。如果有一方获得了五子连珠,则该方获胜;如果棋盘已经填满,但仍然没有五子连珠,则游戏结束,双方平局。具体步骤如下:

3.1 编写checkWin函数,用于判断是否存在五子连珠。

3.2 编写checkTie函数,用于判断是否平局。

3.3 在落子后,判断游戏是否结束。如果游戏结束,则弹出游戏结束信息,并重置游戏。

示例代码如下:

  1. // 在GameWidget类中添加以下成员变量
  2. private:
  3. QGraphicsScene* scene; // 棋盘场景
  4. QGraphicsEllipseItem* lastItem_; // 上一个落子的棋子
  5. PieceType board_[kBoardSize][kBoardSize]; // 棋盘数组
  6. PieceType currentPlayer_; // 当前玩家
  7. // 在GameWidget类的构造函数中添加以下代码,用于初始化棋盘
  8. GameWidget::GameWidget(QWidget *parent) :
  9. QWidget(parent),
  10. ui(new Ui::GameWidget)
  11. {
  12. ui->setupUi(this);
  13. // 创建棋盘场景
  14. scene = new QGraphicsScene(this);
  15. ui->boardView->setScene(scene);
  16. ui->boardView->setRenderHint(QPainter::Antialiasing);
  17. // 绘制棋盘
  18. for (int i = 0; i < kBoardSize; i++) {
  19. for (int j = 0; j < kBoardSize; j++) {
  20. QGraphicsRectItem* rect = new QGraphicsRectItem(i * kCellSize, j * kCellSize, kCellSize, kCellSize);
  21. rect->setPen(Qt::NoPen);
  22. rect->setBrush(QBrush(QColor("#D18B47"), Qt::SolidPattern));
  23. scene->addItem(rect);
  24. }
  25. }
  26. // 初始化棋盘数组
  27. for (int i = 0; i < kBoardSize; i++) {
  28. for (int j = 0; j < kBoardSize; j++) {
  29. board_[i][j] = kEmpty;
  30. }
  31. }
  32. // 初始化当前玩家为黑色
  33. currentPlayer_ = kBlack;
  34. ui->statusLabel->setText(tr("Black's turn"));
  35. }
  36. // 响应落子事件
  37. void GameWidget::mousePressEvent(QMouseEvent* event) {
  38. if (event->button() != Qt::LeftButton) {
  39. return;
  40. }
  41. QPointF pos = ui->boardView->mapToScene(event->pos());
  42. // 将落点转换为棋盘坐标
  43. int x = qRound(pos.x() / kCellSize);
  44. int y = qRound(pos.y() / kCellSize);
  45. // 判断落点是否有效,如果无效则返回
  46. if (x < 0 || x >= kBoardSize || y < 0 || y >= kBoardSize || board_[x][y] != kEmpty) {
  47. return;
  48. }
  49. // 在落点绘制棋子
  50. QGraphicsEllipseItem* item = new QGraphicsEllipseItem(x * kCellSize + kMargin, y * kCellSize + kMargin,
  51. kPieceSize, kPieceSize);
  52. item->setBrush(QBrush((currentPlayer_ == kBlack) ? Qt::black : Qt::white, Qt::SolidPattern));
  53. scene->addItem(item);
  54. // 记录落子位置和棋子对象
  55. QPoint point(x, y);
  56. history_.push(point);
  57. lastItem_ = item;
  58. // 更新棋盘数组
  59. board_[x][y] = currentPlayer_;
  60. // 判断游戏是否结束
  61. if (checkWin(x, y)) {
  62. QString message = (currentPlayer_ == kBlack) ? tr("Black wins!") : tr("White wins!");
  63. QMessageBox::StandardButton button = QMessageBox::information(this, tr("Game Over"), message);
  64. if (button == QMessageBox::Ok) {
  65. resetGame();
  66. }
  67. return;
  68. } else if (checkTie()) {
  69. QMessageBox::StandardButton button = QMessageBox::information(this, tr("Game Over"), tr("Tie!"));
  70. if (button == QMessageBox::Ok) {
  71. resetGame();
  72. }
  73. return;
  74. }
  75. // 切换玩家
  76. currentPlayer_ = (currentPlayer_ == kBlack) ? kWhite : kBlack;
  77. ui->statusLabel->setText((currentPlayer_ == kBlack) ? tr("Black's turn") : tr("White's turn"));
  78. }
  79. // 判断是否五子连珠
  80. bool GameWidget::checkWin(int x, int y) {
  81. int i, j, count;
  82. // 判断横向是否五子连珠
  83. count = 1;
  84. for (i = x - 1; i >= 0 && board_[i][y] == currentPlayer_; i--) {
  85. count++;
  86. }
  87. for (i = x + 1; i < kBoardSize && board_[i][y] == currentPlayer_; i++) {
  88. count++;
  89. }
  90. if (count >= 5)请注意,在这段代码中,有一些变量和常量没有定义。其中,kBoardSize、kCellSize、kMargin、kPieceSize、kEmpty、kBlack、kWhite都是需要定义的。如果您已经在之前的代码中定义了这些变量和常量,可以直接使用以下代码片段。如果没有,请先定义这些变量和常量,再使用以下代码片段。
  91. ```cpp
  92. const int kBoardSize = 15; // 棋盘大小
  93. const int kCellSize = 40; // 格子大小
  94. const int kMargin = 20; // 棋盘边距
  95. const int kPieceSize = 30; // 棋子大小
  96. enum PieceType {
  97. kEmpty,
  98. kBlack,
  99. kWhite
  100. };

4.实现悔棋和重新开始

在游戏中,玩家需要能够进行悔棋和重新开始游戏。具体步骤如下:

4.1 在界面上添加两个按钮,分别用于悔棋和重新开始游戏。

4.2 响应按钮点击事件,实现悔棋和重新开始游戏的功能。

4.3 在实现悔棋功能时,需要将棋盘上最后一个落子的位置清空。

示例代码如下:

  1. // 在界面上添加两个按钮
  2. ui->undoButton->setText(tr("悔棋"));
  3. connect(ui->undoButton, &QPushButton::clicked, this, &GameWidget::undo);
  4. ui->restartButton->setText(tr("重新开始"));
  5. connect(ui->restartButton, &QPushButton::clicked, this, &GameWidget::restart);
  6. // 实现悔棋功能
  7. void GameWidget::undo() {
  8. // 获取棋盘上最后一个落子的位置
  9. int x = history_.back().x;
  10. int y = history_.back().y;
  11. // 清空该位置的棋子
  12. board_[x][y] = kEmpty;
  13. QGraphicsItem* item = scene_->itemAt(
  14. kMargin + x * kCellSize, kMargin + y * kCellSize,
  15. QTransform());
  16. if (item != nullptr) {
  17. scene_->removeItem(item);
  18. delete item;
  19. }
  20. // 移除落子历史记录中的最后一个位置
  21. history_.pop_back();
  22. // 切换当前玩家
  23. currentPlayer_ = (currentPlayer_ == kBlack) ? kWhite : kBlack;
  24. }
  25. // 实现重新开始游戏的功能
  26. void GameWidget::restart() {
  27. // 清空棋盘
  28. memset(board_, kEmpty, sizeof(board_));
  29. // 清空场景中的棋子
  30. QList<QGraphicsItem*> items = scene_->items();
  31. for (auto item : items) {
  32. scene_->removeItem(item);
  33. delete item;
  34. }
  35. // 清空落子历史记录
  36. history_.clear();
  37. // 切换当前玩家
  38. currentPlayer_ = kBlack;
  39. }

以上就是使用C++实现五子棋游戏的详细代码教程,包括棋盘和游戏界面的创建、棋子的绘制和落子、胜负判断和游戏结束、悔棋和重新开始功能。由于篇幅限制,代码中可能存在一些细节问题,需要根据具体情况进行调整。

以下是完整代码:

  1. #include "gamewidget.h"
  2. #include "ui_gamewidget.h"
  3. #include <QGraphicsRectItem>
  4. #include <QGraphicsEllipseItem>
  5. #include <QMessageBox>
  6. const int kBoardSize = 15; // 棋盘大小
  7. const int kCellSize = 40; // 格子大小
  8. const int kMargin = 20; // 棋盘边距
  9. const int kPieceSize = 30; // 棋子大小
  10. enum PieceType {
  11. kEmpty,
  12. kBlack,
  13. kWhite
  14. };
  15. GameWidget::GameWidget(QWidget *parent) :
  16. QWidget(parent),
  17. ui(new Ui::GameWidget)
  18. {
  19. ui->setupUi(this);
  20. // 创建棋盘场景
  21. scene = new QGraphicsScene(this);
  22. ui->boardView->setScene(scene);
  23. ui->boardView->setRenderHint(QPainter::Antialiasing);
  24. // 绘制棋盘
  25. for (int i = 0; i < kBoardSize; i++) {
  26. for (int j = 0; j < kBoardSize; j++) {
  27. QGraphicsRectItem* rect = new QGraphicsRectItem(i * kCellSize, j * kCellSize, kCellSize, kCellSize);
  28. rect->setPen(Qt::NoPen);
  29. rect->setBrush(QBrush(QColor("#D18B47"), Qt::SolidPattern));
  30. scene->addItem(rect);
  31. }
  32. }
  33. // 初始化棋盘数组
  34. for (int i = 0; i < kBoardSize; i++) {
  35. for (int j = 0; j < kBoardSize; j++) {
  36. board_[i][j] = kEmpty;
  37. }
  38. }
  39. // 初始化当前玩家为黑色
  40. currentPlayer_ = kBlack;
  41. ui->statusLabel->setText(tr("Black's turn"));
  42. }
  43. GameWidget::~GameWidget()
  44. {
  45. delete ui;
  46. }
  47. void GameWidget::mousePressEvent(QMouseEvent* event) {
  48. if (event->button() != Qt::LeftButton) {
  49. return;
  50. }
  51. QPointF pos = ui->boardView->mapToScene(event->pos());
  52. // 将落点转换为棋盘坐标
  53. int x = qRound(pos.x() / kCellSize);
  54. int y = qRound(pos.y() / kCellSize);
  55. // 判断落点是否有效,如果无效则返回
  56. if (x < 0 || x >= kBoardSize || y < 0 || y >= kBoardSize || board_[x][y] != kEmpty) {
  57. return;
  58. }
  59. // 在落点绘制棋子
  60. QGraphicsEllipseItem* item = new QGraphicsEllipseItem(x * kCellSize + kMargin, y * kCellSize + kMargin,
  61. kPieceSize, kPieceSize);
  62. item->setBrush(QBrush((currentPlayer_ == kBlack) ? Qt::black : Qt::white, Qt::SolidPattern));
  63. scene->addItem(item);
  64. // 记录落子位置和棋子对象
  65. QPoint point(x, y);
  66. history_.push(point);
  67. lastItem_ = item;
  68. // 更新棋盘数组
  69. board_[x][y] = currentPlayer_;
  70. // 判断游戏是否结束
  71. if (checkWin(x, y)) {
  72. QString message = (currentPlayer_ == kBlack) ? tr("Black wins!") : tr("White wins!");
  73. QMessageBox::StandardButton button = QMessageBox::information(this, tr("Game Over"), message);
  74. if (button == QMessageBox::Ok) {
  75. resetGame();
  76. }
  77. return;
  78. } else if (checkTie()) {
  79. QMessageBox::StandardButton button = QMessageBox::information(this, tr("Game Over"), tr("Tie!"));
  80. if (button == QMessageBox::Ok) {
  81. resetGame();
  82. }
  83. return;
  84. }
  85. // 切换玩家
  86. currentPlayer_ = (currentPlayer_ == kBlack) ? kWhite : kBlack;
  87. ui->statusLabel->setText((currentPlayer_ == kBlack) ? tr("Black's turn") : tr("White's turn"));
  88. }
  89. bool GameWidget::checkWin(int x, int y) {
  90. int i, j, count;
  91. // 判断横向是否五子连珠
  92. count = 1;
  93. for (i = x - 1; i >= 0 && board_[i][y] == currentPlayer_; i--) {
  94. count++;
  95. }
  96. for (i = x + 1; i < kBoardSize && board_[i][y] == currentPlayer_; i++) {
  97. count++;
  98. }
  99. if (count >= 5) {
  100. return true;
  101. }
  102. // 判断纵向是否五子连珠
  103. count = 1;
  104. for (j = y - 1; j >= 0 && board_[x][j] == currentPlayer_; j--) {
  105. count++;
  106. }
  107. for (j = y + 1; j < kBoardSize && board_[x][j] == currentPlayer_; j++) {
  108. count++;
  109. }
  110. if (count >= 5) {
  111. return true;
  112. }
  113. // 判断左上到右下是否五子连珠
  114. count = 1;
  115. for (i = x - 1, j = y - 1; i >= 0 && j >= 0 && board_[i][j] == currentPlayer_; i--, j--) {
  116. count++;
  117. }
  118. for (i = x + 1, j = y + 1; i < kBoardSize && j < kBoardSize && board_[i][j] == currentPlayer_; i++, j++) {
  119. count++;
  120. }
  121. if (count >= 5) {
  122. return true;
  123. }
  124. // 判断左下到右上是否五子连珠
  125. count = 1;
  126. for (i = x - 1, j = y + 1; i >= 0 && j < kBoardSize && board_[i][j] == currentPlayer_; i--, j++) {
  127. count++;
  128. }
  129. for (i = x + 1, j = y - 1; i < kBoardSize && j >= 0 && board_[i][j] == currentPlayer_; i++, j--) {
  130. count++;
  131. }
  132. if (count >= 5) {
  133. return true;
  134. }
  135. return false;
  136. }
  137. bool GameWidget::checkTie() {
  138. for (int i = 0; i < kBoardSize; i++) {
  139. for (int j = 0; j < kBoardSize; j++) {
  140. if (board_[i][j] == kEmpty) {
  141. return false;
  142. }
  143. }
  144. }
  145. return true;
  146. }
  147. void GameWidget::resetGame() {
  148. // 清空棋盘场景和棋盘数组
  149. scene->clear();
  150. for (int i = 0; i < kBoardSize; i++) {
  151. for (int j = 0; j < kBoardSize; j++) {
  152. board_[i][j] = kEmpty;
  153. }
  154. }
  155. // 重置历史记录和当前玩家
  156. while (!history_.empty()) {
  157. history_.pop();
  158. }
  159. currentPlayer_ = kBlack;
  160. // 更新状态栏
  161. ui->statusLabel->setText(tr("Black's turn"));
  162. }
  163. void GameWidget::undo() {
  164. // 如果历史记录为空,则返回
  165. if (history_.empty()) {
  166. return;
  167. }
  168. // 恢复上一个落子点的状态,并从历史记录中删除该点
  169. QPoint point = history_.top();
  170. history_.pop();
  171. board_[point.x()][point.y()] = kEmpty;
  172. scene->removeItem(lastItem_);
  173. delete lastItem_;
  174. lastItem_ = nullptr;
  175. // 切换当前玩家
  176. currentPlayer_ = (currentPlayer_ == kBlack) ? kWhite : kBlack;
  177. ui->statusLabel->setText((currentPlayer_ == kBlack) ? tr("Black's turn") : tr("White's turn"));
  178. }
  179. void GameWidget::newGame() {
  180. // 弹出确认对话框
  181. QMessageBox::StandardButton button = QMessageBox::question(this, tr("New Game"),
  182. tr("Are you sure you want to start a new game?"),
  183. QMessageBox::Yes | QMessageBox::No);
  184. if (button == QMessageBox::Yes) {
  185. resetGame();
  186. }
  187. }
  188. void GameWidget::saveGame() {
  189. // 弹出保存对话框,获取保存文件路径
  190. QString fileName = QFileDialog::getSaveFileName(this, tr("Save Game"), ".", tr("Game files (*.game)"));
  191. if (fileName.isEmpty()) {
  192. return;
  193. }
  194. // 打开保存文件,保存棋盘数组和当前玩家
  195. QFile file(fileName);
  196. if (file.open(QIODevice::WriteOnly)) {
  197. QDataStream stream(&file);
  198. stream.writeRawData((const char*)board_, sizeof(board_));
  199. stream << currentPlayer_;
  200. file.close();
  201. }
  202. }
  203. void GameWidget::loadGame() {
  204. // 弹出打开对话框,获取打开文件路径
  205. QString fileName = QFileDialog::getOpenFileName(this, tr("Load Game"), ".", tr("Game files (*.game)"));
  206. if (fileName.isEmpty()) {
  207. return;
  208. }
  209. // 打开保存文件,读取棋盘数组和当前玩家
  210. QFile file(fileName);
  211. if (file.open(QIODevice::ReadOnly)) {
  212. QDataStream stream(&file);
  213. stream.readRawData((char*)board_, sizeof(board_));
  214. stream >> currentPlayer_;
  215. file.close();
  216. // 清空棋盘场景,重新绘制棋盘和棋子
  217. scene->clear();
  218. for (int i = 0; i < kBoardSize; i++) {
  219. for (int j = 0; j < kBoardSize; j++) {
  220. QGraphicsRectItem* rect = new QGraphicsRectItem(i * kCellSize, j * kCellSize, kCellSize, kCellSize);
  221. rect->setPen(Qt::NoPen);
  222. rect->setBrush(QBrush(QColor("#D18B47"), Qt::SolidPattern));
  223. scene->addItem(rect);
  224. if (board_[i][j] != kEmpty) {
  225. QGraphicsEllipseItem* item = new QGraphicsEllipseItem(i * kCellSize + kMargin, j * kCellSize + kMargin,
  226. kPieceSize, kPieceSize);
  227. item->setBrush(QBrush((board_[i][j] == kBlack) ? Qt::black : Qt::white, Qt::SolidPattern));
  228. scene->addItem(item);
  229. }
  230. }
  231. }
  232. // 更新状态栏
  233. ui->statusLabel->setText((currentPlayer_ == kBlack) ? tr("Black's turn") : tr("White's turn"));
  234. }
  235. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/243702
推荐阅读
相关标签
  

闽ICP备14008679号