Task: Maze generation




Go: package main

import (
    "bytes"
    "fmt"
    "math/rand"
    "time"
)   
    
type maze struct { 
    c  []byte   
    h  []byte   
    v  []byte   
    c2 [][]byte 
    h2 [][]byte 
    v2 [][]byte 
}

func newMaze(rows, cols int) *maze {
    c := make([]byte, rows*cols)              
    h := bytes.Repeat([]byte{'-'}, rows*cols) 
    v := bytes.Repeat([]byte{'|'}, rows*cols) 
    c2 := make([][]byte, rows)                
    h2 := make([][]byte, rows)                
    v2 := make([][]byte, rows)                
    for i := range h2 {
        c2[i] = c[i*cols : (i+1)*cols]
        h2[i] = h[i*cols : (i+1)*cols]
        v2[i] = v[i*cols : (i+1)*cols]
    }
    return &maze{c, h, v, c2, h2, v2}
}

func (m *maze) String() string {
    hWall := []byte("+---")
    hOpen := []byte("+   ")
    vWall := []byte("|   ")
    vOpen := []byte("    ")
    rightCorner := []byte("+\n") 
    rightWall := []byte("|\n")
    var b []byte
    
    for r, hw := range m.h2 {
        
        for _, h := range hw { 
            if h == '-' || r == 0 {
                b = append(b, hWall...)
            } else {
                b = append(b, hOpen...)
            }
        }
        b = append(b, rightCorner...)
        
        for c, vw := range m.v2[r] {
            if vw == '|' || c == 0 {
                b = append(b, vWall...)
            } else {
                b = append(b, vOpen...)
            }
            
            if m.c2[r][c] != 0 {
                b[len(b)-2] = m.c2[r][c]
            }
        }
        b = append(b, rightWall...)
    }
    
    for _ = range m.h2[0] {
        b = append(b, hWall...)
    }
    b = append(b, rightCorner...)
    return string(b)
}

func (m *maze) gen() {
    m.g2(rand.Intn(len(m.c2)), rand.Intn(len(m.c2[0])))
}

const (
    up = iota
    dn
    rt
    lf
)

func (m *maze) g2(r, c int) {
    m.c2[r][c] = ' '
    for _, dir := range rand.Perm(4) {
        switch dir {
        case up:
            if r > 0 && m.c2[r-1][c] == 0 {
                m.h2[r][c] = 0
                m.g2(r-1, c)
            }
        case lf:
            if c > 0 && m.c2[r][c-1] == 0 {
                m.v2[r][c] = 0
                m.g2(r, c-1)
            }
        case dn:
            if r < len(m.c2)-1 && m.c2[r+1][c] == 0 {
                m.h2[r+1][c] = 0
                m.g2(r+1, c)
            }
        case rt:
            if c < len(m.c2[0])-1 && m.c2[r][c+1] == 0 {
                m.v2[r][c+1] = 0
                m.g2(r, c+1)
            }
        }
    }
}

func main() {
    rand.Seed(time.Now().UnixNano())
    m := newMaze(4, 6)
    m.gen()
    fmt.Print(m)
}




Python: g_size = 10
background_color = color(80, 80, 220)
runner = color(255, 50, 50)
visited_color = color(220, 240, 240)
done_color = color(100, 160, 250)

def setup():
    global cell, done, visit, run_cell, c_size
    size(600, 600)
    frameRate(20)
    smooth(4)
    strokeCap(ROUND)
    c_size = max(width / g_size, height / g_size)
    cell = [[None] * g_size for _ in range(g_size)]
    
    for i in range(g_size):
        for j in range(g_size):
            cell[i][j] = Cell(i, j)

    for i in range(g_size):
        for j in range(g_size):
            cell[i][j].add_neighbor()

    run_cell = cell[0][0]
    visit, done = [], []
    visit.append(run_cell)


def draw():
    global run_cell
    
    background(background_color)
    
    for i in range(g_size):
        for j in range(g_size):
            cell[i][j].draw_cell()
            cell[i][j].draw_wall()

    if len(visit) < g_size * g_size:
        if run_cell.check_sides():
            chosen = run_cell.pick_neighbor()
            done.append(run_cell)
            run_cell.stacked = True
            if chosen.i - run_cell.i == 1:
                run_cell.wall[1] = False
                chosen.wall[3] = False
            elif chosen.i - run_cell.i == -1:
                run_cell.wall[3] = False
                chosen.wall[1] = False
            elif chosen.j - run_cell.j == 1:
                run_cell.wall[2] = False
                chosen.wall[0] = False
            else:
                run_cell.wall[0] = False
                chosen.wall[2] = False
            run_cell.current = False
            run_cell = chosen
            run_cell.current = True
            run_cell.visited = True
        elif done:
            run_cell.current = False
            run_cell = done.pop()
            run_cell.stacked = False
            run_cell.current = True


class Cell:

    def __init__(self, i, j):
        self.i = i
        self.j = j
        self.wall = [True, True, True, True]
        self.visited = False
        self.stacked = False
        self.current = False

    def pick_neighbor(self):
        from random import choice
        unvisited = [nb for nb in self.neighbor
                          if nb.visited == False]
        return choice(unvisited)

    def add_neighbor(self):
        i, j = self.i, self.j
        neighbor = []
        if i > 0:
            neighbor.append(cell[i - 1][j])
        if i < g_size - 1:
            neighbor.append(cell[i + 1][j])
        if j > 0:
            neighbor.append(cell[i][j - 1])
        if j < g_size - 1:
            neighbor.append(cell[i][j + 1])
        self.neighbor = neighbor

    def check_sides(self):
        for nb in self.neighbor:
            if not nb.visited:
                return True
        return False

    def draw_cell(self):
        s = c_size
        noStroke()
        noFill()
        if self.current:
            fill(runner)
        elif self.stacked:
            fill(done_color)
        elif self.visited:
            fill(visited_color)
        rect(self.j * s, self.i * s, s, s)

    def draw_wall(self):
        i, j = self.i, self.j
        wall = self.wall
        stroke(0)
        strokeWeight(5)
        if wall[0]: line(j * c_size, i * c_size, j * c_size, (i + 1) * c_size)
        if wall[1]: line(j * c_size, (i + 1) * c_size, (j + 1) * c_size, (i + 1) * c_size)
        if wall[2]: line((j + 1) * c_size, (i + 1) * c_size, (j + 1) * c_size, i * c_size)
        if wall[3]: line((j + 1) * c_size, i * c_size, j * c_size, i * c_size)