QT利用深度优先或者广度优先填充地图

随机生成一张表格图,每个小格子只有两个值0或者1,随机的选中一个格子,然后与其相邻(上下左右)的具有想同值的格子进行着色,查找周围格子的时候使用的两种算法:深度优先搜索和广度优先搜索。
广度优先搜索示例:
在这里插入图片描述

深度优先搜索示例:
在这里插入图片描述
主界面:

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_FloodFill.h"
#include "IUpdateMap.h"
class Islands;

class FloodFill : public QMainWindow,public IUpdateMap {
	Q_OBJECT

public:
	FloodFill(QWidget *parent = Q_NULLPTR);

	virtual void updateMap()override;
private:
	void init();
	virtual void paintEvent(QPaintEvent *event)override;

	virtual void mousePressEvent(QMouseEvent *event)override;
	virtual void mouseMoveEvent(QMouseEvent *event)override;
	virtual void mouseReleaseEvent(QMouseEvent *event)override;
private:
	Ui::FloodFillClass ui;

	Islands* _isLand = nullptr;
};

#include "FloodFill.h"
#include <QPainter>
#include <QMouseEvent>
#include "Islands.h"

FloodFill::FloodFill(QWidget *parent)
	: QMainWindow(parent) {
	ui.setupUi(this);
	setMouseTracking(true);
	ui.centralWidget->setMouseTracking(true);
	init();
}

void FloodFill::updateMap() {
	update();
}

void FloodFill::init() {
	_isLand = new Islands(20, 20);
	_isLand->setUpdateCallback(this);
}

void FloodFill::paintEvent(QPaintEvent *event) {
	QPainter painter(this);
	_isLand->drawIsLand(&painter);
}

void FloodFill::mousePressEvent(QMouseEvent *event) {

}

void FloodFill::mouseMoveEvent(QMouseEvent *event) {

}

void FloodFill::mouseReleaseEvent(QMouseEvent *event) {
	QPoint pt = event->pos();
	_isLand->selectGrid(pt);
}

查找接口:

#pragma once
class IFind {
public:
	IFind();
	~IFind();

	virtual void find();
};


#include "IFind.h"

IFind::IFind() {
}

IFind::~IFind() {
}

void IFind::find() {

}

地图岛:

#pragma once
#include <vector>
#include <QPoint>
#include "IFind.h"

//岛屿

class QPainter;
class QtFindThread;
class SignalGridItem;
class IUpdateMap;

class Islands:public IFind {
public:
	Islands(int w,int h);
	~Islands();

	void drawIsLand(QPainter* p);

	void selectGrid(QPoint pt);

	void setUpdateCallback(IUpdateMap* updateMap);

	virtual void find()override;
private:
	int getType();

	void findBFS();

	void findDFS(QPoint pt);
private:
	int _width = 0;
	int _height = 0;

	int _sideLength = 20;//边长

	QPoint _selectPos = QPoint(-1, -1);//选中的表格位置
	int _selectValue = -1;//选中的格子的值

	std::vector<std::vector<SignalGridItem*>> _grid ;
	std::vector<std::vector<bool>> _book;

	QtFindThread* _findThread = nullptr;

	IUpdateMap* _updateMap = nullptr;//地图更新接口
};


#include "Islands.h"
#include "SignalGridItem.h"
#include <QTime> 
#include <QPainter> 
#include <queue> 
#include "LandGridItem.h"
#include "SeaGridItem.h"
#include "QtFindThread.h"
#include "IUpdateMap.h"
#include<QThread>
#include<QRandomGenerator>

Islands::Islands(int w, int h) {
	_width = w;
	_height = h;

	SignalGridItem* temp = nullptr;
	for (int i = 0; i < _height; i++) {
		std::vector<SignalGridItem*> oneRow;
		for (int j = 0; j < _width; j++) {
			int type = getType();
			if (type == 0){
				temp = new SeaGridItem();
			} else {
				temp = new LandGridItem();
			}

			temp->setX(i);
			temp->setY(j);
			QRect rect(_sideLength*j, _sideLength*i, _sideLength, _sideLength);
			temp->setRect(rect);
			temp->setValue(type);

			oneRow.push_back(temp);
		}
		_grid.push_back(oneRow);
	}

	_findThread = new QtFindThread(nullptr);
	_findThread->setCallback(this);
}

