mirror of
https://gitee.com/yyz_o/bk_bishe_pi.git
synced 2025-09-07 23:21:26 +00:00
262 lines
6.8 KiB
C++
262 lines
6.8 KiB
C++
#include<iostream>
|
||
#include<string>
|
||
#include<vector>
|
||
#include<cstddef>
|
||
#include"eyebot++.h"
|
||
#include"maze_parameter.h"
|
||
#include"maze_func.h"
|
||
using namespace std;
|
||
|
||
|
||
/*---检查单元格各方向是否已被到访---*/
|
||
bool check_mark()
|
||
{ bool check = false;
|
||
int x, y;
|
||
x = rob_x; //机器人当前x坐标
|
||
y = rob_y; //机器人当前y坐标
|
||
int size_x = mark.size();
|
||
int size_y = mark[0].size();
|
||
|
||
bool N_mark;
|
||
bool W_mark;
|
||
bool S_mark;
|
||
bool E_mark;
|
||
|
||
if (x > 0)
|
||
{
|
||
W_mark = mark[x-1][y];
|
||
}
|
||
else
|
||
{
|
||
W_mark = true;
|
||
}
|
||
|
||
if (y > 0)
|
||
{
|
||
S_mark = mark[x][y-1];
|
||
}
|
||
else
|
||
{
|
||
S_mark = true;
|
||
}
|
||
|
||
if (x < size_x - 1)
|
||
{
|
||
E_mark = mark[x+1][y];
|
||
}
|
||
else
|
||
{
|
||
E_mark = true;
|
||
}
|
||
|
||
if (y < size_y - 1)
|
||
{
|
||
N_mark = mark[x][y+1];
|
||
}
|
||
else
|
||
{
|
||
N_mark = true;
|
||
}
|
||
|
||
bool N_road = (!wall[x][y+1][0] && N_mark);
|
||
bool W_road = (!wall[x][y][1] && W_mark);
|
||
bool S_road = (!wall[x][y][0] && S_mark);
|
||
bool E_road = (!wall[x+1][y][1] && E_mark);
|
||
|
||
if (N_road && W_road && S_road && E_road)
|
||
{
|
||
check = true;
|
||
}
|
||
return check;
|
||
}
|
||
|
||
/*---maze_entry函数,用于写入到wall数组中,1:有墙 0:通路---*/
|
||
void maze_entry(int x, int y, int dir, int open)
|
||
{
|
||
int maze_dir = (dir + 4) % 4;
|
||
|
||
switch (maze_dir)
|
||
{
|
||
case 0: //0表示北(上),表示(x,y+1)坐标单元格的下方墙壁信息
|
||
if (y == static_cast<int>(mark[0].size()) - 1 && open) //检测是否超出容器范围,如果超出,则扩大容器:对每一个内层尾插数据
|
||
{
|
||
if (!mark.empty() && !wall.empty()) //插入安全性检测,确保容器非空
|
||
{
|
||
for (size_t i = 0; i < mark.size(); i++)
|
||
{
|
||
mark[i].emplace_back(0);
|
||
}
|
||
for (size_t i = 0; i < wall.size(); i++)
|
||
{
|
||
wall[i].emplace_back(std::vector<int>(2,0));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
cout << "error: mark or wall empty" << endl;
|
||
}
|
||
}
|
||
wall[x][y+1][0] = !open;
|
||
break;
|
||
|
||
case 1: //1表示西(左),表示(x,y)坐标单元格的左侧墙壁信息
|
||
if (x == 0 && open) //检测是否超出容器范围,如果超出,则扩大容器:头插一个内层
|
||
{
|
||
if (!mark.empty() && !wall.empty()) //插入安全性检测,确保容器非空
|
||
{
|
||
//~ std::vector<int> mark_insert(mark[0].size(), 0);
|
||
//~ mark.insert(mark.begin(), mark_insert);
|
||
|
||
//~ std::vector<std::vector<int>> wall_insert(wall[0].size(), std::vector<int>(2,0));
|
||
//~ wall.insert(wall.begin(), wall_insert);
|
||
|
||
mark.emplace(mark.begin(), std::vector<int>(mark[0].size(), 0)); //在mark头部插入一个内层
|
||
wall.emplace(wall.begin(), std::vector<std::vector<int>>(wall[0].size(), std::vector<int>(2, 0))); //在wall头部插入一个内层
|
||
rob_x++;
|
||
rob_x0++;
|
||
}
|
||
else
|
||
{
|
||
cout << "error: mark or wall empty" << endl;
|
||
}
|
||
}
|
||
wall[x][y][1] = !open;
|
||
break;
|
||
|
||
case 2: //2表示南(下),表示(x,y)坐标单元格的下侧墙壁信息
|
||
if (y == 0 && open) //检测是否超出容器范围,如果超出,则扩大容器:对每一个内层头插数据
|
||
{
|
||
if (!mark.empty() && !wall.empty()) //插入安全性检测,确保容器非空
|
||
{
|
||
for (size_t i = 0; i < mark.size(); i++)
|
||
{
|
||
mark[i].emplace(mark[i].begin(), 0);
|
||
}
|
||
for (size_t i = 0; i < wall.size(); i++)
|
||
{
|
||
wall[i].emplace(wall[i].begin(), std::vector<int>(2,0));
|
||
}
|
||
rob_y++;
|
||
rob_y0++;
|
||
}
|
||
else
|
||
{
|
||
cout << "error: mark or wall empty" << endl;
|
||
}
|
||
}
|
||
wall[x][y][0] = !open;
|
||
break;
|
||
|
||
case 3: //3表示东(右),表示(x+1,y)坐标单元格的左侧墙壁信息
|
||
if (x == static_cast<int>(mark.size()) - 1 && open) //检测是否超出容器范围,如果超出,则扩大容器:尾插一个内层
|
||
{
|
||
if (!mark.empty() && !wall.empty()) //插入安全性检测,确保容器非空
|
||
{
|
||
mark.emplace_back(std::vector<int>(mark[0].size(), 0));
|
||
wall.emplace_back(std::vector<std::vector<int>>(wall[0].size(), std::vector<int>(2, 0)));
|
||
}
|
||
else
|
||
{
|
||
cout << "error: mark or wall empty" << endl;
|
||
}
|
||
}
|
||
wall[x+1][y][1] = !open;
|
||
break;
|
||
}
|
||
}
|
||
|
||
/*---检查该方向是否已被标记---*/
|
||
bool unmarked(int x, int y, int dir)
|
||
{
|
||
bool check = false;
|
||
int maze_dir = (dir + 4) % 4;
|
||
switch(maze_dir)
|
||
{
|
||
case 0:
|
||
if (y < (static_cast<int>(mark[0].size()) - 1))
|
||
{
|
||
if (mark[x][y+1] == 0)
|
||
{
|
||
check = true;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 1:
|
||
if (x > 0)
|
||
{
|
||
if (mark[x-1][y] == 0)
|
||
{
|
||
check = true;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 2:
|
||
if (y > 0)
|
||
{
|
||
if (mark[x][y-1] == 0)
|
||
{
|
||
check = true;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 3:
|
||
if (x < (static_cast<int>(mark.size()) - 1))
|
||
{
|
||
if (mark[x+1][y] == 0)
|
||
{
|
||
check = true;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
return check;
|
||
}
|
||
|
||
/*---递归函数---*/
|
||
void explore()
|
||
{
|
||
int F_open,L_open,R_open,old_dir;
|
||
bool check;
|
||
|
||
mark[rob_x][rob_y] = 1; //将当前的单元格设置为已到访
|
||
F_open = PSDGetRaw(1) > DIST_cell; //获取前侧空间状况
|
||
L_open = PSDGetRaw(2) > DIST_cell; //获取左侧空间状况
|
||
R_open = PSDGetRaw(3) > DIST_cell; //获取右侧空间状况
|
||
|
||
maze_entry(rob_x, rob_y, rob_dir, F_open); //写入前方墙壁信息
|
||
maze_entry(rob_x, rob_y, rob_dir + 1, L_open); //写入左侧墙壁信息
|
||
maze_entry(rob_x, rob_y, rob_dir - 1, R_open); //写入右侧墙壁信息
|
||
check = check_mark(); //检查3个方向是否到访
|
||
if (check)
|
||
{
|
||
goto end_explore;
|
||
}
|
||
|
||
old_dir = rob_dir;
|
||
if (F_open && unmarked(rob_x, rob_y, old_dir)) //如果前方有通路且前方单元格未被探索
|
||
{
|
||
go_to(old_dir); //向前移动一格
|
||
explore(); //进行递归,在完成所有可到达单元格的访问前,一直循环在explore中
|
||
go_to(old_dir + 2); //返回到移动前的单元格
|
||
}
|
||
|
||
if (L_open && unmarked(rob_x, rob_y, old_dir + 1)) //如果左侧有通路且前方单元格未被探索
|
||
{
|
||
go_to(old_dir + 1); //向左移动一格
|
||
explore(); //进行递归,在完成所有可到达单元格的访问前,一直循环在explore中
|
||
go_to(old_dir - 1); //返回到移动前的单元格
|
||
}
|
||
|
||
if (R_open && unmarked(rob_x, rob_y, old_dir - 1)) //如果右侧有通路且前方单元格未被探索
|
||
{
|
||
go_to(old_dir - 1); //向右移动一格
|
||
explore(); //进行递归,在完成所有可到达单元格的访问前,一直循环在explore中
|
||
go_to(old_dir + 1); //返回到移动前的单元格
|
||
}
|
||
end_explore: //check_mark函数确认三个方向都被探索的话,直接跳转到此处结束此次循环
|
||
VWWait();
|
||
} //递归结束
|