#include #include #include #include #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(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(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 mark_insert(mark[0].size(), 0); //~ mark.insert(mark.begin(), mark_insert); //~ std::vector> wall_insert(wall[0].size(), std::vector(2,0)); //~ wall.insert(wall.begin(), wall_insert); mark.emplace(mark.begin(), std::vector(mark[0].size(), 0)); //在mark头部插入一个内层 wall.emplace(wall.begin(), std::vector>(wall[0].size(), std::vector(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(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(mark.size()) - 1 && open) //检测是否超出容器范围,如果超出,则扩大容器:尾插一个内层 { if (!mark.empty() && !wall.empty()) //插入安全性检测,确保容器非空 { mark.emplace_back(std::vector(mark[0].size(), 0)); wall.emplace_back(std::vector>(wall[0].size(), std::vector(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(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(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(); } //递归结束