package main import ( "bufio" "fmt" "log" "math/rand" "os" "strconv" "time" ) func main() { rand.Seed(time.Now().UnixNano()) printWelcome() h, w := getDimensions() m := NewMaze(h, w) m.draw() } type direction int64 const ( LEFT direction = iota UP RIGHT DOWN ) const ( EXIT_DOWN = 1 EXIT_RIGHT = 2 ) type maze struct { width int length int used [][]int walls [][]int enterCol int } func NewMaze(w, l int) maze { if (w < 2) || (l < 2) { log.Fatal("invalid dimensions supplied") } m := maze{width: w, length: l} m.used = make([][]int, l) for i := range m.used { m.used[i] = make([]int, w) } m.walls = make([][]int, l) for i := range m.walls { m.walls[i] = make([]int, w) } // randomly determine the entry column m.enterCol = rand.Intn(w) // determine layout of walls m.build() // add an exit col := rand.Intn(m.width - 1) row := m.length - 1 m.walls[row][col] = m.walls[row][col] + 1 return m } func (m *maze) build() { row := 0 col := 0 count := 2 for { possibleDirs := m.getPossibleDirections(row, col) if len(possibleDirs) != 0 { row, col, count = m.makeOpening(possibleDirs, row, col, count) } else { for { if col != m.width-1 { col = col + 1 } else if row != m.length-1 { row = row + 1 col = 0 } else { row = 0 col = 0 } if m.used[row][col] != 0 { break } } } if count == (m.width*m.length)+1 { break } } } func (m *maze) getPossibleDirections(row, col int) []direction { possible_dirs := make(map[direction]bool, 4) possible_dirs[LEFT] = true possible_dirs[UP] = true possible_dirs[RIGHT] = true possible_dirs[DOWN] = true if (col == 0) || (m.used[row][col-1] != 0) { possible_dirs[LEFT] = false } if (row == 0) || (m.used[row-1][col] != 0) { possible_dirs[UP] = false } if (col == m.width-1) || (m.used[row][col+1] != 0) { possible_dirs[RIGHT] = false } if (row == m.length-1) || (m.used[row+1][col] != 0) { possible_dirs[DOWN] = false } ret := make([]direction, 0) for d, v := range possible_dirs { if v { ret = append(ret, d) } } return ret } func (m *maze) makeOpening(dirs []direction, row, col, count int) (int, int, int) { dir := rand.Intn(len(dirs)) if dirs[dir] == LEFT { col = col - 1 m.walls[row][col] = int(EXIT_RIGHT) } else if dirs[dir] == UP { row = row - 1 m.walls[row][col] = int(EXIT_DOWN) } else if dirs[dir] == RIGHT { m.walls[row][col] = m.walls[row][col] + EXIT_RIGHT col = col + 1 } else if dirs[dir] == DOWN { m.walls[row][col] = m.walls[row][col] + EXIT_DOWN row = row + 1 } m.used[row][col] = count count = count + 1 return row, col, count } // draw the maze func (m *maze) draw() { for col := 0; col < m.width; col++ { if col == m.enterCol { fmt.Print(". ") } else { fmt.Print(".--") } } fmt.Println(".") for row := 0; row < m.length; row++ { fmt.Print("|") for col := 0; col < m.width; col++ { if m.walls[row][col] < 2 { fmt.Print(" |") } else { fmt.Print(" ") } } fmt.Println() for col := 0; col < m.width; col++ { if (m.walls[row][col] == 0) || (m.walls[row][col] == 2) { fmt.Print(":--") } else { fmt.Print(": ") } } fmt.Println(".") } } func printWelcome() { fmt.Println(" AMAZING PROGRAM") fmt.Print(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") } func getDimensions() (int, int) { scanner := bufio.NewScanner(os.Stdin) fmt.Println("Enter a width ( > 1 ):") scanner.Scan() w, err := strconv.Atoi(scanner.Text()) if err != nil { log.Fatal("invalid dimension") } fmt.Println("Enter a height ( > 1 ):") scanner.Scan() h, err := strconv.Atoi(scanner.Text()) if err != nil { log.Fatal("invalid dimension") } return w, h }