逆风微光 |
2018-05-20 12:33 |
《Qt实战小项目》2,五子棋游戏
这是我的CSDN博客专栏《Qt实战小项目》的系列文章第2篇。 专栏地址:https://blog.csdn.net/dpsying/category_9267660.html 目前专栏内有这些文章: QT项目一:俄罗斯方块游戏 QT项目二:五子棋游戏 QT项目三:中国象棋 QT项目四:扫雷游戏 QT项目五--计算器 QT项目六:简易客户信息管理系统 1,简介 QT5.5.1 开发的五子棋单机版,花了一个晚上+熬夜完成。 (2020-8-27:源码已改为QT5.11.1编译过) 2,效果 [attachment=21870] 3,思路
棋盘为15*15矩阵 棋子Item 存1个坐标点、一个颜色类型(黑棋还是白棋) 绘制顺序依次为 棋盘、棋子、鼠标(也是一个棋子) 核心算法(判断五子连): 对所下的棋子,向 8个方向分别统计相邻的同色棋子个数 8个方向为:左、左上、上、右上、右、右下、下、左下 然后在一条直线的2个方向的棋子个数加起来,即得到该直线上与所下棋子相邻的同色棋子个数 棋子类Item.h: 包含一个QPoint圆心坐标,和一个bool变量,代表是黑方还是白方 - #pragma once
#include <QPoint> class Item { public: Item(void); Item(QPoint pt,bool bBlack); ~Item(void); bool operator==(const Item &t1)const { return ((mPt == t1.mPt) && (mBlack == t1.mBlack)); } QPoint mPt; bool mBlack; private: };
MainWindow.h:QVector<Item> mItems 保存所有棋子
- #ifndef MAINWINDOW_H
#define MAINWINDOW_H #include <QMainWindow> #include "Item.h" namespace Ui { class MainWindow; } #define CHESS_ROWS 15 #define CHESS_COLUMES 15 #define RECT_WIDTH 50 #define RECT_HEIGHT 50 class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); protected: void paintEvent(QPaintEvent *); void mousePressEvent(QMouseEvent *); private: void DrawChessboard(); //画棋盘 void DrawItems(); //画棋子 void DrawItemWithMouse(); //画跟随鼠标的棋子 void DrawChessAtPoint(QPainter& painter,QPoint& pt); //统计某个方向(共8个方向)上的相连个数,用QPoint表示统计方向,如(1,1)表示右下方,(-1,0)表示向左 int CountNearItem(Item item,QPoint ptDirection); private: Ui::MainWindow *ui; QVector<Item> mItems; //所有棋子 bool mBlack; //当前是否该黑棋下 }; #endif // MAINWINDOW_H
MainWindow.cpp:
- #include "mainwindow.h"
#include "ui_mainwindow.h" #include "qpainter.h" #include "qevent.h" #include "qpoint.h" #include "qmessagebox.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->mainToolBar->hide(); ui->menuBar->hide(); resize((CHESS_COLUMES + 1)*RECT_WIDTH ,(CHESS_ROWS + 1)*RECT_HEIGHT); mBlack = true; } MainWindow::~MainWindow() { delete ui; } void MainWindow::paintEvent(QPaintEvent *e) { DrawChessboard(); //画棋盘 DrawItems(); //画棋子 DrawItemWithMouse(); //画鼠标(当前方的棋子形状) update(); } void MainWindow::DrawChessboard() { QPainter painter(this); painter.setRenderHint(QPainter::HighQualityAntialiasing, true); painter.setBrush(Qt::darkYellow); painter.setPen(QPen(QColor(Qt::black),2)); for(int i = 0;i<CHESS_COLUMES; i++) { for (int j = 0; j<CHESS_ROWS; j++) { painter.drawRect( (i+0.5)*RECT_WIDTH,(j+0.5)*RECT_HEIGHT,RECT_WIDTH,RECT_HEIGHT); } } } void MainWindow::DrawItems() { QPainter painter(this); painter.setPen(QPen(QColor(Qt::transparent))); for (int i = 0; i<mItems.size(); i++) { Item item = mItems[i]; if (item.mBlack) { painter.setBrush(Qt::black); } else { painter.setBrush(Qt::white); } DrawChessAtPoint(painter,item.mPt); } } void MainWindow::DrawChessAtPoint(QPainter& painter,QPoint& pt) { QPoint ptCenter((pt.x()+0.5)*RECT_WIDTH,(pt.y()+0.5)*RECT_HEIGHT); painter.drawEllipse(ptCenter,RECT_WIDTH / 2,RECT_HEIGHT / 2); } void MainWindow::DrawItemWithMouse() { QPainter painter(this); painter.setPen(QPen(QColor(Qt::transparent))); if (mBlack) { painter.setBrush(Qt::black); } else { painter.setBrush(Qt::white); } painter.drawEllipse(mapFromGlobal(QCursor::pos()),RECT_WIDTH / 2,RECT_HEIGHT / 2); } void MainWindow::mousePressEvent(QMouseEvent * e) { //求鼠标点击处的棋子点pt QPoint pt; pt.setX( (e->pos().x() ) / RECT_WIDTH); pt.setY( (e->pos().y() ) / RECT_HEIGHT); //如果已存在棋子,就什么也不做 for (int i = 0; i<mItems.size(); i++) { Item item = mItems[i]; if (item.mPt == pt) { //已有棋子 return; } } //不存在棋子,就下一个 Item item(pt,mBlack); mItems.append(item); //统计4个方向是否五子连 int nLeft = CountNearItem(item,QPoint(-1,0)); int nLeftUp = CountNearItem(item,QPoint(-1,-1)); int nUp = CountNearItem(item,QPoint(0,-1)); int nRightUp = CountNearItem(item,QPoint(1,-1)); int nRight = CountNearItem(item,QPoint(1,0)); int nRightDown = CountNearItem(item,QPoint(1,1)); int nDown = CountNearItem(item,QPoint(0,1)); int nLeftDown = CountNearItem(item,QPoint(-1,1)); if ( (nLeft + nRight) >= 4 || (nLeftUp + nRightDown) >= 4 || (nUp + nDown) >= 4 || (nRightUp + nLeftDown) >= 4 ) { QString str = mBlack? QStringLiteral("黑棋胜利!") : QStringLiteral("白棋胜利!"); QMessageBox::information(NULL, QStringLiteral("游戏结束"),str, QMessageBox::Ok , QMessageBox::Ok); mItems.clear(); //NewGame(); return; } //该另一方下棋了 mBlack = !mBlack; } int MainWindow::CountNearItem(Item item,QPoint ptDirection) { int nCount = 0; item.mPt += ptDirection; while (mItems.contains(item)) { nCount++; item.mPt += ptDirection; } return nCount; }
4,源码
源码可在学习群免费下载! 群号码:1149411109 群名称:Qt实战派学习群
|
|