MFC实现红黑砖块
MFC实现红黑砖块
##题目
老题目了,给定w,h长宽的图,上面有颜色不同的瓷砖,黑和红,问从给的起点出发,只能走黑色瓷砖,能走多少块,可视化输出过程
##思路
咋一看搜索水题,但是要用可视化,要用模板类,,,崩溃掉了,又得拾起MFC了,在学会别的可视化之前,先凑活吧
每个点可以连4条边,超过边界的不连,从起点dfs,遍历每一个相邻的点,判断是不是#黑砖块,是就入栈,vis数组更新为true,每次出栈的时候涂色,难点其实不在图算法,而是MFC画图,,,,
###1)图的模板类设计
只用一个class T就行了,没有边权值,基本上都是书上的代码
```
#pragma once
#include
using namespace std;
const int DefaultSize = 1000;
template
struct Edge {
int dest;
Edge*link;
Edge(){}
Edge(int to) :dest(to), link(NULL){}
};
template
struct Vertex {
T data;
Edge*adj;
};
template
class Graph{
public:
Graph(int sz=DefaultSize);
~Graph();
int GetNodeNum() {
return numVertices;
}
bool insertVertex(const T&vertex);
bool insertEdge(int v1, int v2);
int getFirstNeighbor(int v);
int getNextNeighbor(int v, int w);
T getValue(int v);
void clear();
protected:
Vertex*NodeTable;
int numVertices;
int maxVertices;
int numEdge;
};
template
Graph::Graph(int sz) {
maxVertices = sz;
numVertices =numEdge=0;
NodeTable = new Vertex[maxVertices];
if (NodeTable == NULL) {
cerr
Graph::~Graph() {
for (int i(0); i *p = NodeTable[i].adj;
while (p != NULL) {
NodeTable[i].adj = p->link;
delete p;
p = NodeTable[i].adj;
}
}
delete[]NodeTable;
}
template
bool Graph::insertVertex(const T&vertex) {
if (numVertices == maxVertices)return false;
NodeTable[numVertices].data = vertex;
numVertices++;
return true;
}
template
bool Graph::insertEdge(int v1, int v2) {
if (v1 >= 0 && v1 = 0 && v2 *p = NodeTable[v1].adj;
while (p != NULL && p->dest != v2) {
p = p->link;
}
if (p != NULL)return false;
p = new Edge;
p->dest = v2;
p->link = NodeTable[v1].adj;
NodeTable[v1].adj = p;
numEdge++;
}
return 0;
}
template
int Graph::getFirstNeighbor(int v) {
if (v != -1) {
Edge*p = NodeTable[v].adj;
if (p != NULL)return p->dest;
}
return -1;
}
template
int Graph::getNextNeighbor(int v, int w) {
if (v != -1) {
Edge*p = NodeTable[v].adj;
while (p != NULL && p->dest != w) {
p = p->link;
}
if (p != NULL && p->link != NULL)
return p->link->dest;
}
return -1;
}
template
void Graph::clear() {
for (int i(0); i *p = NodeTable[i].adj;
while (p != NULL) {
NodeTable[i].adj = p->link;
delete p;
p = NULL;
p = NodeTable[i].adj;
}
}
numVertices = 0;
numEdge = 0;
}
template
T Graph::getValue(int v) {
if (v == -1)return NULL;
return NodeTable[v].data;
}
```
2)界面设计
好了,最简单的模板类设计已经解决了(括弧笑),接下来我们开始做界面。首先建立一个基于单文档的MFC工程,打开资源视图,在工具条那里加3个按钮进去,然后分别在view类里面添加事件处理程序
3)数据输入
先定义view下的自定义数据
int W, H;
int Spos;
bool is_OK = false;
char feld[30][30];
Graph<char>G;
afx_msg void OnReadGraph();
afx_msg void Onbuild();
void DrawRect(CRect crect, int border, CBrush&brush);
void DrawCircle(CRect rect, int border, CBrush&brush);
afx_msg void Onstart();
数据输入用了自带的资源管理器类,把txt的房间文件读取,需要注意的是,W和H后面都要加空格,这才能从strline中提取单个数字出来
void C走瓷砖View::OnReadGraph()
{
Invalidate();
CString fileName;
CFileDialog dlg(TRUE);
if (IDOK == dlg.DoModal())
fileName = dlg.GetPathName();
if (fileName.IsEmpty())
return;
CStdioFile file;
if (file.Open(fileName, CFile::modeRead))
{
is_OK = true;
CString strLine;
CString str;
file.ReadString(strLine);
AfxExtractSubString(str, strLine, 0, ' ');
W = _ttoi(str);
AfxExtractSubString(str, strLine, 1, ' ');
H = _ttoi(str);
for (int i(0); i < H; i++) {
file.ReadString(strLine);
for (int j(0); j < W; j++) {
feld[i][j] = strLine[j];
}
}
file.Close();
}
// TODO: 在此添加命令处理程序代码
}
4)建图并画图
先定义两个函数,一个画矩形一个画圆,
void C走瓷砖View::DrawRect(CRect rect,int border,CBrush&brush)
{
CClientDC dc(this);
//dc.SetROP2(R2_XORPEN);
CPen pen;
pen.CreatePen(PS_SOLID, border, RGB(128,128, 128));
CPen *ppen = dc.SelectObject(&pen);
dc.Rectangle(rect);
dc.SelectObject(ppen);
CBrush *pbrush;
pbrush = dc.SelectObject(&brush);
dc.Rectangle(rect);
dc.SelectObject(pbrush);
// TODO: 在此处添加实现代码.
}
void C走瓷砖View::DrawCircle(CRect rect, int border, CBrush&brush)
{
CClientDC dc(this);
int width = 50 / max(W, H);
CRect newrect(rect.left + width, rect.top +width, rect.right - width, rect.bottom - width);
CBrush *pbrush;
pbrush = dc.SelectObject(&brush);
dc.Ellipse(newrect);
dc.SelectObject(pbrush);
// TODO: 在此处添加实现代码.
}
传3个参数进去,矩形,边界宽度,填充颜色,先填充颜色,再用pen画框子好看点
接下来是建图的函数
void C走瓷砖View::Onbuild()
{
if (is_OK == false) {
AfxMessageBox(_T("请先读取房间!"));
return;
}
G.clear();
int cut=0;
for (int i(0); i < H; i++) {
for (int j(0); j < W; j++) {
if (feld[i][j] == '@') {
Spos = i * W + j;
}
G.insertVertex(feld[i][j]);
cut++;
}
}
int s1, s2, s3, s4;
for (int i(0); i <H; i++) {
for (int j(0); j < W; j++) {
if (j) {
s1 = i * W + j - 1;
G.insertEdge(i*W + j, s1);
}
if (j < W - 1) {
s2 = i * W + j + 1;
G.insertEdge(i*W + j, s2);
}
s3 = (i -1)* W + j;
G.insertEdge(i*W + j, s3);
s4 = (i +1)* W + j;
G.insertEdge(i*W + j, s4);
}
}
int width = 500 / max(W, H);
CRect rect(200, 200, 200 + width * W, 200 + width * H);
int border = 5;
CBrush brush;
brush.CreateSolidBrush(RGB(255, 255,0));
DrawRect(rect, border, brush);
border = 2;
CBrush redbrush, blackbrush;
redbrush.CreateSolidBrush(RGB(255, 0, 0));
blackbrush.CreateSolidBrush(RGB(0, 0, 0));
for (int i(0); i < H; i++) {
for (int j(0); j < W; j++) {
CRect rect(200+j*width, 200+i*width, 200 + (j+1) * width, 200 + (i+1) * width);
if (feld[i][j] == '*') {
DrawRect(rect, border, redbrush);
}
else DrawRect(rect, border, blackbrush);
if (feld[i][j] == '@') {
CBrush greenbrush;
greenbrush.CreateSolidBrush(RGB(0,255,0));
DrawCircle(rect, border, greenbrush);
}
}
}
// TODO: 在此添加命令处理程序代码
}
用了画图的函数以后改代码也方便了很多
5)DFS走格子动画显示
其实这里也和上面的差不多,用到了栈
void C走瓷砖View::Onstart()
{
if (!is_OK) {
AfxMessageBox(_T("请先读取并绘制图"));
return;
}
int width = 500 / max(W, H);
int cur = Spos;
stack<int>P;
P.push(cur);
bool *vis= new bool[G.GetNodeNum()];
for (int i(0); i < G.GetNodeNum(); i++) {
vis[i] = false;
}
CBrush pinkbrush;
pinkbrush.CreateSolidBrush(RGB(255, 192,203));
int border = 2;
vis[cur] = true;
while (!P.empty()) {
cur = P.top();
P.pop();
CRect rect(200 + cur%W * width, 200 + (cur/W)* width, 200 + ((cur%W) + 1) * width, 200 + (cur / W + 1) * width);
DrawRect(rect, border, pinkbrush);
Sleep(50);
int w = G.getFirstNeighbor(cur);
if (w != -1) {
if (!vis[w] && G.getValue(w) == '#') {
P.push(w);
vis[w] = true;
}
int s = G.getNextNeighbor(cur, w);
while (s != -1) {
if (!vis[s] && G.getValue(s) == '#') {
P.push(s);
vis[s] = true;
}
s = G.getNextNeighbor(cur, s);
}
}
}
// TODO: 在此添加命令处理程序代码
}
6)房间数据哪里来?
当然不能自己手写了,手写大了太累,再写个程序,生成房间瓷砖数据
#include<iostream>
#include<time.h>
using namespace std;
int main() {
int x;
srand(time(0));
while (cin >> x) {
int W = rand() % 20 + 5;
int H = W - rand() % 5;
cout << W << ' ' << H << ' ' << endl;
for (int i(0); i < H; i++) {
for (int j(0); j < W; j++) {
int s = rand() % 2;
if (s == 1)
cout << "*";
else cout << "#";
}
cout << endl;
}
cout << endl;
}
}
只要随便输个数,就能生成一个图,然后选个你喜欢的地方,改成@起点,存在txt里就ok
后记
MFC其实还挺好玩的,(真香)
就是脖子好疼
2018/12/26 23:32:09
MFC实现红黑砖块的更多相关文章
- 数据结构--树(遍历,红黑,B树)
平时接触树还比较少,写一篇博文来积累一下树的相关知识. 很早之前在数据结构里面学的树的遍历. 前序遍历:根节点->左子树->右子树 中序遍历:左子树->根节点->右子树 后序遍 ...
- 蓝绿部署、红黑部署、AB测试、灰度发布、金丝雀发布、滚动发布的概念与区别(转)
出处:https://www.baidu.com/link?url=QjboallwNm_jxcL3fHG57wEakiBfAs_3-TChTGu1eBXstlHEsGBc-NDA7AKTqsiroB ...
- 织梦dedecms红黑配图片模板源码v2.0
dedecms红黑配风格美女图片站是采用dedecms程序搭建的图片网站源码,网站感觉很大气,简约但是不简单,适合做图片网站.网站模板是收集其他网站的模板,感谢原网站提供者.在安装过程中出现问题,现已 ...
- http://www.2cto.com/ 红黑联盟
http://www.2cto.com/ 红黑联盟,一个不错的学习或者开阔眼界的网站,内部由中文书写.比较适合国人.
- [数据结构与算法]RED-BLACK(红黑)树的实现TreeMap源码阅读
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- [转载] RED-BLACK(红黑)树的实现TreeMap源码阅读
转载自http://lxy2330.iteye.com/blog/1664786 由于平衡二叉树与红黑树都是二叉排序树,又红黑树是对平衡二叉树的一种改进实现,所以它的很多思想算法都来源于排序二叉或平衡 ...
- 算法进阶面试题04——平衡二叉搜索树、AVL/红黑/SB树、删除和调整平衡的方法、输出大楼轮廓、累加和等于num的最长数组、滴滴Xor
接着第三课的内容和讲了第四课的部分内容 1.介绍二叉搜索树 在二叉树上,何为一个节点的后继节点? 何为搜索二叉树? 如何实现搜索二叉树的查找?插入?删除? 二叉树的概念上衍生出的. 任何一个节点,左比 ...
- 红黑数之原理分析及C语言实现
目录: 1.红黑树简介(概念,特征,用途) 2.红黑树的C语言实现(树形结构,添加,旋转) 3.部分面试题() 1.红黑树简介 1.1 红黑树概念 红黑树(Red-Black Tree,简称R-B T ...
- 广东省-IT公司红黑榜排名
红榜Top100 Order Company Name Point Change 1 百富计算机技术(深圳)有限公司 94.00 -- 2 中国网通广州分公司 88.00 -- 3 深圳市汇 ...
随机推荐
- kaldi通用底层矩阵运算库——CUDA
cudamatrix/cublas-wrappers.h 该头文件对cuBLAS的接口进行了简单的封装(函数名的简化和部分kaldi函数的封装). 比如 cublasSgemm_v2封装为cublas ...
- java平台学习笔记
java程序从编写源码开始到程序执行一共有三个阶段,编写期,编译期,运行期. 通常,人们都希望自己的程序更快(不仅仅是执行更快,也有编写更快),因此java在不断更新. java源码先通过javac编 ...
- 415 DOM 查找列表框、下拉菜单控件、对表格元素/表单控件进行增删改操作、创建元素并且复制节点与删除、 对表格操作、通用性和标准的事件监听方法(点击后弹窗效果以及去掉效果)
DOM访问列表框.下拉菜单的常用属性: form.length.options.selectedindex.type 使用options[index]返回具体选项所对应的常用属性:defa ...
- Theano.tensor.round函数学习,同时解决输出Elemwise{xxx,no_inplace}.0的问题
1. 出现Elemwise{xxx,no_inplace}.0 这是因为没有定义theano.function所致,参考下面错误示范: y = np.random.normal(size=(2,2 ...
- 关于shell变量的继承总结
结论: 默认,父shell和子shell的变量是隔离的. sh方式运行脚本,会重新开启一个子shell,无法继承父进程的普通变量,能继承父进程export的全局变量. source或者. 方式运行脚本 ...
- Oracle_CDC异步Autolog online redo部署示例
一.CDC简介 Oracle CDC (Change Data Capture)变化数据捕获,是一种数据增量处理技术.CDC特性是在Oracle9i数据库中引入的.CDC能够帮助你识别从上次提取之后发 ...
- ubuntu系统的teamviewer的安装及使用
参考链接: 安装: https://blog.csdn.net/weixin_34613450/article/details/80541799 使用: https://jingyan.baidu.c ...
- R语言︱LDA主题模型——最优主题...
R语言︱LDA主题模型——最优主题...:https://blog.csdn.net/sinat_26917383/article/details/51547298#comments
- 生活英语读写MOOC-Literature Tutor-有声名著阅读推荐
生活英语读写MOOC-Literature Tutor-有声名著阅读推荐 1. Alice's Adventures in Wonderland 爱丽丝漫游奇境记 音频与文本下载地址:链接:http: ...
- router-link 返回上页 和 新窗口打开链接
1.如果使用了Vue-router的话,就可以用 this.$router.go(-1) 实现返回: 2.如果没使用vue-router,就可以用 window.history.go(-1) 实现返回 ...