Islands::~Islands() {
}

void Islands::drawIsLand(QPainter* p) {
	p->setPen(QPen(Qt::red, 2, Qt::SolidLine));

	for (int i = 0; i < _width + 1; i++) {
		p->drawLine(1, i*_sideLength, _height*_sideLength, i*_sideLength);
	}

	for (int j = 0; j < _height + 1; j++) {
		p->drawLine(j*_sideLength, 1, j*_sideLength, _width*_sideLength);
	}

	for (int i = 0; i < _width; i++) {
		for (int j = 0; j < _height; j++) {
			_grid[i][j]->drawGridItem(p);
		}
	}
}

void Islands::selectGrid(QPoint pt) {
	for (int i = 0; i < _height; i++) {
		std::vector<bool> oneLine;
		for (int j = 0; j < _width; j++) {
			oneLine.push_back(false);
		}
		_book.push_back(oneLine);
	}
	
	bool isSelect = false;
	for (int i = 0; i < _height; i++) {
		for (int j = 0; j < _width; j++) {
			if (_grid[i][j]->containtsPt(pt)){
				_grid[i][j]->setGrawBK(true);
				_selectPos = QPoint(i, j);
				_selectValue = _grid[i][j]->getValue();
				isSelect = true;
				_book[i][j] = true;
				break;
			}
		}
		if (isSelect){
			_findThread->start();
			break;
		}
	}
}

void Islands::setUpdateCallback(IUpdateMap* updateMap) {
	_updateMap = updateMap;
}

void Islands::find() {
#if 0//广度优先搜索
	findBFS();
#else//深度优先搜索
	findDFS(_selectPos);
#endif
}

int Islands::getType() {
	int randNum = QRandomGenerator::global()->bounded(10);//生成一个0和10之间的整数
	int n = randNum % 2;    //产生随机数  
	return n;
}

//广度优先搜索
void Islands::findBFS() {
	int next[4][2] = {//按照顺时针方向搜索
		{ 0,1 },//向右
		{ 1,0 },//向下
		{ 0,-1 },//向左
		{ -1,0 }//向上
	};

	std::queue<QPoint> posList;
	posList.push(_selectPos);
	while (posList.size()>0) {
		for (int i =0;i< 4;i++){
			QPoint ptNext = posList.front() + QPoint(next[i][0], next[i][1]);

			//越界判断
			if (ptNext.x() < 0 || ptNext.x() >= _height || ptNext.y() < 0 || ptNext.y() >= _width) {
				continue;
			}
			if (_grid[ptNext.x()][ptNext.y()]->getValue() == _selectValue && !_book[ptNext.x()][ptNext.y()]){
				_grid[ptNext.x()][ptNext.y()]->setGrawBK(true);
				_book[ptNext.x()][ptNext.y()] = true;
				_updateMap->updateMap();
				QThread::msleep(50);
				posList.push(ptNext);
			}
		}
		posList.pop();
	}
}

//深度优先搜索
void Islands::findDFS(QPoint pt) {
	int next[4][2] = {//按照顺时针方向搜索
		{ 0,1 },//向右
		{ 1,0 },//向下
		{ 0,-1 },//向左
		{ -1,0 }//向上
	};

	
	for (int i = 0; i < 4; i++) {
		QPoint ptNext = pt + QPoint(next[i][0], next[i][1]);

		//越界判断
		if (ptNext.x() < 0 || ptNext.x() >= _height || ptNext.y() < 0 || ptNext.y() >= _width) {
			continue;
		}

		//是选中
		if (_grid[ptNext.x()][ptNext.y()]->getValue() == _selectValue && !_book[ptNext.x()][ptNext.y()]) {
			_grid[ptNext.x()][ptNext.y()]->setGrawBK(true);
			_book[ptNext.x()][ptNext.y()] = true;
			_updateMap->updateMap();
			QThread::msleep(50);
			findDFS(ptNext);
		}
	}
}

