|
| 1 | +package main |
| 2 | + |
| 3 | +import ( |
| 4 | + "fmt" |
| 5 | + "math/rand" |
| 6 | +) |
| 7 | + |
| 8 | +// MapItem 定义迷宫元素枚举 |
| 9 | +type MapItem int |
| 10 | + |
| 11 | +const ( |
| 12 | + MapWall MapItem = iota |
| 13 | + MapGround |
| 14 | + MapEntrance |
| 15 | + MapExit |
| 16 | + MapOutside |
| 17 | + MapStep |
| 18 | +) |
| 19 | + |
| 20 | +// Point 定义点结构体 |
| 21 | +type Point struct { |
| 22 | + X, Y int |
| 23 | +} |
| 24 | + |
| 25 | +// Size 定义大小结构体 |
| 26 | +type Size struct { |
| 27 | + Width, Height int |
| 28 | +} |
| 29 | + |
| 30 | +// Rect 定义矩形结构体 |
| 31 | +type Rect struct { |
| 32 | + X, Y, Width, Height int |
| 33 | +} |
| 34 | + |
| 35 | +// Maze 迷宫结构 |
| 36 | +type Maze struct { |
| 37 | + Map [][]MapItem // 迷宫地图 |
| 38 | + MapSize Size // 迷宫尺寸 |
| 39 | + PlayerPos Point // 游戏者位置 |
| 40 | +} |
| 41 | + |
| 42 | +// MakeMaze 生成迷宫(注:宽高必须是奇数) |
| 43 | +func (m *Maze) MakeMaze(width, height int) { |
| 44 | + if width%2 != 1 { |
| 45 | + width += 1 |
| 46 | + } |
| 47 | + |
| 48 | + if height%2 != 1 { |
| 49 | + height += 1 |
| 50 | + } |
| 51 | + |
| 52 | + // 记录迷宫尺寸 |
| 53 | + m.MapSize = Size{Width: width, Height: height} |
| 54 | + |
| 55 | + // 分配迷宫内存 |
| 56 | + m.Map = make([][]MapItem, width+2) |
| 57 | + for x := 0; x < width+2; x++ { |
| 58 | + m.Map[x] = make([]MapItem, height+2) |
| 59 | + // 初始化为墙 |
| 60 | + for y := 0; y < height+2; y++ { |
| 61 | + m.Map[x][y] = MapWall |
| 62 | + } |
| 63 | + } |
| 64 | + |
| 65 | + // 定义边界 |
| 66 | + for x := 0; x <= width+1; x++ { |
| 67 | + m.Map[x][0] = MapGround |
| 68 | + m.Map[x][height+1] = MapGround |
| 69 | + } |
| 70 | + |
| 71 | + for y := 1; y <= height; y++ { |
| 72 | + m.Map[0][y] = MapGround |
| 73 | + m.Map[width+1][y] = MapGround |
| 74 | + } |
| 75 | + |
| 76 | + // 定义入口和出口 |
| 77 | + m.Map[1][2] = MapEntrance |
| 78 | + m.Map[width][height-1] = MapExit |
| 79 | + |
| 80 | + // 设置玩家初始位置 |
| 81 | + m.PlayerPos = Point{X: 1, Y: 2} |
| 82 | + |
| 83 | + // 从任意点开始遍历生成迷宫 |
| 84 | + x := ((rand.Intn(width-1) & 0xfffe) + 2) |
| 85 | + y := ((rand.Intn(height-1) & 0xfffe) + 2) |
| 86 | + m.TravelMaze(x, y) |
| 87 | + |
| 88 | + // 将边界标记为迷宫外 |
| 89 | + for x := 0; x <= width+1; x++ { |
| 90 | + m.Map[x][0] = MapOutside |
| 91 | + m.Map[x][height+1] = MapOutside |
| 92 | + } |
| 93 | + |
| 94 | + for y := 1; y <= height; y++ { |
| 95 | + m.Map[0][y] = MapOutside |
| 96 | + m.Map[width+1][y] = MapOutside |
| 97 | + } |
| 98 | +} |
| 99 | + |
| 100 | +// TravelMaze 生成迷宫:遍历 (x, y) 四周 |
| 101 | +func (m *Maze) TravelMaze(x, y int) { |
| 102 | + // 定义遍历方向 |
| 103 | + directions := [4][2]int{{0, 1}, {1, 0}, {0, -1}, {-1, 0}} |
| 104 | + |
| 105 | + // 将遍历方向乱序 |
| 106 | + for i := 0; i < 4; i++ { |
| 107 | + n := rand.Intn(4) |
| 108 | + directions[i], directions[n] = directions[n], directions[i] |
| 109 | + } |
| 110 | + |
| 111 | + // 尝试周围四个方向 |
| 112 | + m.Map[x][y] = MapGround |
| 113 | + for i := 0; i < 4; i++ { |
| 114 | + dx, dy := directions[i][0], directions[i][1] |
| 115 | + if m.Map[x+2*dx][y+2*dy] == MapWall { |
| 116 | + m.Map[x+dx][y+dy] = MapGround |
| 117 | + m.TravelMaze(x+dx*2, y+dy*2) // 递归 |
| 118 | + } |
| 119 | + } |
| 120 | +} |
| 121 | + |
| 122 | +// MapRoute 实现迷宫求解,使用深度优先搜索算法 |
| 123 | +func (m *Maze) MapRoute() { |
| 124 | + // 定义方向:上、右、下、左 |
| 125 | + directions := [4][2]int{{-1, 0}, {0, 1}, {1, 0}, {0, -1}} |
| 126 | + |
| 127 | + // 找到入口位置 |
| 128 | + var start Point |
| 129 | + found := false |
| 130 | + for i := 0; i < m.MapSize.Width+2 && !found; i++ { |
| 131 | + for j := 0; j < m.MapSize.Height+2; j++ { |
| 132 | + if m.Map[i][j] == MapEntrance { |
| 133 | + start = Point{X: i, Y: j} |
| 134 | + found = true |
| 135 | + break |
| 136 | + } |
| 137 | + } |
| 138 | + } |
| 139 | + |
| 140 | + if !found { |
| 141 | + fmt.Println("未找到迷宫入口") |
| 142 | + return |
| 143 | + } |
| 144 | + |
| 145 | + // 创建访问标记数组 |
| 146 | + visited := make([][]bool, m.MapSize.Width+2) |
| 147 | + for i := range visited { |
| 148 | + visited[i] = make([]bool, m.MapSize.Height+2) |
| 149 | + } |
| 150 | + |
| 151 | + // 记录路径的栈 |
| 152 | + path := []Point{start} |
| 153 | + visited[start.X][start.Y] = true |
| 154 | + |
| 155 | + // 深度优先搜索函数 |
| 156 | + var dfs func(x, y int) bool |
| 157 | + dfs = func(x, y int) bool { |
| 158 | + // 如果到达出口,返回成功 |
| 159 | + if m.Map[x][y] == MapExit { |
| 160 | + return true |
| 161 | + } |
| 162 | + |
| 163 | + // 尝试四个方向 |
| 164 | + for _, dir := range directions { |
| 165 | + nx, ny := x+dir[0], y+dir[1] |
| 166 | + |
| 167 | + // 检查是否可以移动到(nx, ny) |
| 168 | + if nx >= 0 && nx < m.MapSize.Width+2 && |
| 169 | + ny >= 0 && ny < m.MapSize.Height+2 && |
| 170 | + (m.Map[nx][ny] == MapGround || m.Map[nx][ny] == MapExit) && |
| 171 | + !visited[nx][ny] { |
| 172 | + |
| 173 | + visited[nx][ny] = true |
| 174 | + path = append(path, Point{X: nx, Y: ny}) |
| 175 | + |
| 176 | + // 递归搜索 |
| 177 | + if dfs(nx, ny) { |
| 178 | + return true |
| 179 | + } |
| 180 | + |
| 181 | + // 回溯 |
| 182 | + path = path[:len(path)-1] |
| 183 | + } |
| 184 | + } |
| 185 | + |
| 186 | + return false |
| 187 | + } |
| 188 | + |
| 189 | + // 开始搜索 |
| 190 | + if dfs(start.X, start.Y) { |
| 191 | + // 标记路径 |
| 192 | + for i := 1; i < len(path)-1; i++ { // 跳过入口和出口 |
| 193 | + point := path[i] |
| 194 | + m.Map[point.X][point.Y] = MapStep |
| 195 | + } |
| 196 | + fmt.Println("迷宫路径已找到并标记") |
| 197 | + } else { |
| 198 | + fmt.Println("未找到可行的迷宫路径") |
| 199 | + } |
| 200 | +} |
| 201 | + |
| 202 | +func (m *Maze) PrintMaze() { |
| 203 | + for j := 0; j < m.MapSize.Height+2; j++ { |
| 204 | + for i := 0; i < m.MapSize.Width+2; i++ { |
| 205 | + if m.Map[i][j] == MapWall { |
| 206 | + fmt.Print("\x1b[43m \x1b[0m") |
| 207 | + } else if m.Map[i][j] == MapGround { |
| 208 | + fmt.Print(" ") |
| 209 | + } else if m.Map[i][j] == MapOutside { |
| 210 | + fmt.Print("\x1b[44m \x1b[0m") |
| 211 | + } else if m.Map[i][j] == MapEntrance { |
| 212 | + fmt.Print("\x1b[42m \x1b[0m") |
| 213 | + } else if m.Map[i][j] == MapExit { |
| 214 | + fmt.Print("\x1b[41m \x1b[0m") |
| 215 | + } else if m.Map[i][j] == MapStep { |
| 216 | + fmt.Print("\x1b[45m \x1b[0m") |
| 217 | + } |
| 218 | + } |
| 219 | + fmt.Println() |
| 220 | + } |
| 221 | +} |
0 commit comments