C++控制台实现迷宫和迷宫求解
前言
提示:VS2019
提示:以下是本篇文章正文内容
一、头文件介绍
1.向量
#include<vector>
遍历方法
非自定义数据类型
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
void print(int val) {
cout << val << '\t';
}
void test01() {
vector<int> v;
v.push_back(10);//尾部插入
v.push_back(20);
v.push_back(30);
v.push_back(40);
//方法一:
for_each(v.begin(), v.end(), print);
cout << endl;
//方法二:
for (vector<int>::iterator it = v.begin(); it < v.end(); it++) {
cout << *it << '\t';
}
cout << endl;
//方法三:
vector<int>::iterator pbegin = v.begin();
vector<int>::iterator pend = v.end();
while (pbegin != pend) {
cout << *pbegin << '\t';
pbegin++;
}
cout << endl;
}
int main()
{
test01();
return 0;
}
自定义数据类型
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class Person {
public:
int age;
string name;
Person(int age, string name) {
this->age = age;
this->name = name;
}
};
void test01() {
vector<Person> v;
Person p1(10, "a");
Person p2(20, "b");
Person p3(30, "c");
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) {
cout << (*it).name << '\t' << (*it).age << endl;
}
}
void test02() {
vector<Person*> v;
Person p1(10, "a");
Person p2(20, "b");
Person p3(30, "c");
v.push_back(&p1);
v.push_back(&p2);
v.push_back(&p3);
for (vector<Person*>::iterator it = v.begin(); it != v.end(); it++) {
cout << (*it)->name << '\t' << (*it)->age << endl;
}
}
int main() {
//test01();
test02();
return 0;
}
二维向量
#include<iostream>
#include<vector>
using namespace std;
void test01() {
vector<vector<int>> v;
vector<int> v1;
vector<int> v2;
vector<int> v3;
for (int i = 0; i < 4;i++) {
v1.push_back(i);
v2.push_back(i + 4);
v3.push_back(i + 8);
}
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++) {
for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++) {
cout << *vit << '\t';
}
cout << endl;
}
}
int main() {
test01();
return 0;
}
2.algorithm
#include<algorithm>
find
#include<vector>
#include <iostream>
#include<algorithm>
#include<string>
using namespace std;
class Person {
public:
string m_Name;
int m_Age;
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
bool operator==(const Person& p) {
return (this->m_Age == p.m_Age) && (this->m_Name == p.m_Name);
}
};
//自定义数据类型的一元谓词实现
class FindOlder {
public:
bool operator()(const Person& p)
{
return p.m_Age > 10;
}
};
//非自定义数据类型的一元谓词实现
class CountGreater {
public:
bool operator()(int val) {
return val > 5;
}
};
void test01()
{
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
v.push_back(9);
//使用find查找
vector<int>::iterator it = find(v.begin(), v.end(), 5);
if (it == v.end())
{
cout << "没找着" << endl;
}
else
{
cout << "找到了:" << *it << endl;
}
vector<int>::iterator it_ = adjacent_find(v.begin(), v.end());
if (it_ == v.end()) {
cout << "meiyou" << endl;
}
else {
cout << "you" << ":" << *it_ << endl;
}
}
void test02() {
vector<Person> p;
Person p1("张三", 10);
Person p2("李四", 11);
Person p3("二麻子", 12);
Person p4("张三", 10);
p.push_back(p1);
p.push_back(p2);
p.push_back(p3);
p.push_back(p4);
vector<Person>::iterator it_01 = find(p.begin(), p.end(), p1);
if (it_01 == p.end()) {
cout << "没找着" << endl;
}
else {
cout << "找到了:" << it_01->m_Name << ":" << it_01->m_Age << endl;
}
vector<Person>::iterator it_02 = find_if(p.begin(), p.end(), FindOlder());
if (it_02 == p.end()) {
cout << "wu" << endl;
}
else {
cout << "you:" << (*it_02).m_Name << ":" << it_02->m_Age << endl;
}
}
void test03() {
vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
v.push_back(9);
bool b;
b = binary_search(v.begin(), v.end(), 5);
//返回一个布尔类型的数据,只能用于有序数列
if (b) {
cout << "you" << endl;
}
else {
cout << "wu" << endl;
}
int num = count(v.begin(), v.end(), 9);
cout << "v有几个9?" << "有" << num << "个" << endl;
int nums = count_if(v.begin(), v.end(), CountGreater());
cout << "大于5的数有" << nums << "个" << endl;
}
//_Pred:谓词
int main() {
//test01();
//test02();
test03();
return 0;
}
transform
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class MyCompare {
public:
bool operator()(int val1,int val2) {
return val1 > val2;
}
};
class MyTransform {
public:
int operator()(int val) {
return val + 10;
}
};
class MyPrint {
public:
void operator()(int val) {
cout << val << '\t';
}
};
void test01() {
vector<int>v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
vector<int>vTarget;
vTarget.resize(v.size());
//将前两个参数指定的数据,通过最后一个参数指定的规则,复制到从第三个指定的位置开辟的空间
transform(v.begin(), v.end(), vTarget.begin(), MyTransform());
for_each(vTarget.begin(), vTarget.end(), MyPrint());
cout << endl;
}
int main() {
test01();
return 0;
}
交并差
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
void print(int val) {
cout << val << '\t';
}
void test01() {
vector<int> v1;
vector<int> v2;
for (int i = 0; i < 10; i++) {
v1.push_back(i);
v2.push_back(i + 3);
}
vector<int> vTarget1;
vTarget1.resize(min(v1.size(), v2.size()));
cout << "交集:" << endl;
vector<int>::iterator itEnd1 = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget1.begin());
for_each(vTarget1.begin(), itEnd1, print);
cout << endl;
vector<int> vTarget2;
vTarget2.resize(v1.size() + v2.size());
vector<int>::iterator itEnd2 = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget2.begin());
cout << "并集:" << endl;
for_each(vTarget2.begin(),itEnd2, print);
cout << endl;
vector<int> vTarget3;
vTarget3.resize(v1.size());
cout << "v1与v2的差集:" << endl;
vector<int>::iterator itEnd3 = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget3.begin());
for_each(vTarget3.begin(), itEnd3, print);
cout << endl;
vector<int> vTarget4;
vTarget4.resize(v2.size());
cout << "v2与v1的差集:" << endl;
vector<int>::iterator itEnd4 = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), vTarget4.begin());
for_each(vTarget4.begin(), itEnd4, print);
}
int main() {
test01();
return 0;
}
numeric(accumulate、fill)
#include<iostream>
#include<numeric>
#include<vector>
#include<algorithm>
using namespace std;
void print(int val) {
cout << val << '\t';
}
void test01() {
vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
//初始和设为0,包含在numeric中
int sum = accumulate(v.begin(), v.end(), 0);
cout << "sum:" << sum << endl;
v.resize(20);
//使用一个数据,填满vector
fill(find(v.begin(), v.end(), 9), v.end(), 13);
for_each(v.begin(), v.end(), print);
cout << endl;
}
int main() {
test01();
return 0;
}
其他操作(random_shuffle、sort、merge、replace、replace_if、unique、reverse)
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class print {
public:
void operator()(int val) {
cout << val << '\t';
}
};
class Descend {
public:
bool operator()(int val1,int val2) {
return val1 > val2;
}
};
class EnterOne {
public:
bool operator()(int val) {
return val > 98;
}
};
void test01() {
vector<int> v;
for (int i = 10; i > 0; i--) {
v.push_back(i);
}
sort(v.begin(), v.end());
cout << "非降序排列:" << endl;
for_each(v.begin(), v.end(),print());
cout << endl;
cout << "置乱:" << endl;
random_shuffle(v.begin(), v.end());
for_each(v.begin(), v.end(), print());
cout << endl;
cout << "降序排列:" << endl;
sort(v.begin(), v.end(), Descend());
for_each(v.begin(), v.end(), print());
cout << endl;
vector<int> v_;
for (int i = 5; i < 10; i++) {
v_.push_back(i);
}
sort(v.begin(), v.end());
vector<int>vTarget;
vTarget.resize(v.size() + v_.size());
merge(v.begin(), v.end(), v_.begin(), v_.end(), vTarget.begin());
//_OutIt _Dest:输出目标,merge第五个参数位置
cout << "合并后的vTarget:" << endl;
for_each(vTarget.begin(), vTarget.end(), print());
cout << endl;
sort(v.begin(), v.end(), Descend());
sort(v_.begin(), v_.end(), Descend());
merge(v.begin(), v.end(), v_.begin(), v_.end(), vTarget.begin(), Descend());
cout << "降序排列:" << endl;
for_each(vTarget.begin(), vTarget.end(), print());
cout << endl;
cout << "去重:" << endl;
vTarget.erase(unique(vTarget.begin(), vTarget.end()), vTarget.end());
//unique:将重复元素放置数组尾部,并返回重复值的第一个重复值的迭代器
for_each(vTarget.begin(), vTarget.end(), print());
cout << endl;
cout << "反转后:" << endl;
reverse(vTarget.begin(), vTarget.end());
for_each(vTarget.begin(), vTarget.end(), print());
}
void test02() {
vector<int> v;
for (int i = 0; i < 6; i++) {
v.push_back(i);
v.push_back(i);
}
v.push_back(99);
v.push_back(90);
v.push_back(99);
replace(v.begin(), v.end(), 5, 100);
for_each(v.begin(), v.end(), print());
cout << endl;
replace_if(v.begin(), v.end(), EnterOne(), 100);
for_each(v.begin(), v.end(), print());
}
void test03() {
vector<int> v1;
vector<int> v2;
for (int i = 1; i < 10; i++) {
v1.push_back(i);
v2.push_back(i + 100);
}
cout << "交换前:" << endl;
for_each(v1.begin(), v1.end(), print());
cout << endl;
for_each(v2.begin(), v2.end(), print());
cout << endl;
swap(v1, v2);
cout << "交换后:" << endl;
for_each(v1.begin(), v1.end(), print());
cout << endl;
for_each(v2.begin(), v2.end(), print());
}
int main() {
//test01();
//test02();
test03();
return 0;
}
二、动态分配二维数组
#include<iostream>
using namespace std;
int main() {
int** p;
int a, b;
cout << "请输入行列:" << endl;
cin >> a >> b;
//全部填充为零,每一维存储一个一级指针,之后为每一个一级指针对应一个数组
p = new int* [a]{ 0 };
for (int i = 0; i < a; i++) {
p[i] = new int[b]{ 0 };
}
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
cout << p[i][j] << " ";
}
cout << endl;
}
//自己开辟的空间,自己释放
for (int i = 0; i < a; i++){
delete[] p[i];
}
delete[] p;
return 0;
}
或者使用智能指针实现(不需要自己释放)
https://blog.csdn.net/zy19940906/article/details/50470087
三、pair
这样pair<int,int> a
#include <iostream>
using namespace std;
int main()
{
int num;
string name;
//初始化
pair<int, string> a(1, "a");
//拷贝构造
pair<int, string> b(a);
//运算符重载
pair<int, string> c;
c = b;
//通过.firs,.second分别访问第一二个元素
cout << c.first << " " << c.second << endl;
return 0;
}
四、思路
1.迷宫生成:
采用深度优先(DFS)生成迷宫
https://blog.csdn.net/jjwwwww/article/details/82872922
2.迷宫求解:
使用简单的A*算法求解迷宫
https://blog.csdn.net/qq_36949278/article/details/109255204
五、代码实现
myMaze.cpp
#include "Maze.h"
/*
根据深度优先遍历生成迷宫
并求解
*/
int main()
{
bool jixu = true;
int a = 1;
while (jixu) {
switch (a) {
case 1: {
cout << "请输入迷宫的行和列:" << endl;
int row, col;
cin >> row >> col;
Maze maze(row, col);
break;
}
case 0:
jixu = false;
default:
break;
}
}
return 0;
}
Maze.h
#pragma once
#include<iostream>
#include<vector>
#include<stack>
#include<algorithm>
#include<cmath>
using namespace std;
class Maze {
private:
int** map;
vector < pair<int, int >> direction = { {1, 0}, {0, 1}, {-1, 0}, {0, -1} };//控制方向
pair<int, int> size;//迷宫的尺寸
void setStartPoint();//开始的点
bool isInRange(int x, int y);//越界判断
bool dig(int x, int y);//挖!
int dist(pair<int, int>);//计算F和
bool distance(pair<int, int> a,pair<int,int> b);//判断F和大小
void setPoint(int i, int j,int d);
int getPoint(int i, int j);
//冒泡排序
void bubbleSort(int lo, int hi);
bool bubble(int lo, int hi);
//stack<pair<int, int>> path;
vector<pair<int, int>> open;
vector<pair<int, int>> close;
pair<int, int> exit;//迷宫结束的位置
pair<int, int> start;//迷宫开始的位置
enum {
Wall = 0,
Road = 1,
Jam = -1,
Sol = -2
};
public:
Maze(int row, int col);//初始化迷宫
~Maze();
void createMaze();//创建迷宫
void print();//打印迷宫
bool solveMaze();//生成路径
void print_Path();//打印路径
};
Maze.cpp
#include "Maze.h"
Maze::Maze(int row, int col)
{
//行,列必须是奇数
if (row % 2 == 0)
{
row++;
}
if (col % 2 == 0)
{
col++;
}
//初始化size
size.first = row;
size.second = col;
//初始化地图map
map = new int* [size.first]{ 0 };
for (int i = 0; i < size.first; i++) {
map[i] = new int[size.second]{ 0 };
}
//做地图
createMaze();
}
void Maze::createMaze()
{
setStartPoint();
dig(start.first, start.second);
//设置出口
exit = { size.first - 1, size.second};
setPoint(size.first - 1, size.second, 1);
print();
solveMaze();
cout << endl;
print_Path();
}
//设置入口和起始点
void Maze::setStartPoint()
{
//在四周随便选面墙作为起始点
//只在写入map时,认为计数从0开始,所以这里b,c都只能是偶数
srand((unsigned)time(NULL));
int a = rand() % 4 + 1;
int b = rand() % size.first;
int c = rand() % size.second;
if (b < 2) {
b += 2;
}
if (b % 2 == 1) {
b++;
}
if (c < 2){
c += 2;
}
if (c % 2 == 1){
c++;
}
if (a == 1)
{
start.first = 2;
start.second = c;
map[0][c - 1] = Road;//设置入口后面的墙是路,以下相同
}
if (a == 2)
{
start.first = size.first - 1;
start.second = c;
map[size.first - 1][c - 1] = Road;
}
if (a == 3)
{
start.first = b;
start.second = 2;
map[b - 1][0] = Road;
}
if (a == 4)
{
start.first = b;
start.second = size.second - 1;
map[b - 1][size.second - 1] = Road;
}
}
//判断节点是否合法
bool Maze::isInRange(int x, int y)
{
if (x <= 1 || x >= size.first) {
return false;
}
if (y <= 1 || y >= size.second) {
return false;
}
return true;
}
//
bool Maze::dig(int x, int y)
{
setPoint(x, y, 1);
//random_shuffle:STL中的函数,用来对一个元素序列进行重新排序(随机的)
random_shuffle(direction.begin(), direction.end());
for (int i = 0; i < 4; i++) {
int temp_X = x + 2 * direction[i].first;
int temp_Y = y + 2 * direction[i].second;
if (isInRange(temp_X, temp_Y) && (!getPoint(temp_X, temp_Y)))
{
//移动方向后位置合法
setPoint(x + direction[i].first, y + direction[i].second, Road);
//print();
//cout << endl;
if (!dig(temp_X, temp_Y)) {
continue;
}
}
}
//四个方向都没有未标记方块
if (x == start.first && y == start.second)
{
return true;//栈空返回true,完成迷宫生成
}
else
{
return false;//栈非空返回false,返回上一层
}
}
//打印地图
void Maze::print()
{
for (int i = 0; i < size.first; i++) {
for (int j = 0; j < size.second; j++) {
cout << ((map[i][j] > 0) ? " " : "■");
}
cout << endl;
}
cout << endl;
}
//打印路径
void Maze::print_Path()
{
for (int i = 1; i <= size.first; i++) {
for (int j = 1; j <= size.second; j++) {
switch (getPoint(i, j)) {
case Wall:
cout << "■";
break;
case Sol:
cout << "□";
break;
case Jam:
case Road:
default:
cout << " ";
break;
}
}
cout << endl;
}
cout << endl;
}
//计算F和
int Maze::dist(pair<int, int> a)
{
return abs(exit.first - a.first + exit.second - a.second) +
close.size();
}
//采用A*寻找迷宫的解
//计算F和采用升序排列
bool Maze::distance(pair<int, int> a,pair<int, int> b)
{
int val1 = dist(a);
int val2 = dist(b);
return val1 < val2;
}
bool Maze::solveMaze()
{
pair<int, int> temp = start;//用于解迷宫
while(true){
setPoint(temp.first, temp.second, Sol);
close.push_back(temp);
if (abs(exit.first - temp.first + exit.second - temp.second) == 1)
{
break;
}
int current_x, current_y;
current_x = temp.first;
current_y = temp.second;
for (int i = 0; i < 4; i++)
{
//如若节点周围是路,则入open
if (isInRange(current_x + direction[i].first, current_y + direction[i].second)
&& (getPoint(current_x + direction[i].first, current_y + direction[i].second) == Road)
//&&((current_x + direction[i].first != start.first)&&(current_y + direction[i].second != start.second))
)
{
open.push_back({ current_x + direction[i].first, current_y + direction[i].second });
}
}
if (open.empty()) {
break;
}
bubbleSort(0, open.size());
temp = open.back();
open.pop_back();
}
return true;
}
//冒泡排序,选择路径
void Maze::bubbleSort(int lo, int hi)
{
while (!bubble(lo, hi--));
}
bool Maze::bubble(int lo, int hi)
{
bool sorted = true;
while (++lo < hi)
{
if (distance(open[lo - 1], open[lo]))
{
sorted = false;
swap(open[lo - 1], open[lo]);
}
}
return sorted;
}
//设置地图上某个点
void Maze::setPoint(int i, int j, int d)
{
map[i - 1][j - 1] = d;
};
//返回地图上某个点
int Maze::getPoint(int i, int j)
{
return map[i - 1][j - 1];
};
Maze::~Maze() {
//释放地图
for (int i = 0; i < size.first; i++)
{
delete[] map[i];
}
delete[] map;
}
总结
提示:注意pair难以通过STL中自带的sort进行自定义谓词的特殊排序,不要这样做,不如自己重写一个排序方案。