RosettaCodeData/Task/Maze-generation/Swift/maze-generation.swift

170 lines
4 KiB
Swift
Raw Permalink Normal View History

2016-12-05 23:44:36 +01:00
import Foundation
2017-09-23 10:01:46 +02:00
extension Array {
mutating func shuffle() {
2018-06-22 20:57:24 +00:00
guard count > 1 else { return }
for i in 0..<self.count - 1 {
let j = Int(arc4random_uniform(UInt32(count - i))) + i
guard i != j else { continue }
swap(&self[i], &self[j])
2017-09-23 10:01:46 +02:00
}
2016-12-05 23:44:36 +01:00
}
2017-09-23 10:01:46 +02:00
}
enum Direction:Int {
case north = 1
case south = 2
case east = 4
case west = 8
2016-12-05 23:44:36 +01:00
2017-09-23 10:01:46 +02:00
static var allDirections:[Direction] {
return [Direction.north, Direction.south, Direction.east, Direction.west]
2016-12-05 23:44:36 +01:00
}
var opposite:Direction {
2017-09-23 10:01:46 +02:00
switch self {
case .north:
return .south
case .south:
return .north
case .east:
return .west
case .west:
return .east
2016-12-05 23:44:36 +01:00
}
}
2017-09-23 10:01:46 +02:00
var diff:(Int, Int) {
switch self {
case .north:
return (0, -1)
case .south:
return (0, 1)
case .east:
return (1, 0)
case .west:
return (-1, 0)
}
}
var char:String {
switch self {
case .north:
return "N"
case .south:
return "S"
case .east:
return "E"
case .west:
return "W"
}
2016-12-05 23:44:36 +01:00
}
2017-09-23 10:01:46 +02:00
}
2016-12-05 23:44:36 +01:00
class MazeGenerator {
2017-09-23 10:01:46 +02:00
let x:Int
let y:Int
var maze:[[Int]]
2016-12-05 23:44:36 +01:00
init(_ x:Int, _ y:Int) {
self.x = x
self.y = y
2017-09-23 10:01:46 +02:00
let column = [Int](repeating: 0, count: y)
self.maze = [[Int]](repeating: column, count: x)
2016-12-05 23:44:36 +01:00
generateMaze(0, 0)
}
2017-09-23 10:01:46 +02:00
private func generateMaze(_ cx:Int, _ cy:Int) {
var directions = Direction.allDirections
directions.shuffle()
for direction in directions {
let (dx, dy) = direction.diff
let nx = cx + dx
let ny = cy + dy
if inBounds(nx, ny) && maze[nx][ny] == 0 {
maze[cx][cy] |= direction.rawValue
maze[nx][ny] |= direction.opposite.rawValue
generateMaze(nx, ny)
}
}
}
private func inBounds(_ testX:Int, _ testY:Int) -> Bool {
return inBounds(value:testX, upper:self.x) && inBounds(value:testY, upper:self.y)
}
private func inBounds(value:Int, upper:Int) -> Bool {
return (value >= 0) && (value < upper)
}
2016-12-05 23:44:36 +01:00
func display() {
2017-09-23 10:01:46 +02:00
let cellWidth = 3
for j in 0..<y {
2016-12-05 23:44:36 +01:00
// Draw top edge
2017-09-23 10:01:46 +02:00
var topEdge = ""
for i in 0..<x {
topEdge += "+"
topEdge += String(repeating: (maze[i][j] & Direction.north.rawValue) == 0 ? "-" : " ", count: cellWidth)
2016-12-05 23:44:36 +01:00
}
2017-09-23 10:01:46 +02:00
topEdge += "+"
print(topEdge)
2016-12-05 23:44:36 +01:00
// Draw left edge
2017-09-23 10:01:46 +02:00
var leftEdge = ""
for i in 0..<x {
leftEdge += (maze[i][j] & Direction.west.rawValue) == 0 ? "|" : " "
leftEdge += String(repeating: " ", count: cellWidth)
2016-12-05 23:44:36 +01:00
}
2017-09-23 10:01:46 +02:00
leftEdge += "|"
print(leftEdge)
2016-12-05 23:44:36 +01:00
}
// Draw bottom edge
2017-09-23 10:01:46 +02:00
var bottomEdge = ""
for _ in 0..<x {
bottomEdge += "+"
bottomEdge += String(repeating: "-", count: cellWidth)
2016-12-05 23:44:36 +01:00
}
2017-09-23 10:01:46 +02:00
bottomEdge += "+"
print(bottomEdge)
2016-12-05 23:44:36 +01:00
}
2017-09-23 10:01:46 +02:00
func displayInts() {
for j in 0..<y {
var line = ""
for i in 0..<x {
line += String(maze[i][j]) + "\t"
}
print(line)
2016-12-05 23:44:36 +01:00
}
2017-09-23 10:01:46 +02:00
}
2016-12-05 23:44:36 +01:00
2017-09-23 10:01:46 +02:00
func displayDirections() {
for j in 0..<y {
var line = ""
for i in 0..<x {
line += getDirectionsAsString(maze[i][j]) + "\t"
2016-12-05 23:44:36 +01:00
}
2017-09-23 10:01:46 +02:00
print(line)
2016-12-05 23:44:36 +01:00
}
}
2017-09-23 10:01:46 +02:00
private func getDirectionsAsString(_ value:Int) -> String {
var line = ""
for direction in Direction.allDirections {
if (value & direction.rawValue) != 0 {
line += direction.char
}
}
return line
2016-12-05 23:44:36 +01:00
}
}
2017-09-23 10:01:46 +02:00
let x = 20
2016-12-05 23:44:36 +01:00
let y = 10
let maze = MazeGenerator(x, y)
maze.display()