地图更新接口:

#pragma once
class IUpdateMap {
public:
	IUpdateMap();
	~IUpdateMap();

	virtual void updateMap() = 0;
};


#include "IUpdateMap.h"



IUpdateMap::IUpdateMap() {
}


IUpdateMap::~IUpdateMap() {
}

单个格子

#pragma once
#include <QRect>
#include <QPoint>

//单个格子

class QPainter;

class SignalGridItem {
public:
	SignalGridItem();
	SignalGridItem(int x,int y,int v);
	~SignalGridItem();

	void setX(int x) {
		_x = x;
	}
	int&getX() {
		return _x;
	}

	void setY(int y) {
		_y = y;
	}
	int&getY() {
		return _y;
	}

	void setValue(int v) {
		_value = v;
	}
	int&getValue() {
		return _value;
	}

	void setRect(QRect rect) {
		_rect = rect;
	}

	void setGrawBK(bool b) {
		_isDrawBK = b;
	}

	bool containtsPt(QPoint pt);

	virtual void drawGridItem(QPainter* p);

protected:
	int _x = -1;
	int _y = -1;
	int _value = 0;//0-海洋 1-陆地

	QRect _rect;

	bool _isDrawBK = false;//是否绘制背景
};


#include "SignalGridItem.h"
#include <QPainter>

SignalGridItem::SignalGridItem() {
	_isDrawBK = false;
}

SignalGridItem::SignalGridItem(int x, int y, int v) {
	_x = x;
	_y = y;
	_value = v;
}

SignalGridItem::~SignalGridItem() {
}

bool SignalGridItem::containtsPt(QPoint pt) {
	return _rect.contains(pt);
}


void SignalGridItem::drawGridItem(QPainter* p) {
	p->setPen(QPen(Qt::black));
	QString valueStr = QString::number(_value);
	p->drawText(_rect, Qt::AlignCenter, valueStr);
}

陆地格子

#pragma once
#include "SignalGridItem.h"

//陆地格子

class LandGridItem :public SignalGridItem {
public:
	LandGridItem();
	~LandGridItem();

	virtual void drawGridItem(QPainter* p)override;
};


#include "LandGridItem.h"
#include <QPainter>

LandGridItem::LandGridItem() {
}

LandGridItem::~LandGridItem() {
}

void LandGridItem::drawGridItem(QPainter* p) {
	if (_isDrawBK) {
		p->setBrush(QBrush(Qt::green));
		p->drawRect(_rect);
	}
	SignalGridItem::drawGridItem(p);
}

海洋格子

#pragma once
#include "SignalGridItem.h"

//海洋格子
class QPainter;

class SeaGridItem :public SignalGridItem {
public:
	SeaGridItem();
	~SeaGridItem();

	virtual void drawGridItem(QPainter* p)override;

};


#include "SeaGridItem.h"
#include <QPainter>

SeaGridItem::SeaGridItem() {
}

SeaGridItem::~SeaGridItem() {
}


void SeaGridItem::drawGridItem(QPainter* p) {
	if (_isDrawBK){
		p->setBrush(QBrush(Qt::blue));
		p->drawRect(_rect);
	}
	SignalGridItem::drawGridItem(p);
}

查找线程

#pragma once

#include <QThread>

class IFind;

class QtFindThread : public QThread {
	Q_OBJECT

public:
	QtFindThread(QObject *parent);
	~QtFindThread();

	virtual void run()override;
	void setCallback(IFind* find);
private: 
	IFind* _find = nullptr;
};

#include "QtFindThread.h"
#include "IFind.h"

QtFindThread::QtFindThread(QObject *parent)
	: QThread(parent) {
}

QtFindThread::~QtFindThread() {
}

void QtFindThread::run() {
	_find->find();
}

void QtFindThread::setCallback(IFind* find) {
	_find = find;
}

aaa

代码下载

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wb175208

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值