|
这是我的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,效果 window.open('http://www.qtcn.org/bbs/attachment/Mon_2008/44_188170_00fd9df3f596173.gif?132');" style="max-width:700px;max-height:700px;" onload="if(is_ie6&&this.offsetWidth>700)this.width=700;" > 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实战派学习群
|