From c0a9f788ee0b49285ea76d1c1cc139d2c7341d52 Mon Sep 17 00:00:00 2001 From: Wari Wahab Date: Sun, 15 Feb 2015 01:32:59 +0800 Subject: [PATCH 1/6] First bit done, TODO, binary tree alg to connect the cells --- README.md | 7 +++--- cell.go | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ grid.go | 49 +++++++++++++++++++++++++++++++++++++ main.go | 36 +++++++++++++++++++++++++++ 4 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 cell.go create mode 100644 grid.go create mode 100644 main.go diff --git a/README.md b/README.md index b360f98..5752dfd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ -# Mazes +# Mazes Chapter 2 -Based on the book [Mazes for Programmers: Code Your Own Twisty Little Passages](https://pragprog.com/book/jbmaze/mazes-for-programmers) +Chapter 2 is all about building a grid class that contains cells. + +The following code is just a port of the ruby code in the book -All code are in the chapter branches diff --git a/cell.go b/cell.go new file mode 100644 index 0000000..cffd065 --- /dev/null +++ b/cell.go @@ -0,0 +1,73 @@ +package main + +type Cell struct { + row, col int + North, South, East, West *Cell + links map[*Cell]bool +} + +func NewCell(row, col int) *Cell { + c := new(Cell) + c.row, c.col = row, col + c.links = make(map[*Cell]bool) + return c +} + +func (c Cell) Row() int { + return c.row +} + +func (c Cell) Col() int { + return c.col +} + +func (c *Cell) Link(cell *Cell, bidi bool) *Cell { + c.links[cell] = true + + if bidi { + c.Link(c, false) + } + return c +} + +func (c *Cell) Unlink(cell *Cell, bidi bool) *Cell { + delete(c.links, cell) + if bidi { + c.Unlink(c, false) + } + return c +} + +func (c Cell) IsLinked(cell *Cell) bool { + for x := range c.links { + if x == cell { + return true + } + } + return false +} + +func (c Cell) Links() []*Cell { + list := make([]*Cell, 0) + for x := range c.links { + list = append(list, x) + } + return list +} + +func (c Cell) Neighbors() []*Cell { + list := make([]*Cell, 0) + if c.North != nil { + list = append(list, c.North) + } + if c.South != nil { + list = append(list, c.South) + } + if c.East != nil { + list = append(list, c.East) + } + if c.West != nil { + list = append(list, c.West) + } + return list +} diff --git a/grid.go b/grid.go new file mode 100644 index 0000000..42c794d --- /dev/null +++ b/grid.go @@ -0,0 +1,49 @@ +package main + +type Grid struct { + Rows, Cols int + grid [][]*Cell +} + +func NewGrid(rows, cols int) *Grid { + g := new(Grid) + g.Rows, g.Cols = rows, cols + g.prepareGrid() + g.configureCells() + + return g +} + +func (g *Grid) prepareGrid() { + rows := make([][]*Cell, g.Rows) + + for r := range rows { + cols := make([]*Cell, g.Cols) + for c := range cols { + cols[c] = NewCell(r, c) + } + rows[r] = cols + } + g.grid = rows +} + +func (g *Grid) configureCells() { + for r := range g.grid { + for c := range g.grid[r] { + g.grid[r][c].North = g.getCell(r-1, c) + g.grid[r][c].South = g.getCell(r+1, c) + g.grid[r][c].West = g.getCell(r, c-1) + g.grid[r][c].East = g.getCell(r, c+1) + } + } +} + +func (g *Grid) getCell(row, col int) *Cell { + if row < 0 || row >= g.Rows { + return nil + } + if col < 0 || col >= g.Cols { + return nil + } + return g.grid[row][col] +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..e39b2b7 --- /dev/null +++ b/main.go @@ -0,0 +1,36 @@ +// Not done yet, currently, what's below is just test code to see what's going on +package main + +import "fmt" + +func main() { + c := NewCell(0, 0) + d := NewCell(0, 1) + c.Link(d, true) + c.North = d + d.South = c + d.Link(c, false) + + fmt.Println(c) + fmt.Println(d) + fmt.Println(c.Links()) + fmt.Println(c.Neighbors()) + fmt.Println(d.Neighbors()) + fmt.Println(c.IsLinked(d)) + c.Unlink(d, true) + fmt.Println(c) + fmt.Println(d) + fmt.Println(c.Links()) + fmt.Println(c.Neighbors()) + fmt.Println(d.Neighbors()) + fmt.Println(c.IsLinked(d)) + + g := NewGrid(10, 10) + fmt.Println(g.grid) + + fmt.Println(g.grid[4][5]) + fmt.Println(g.grid[4][5].North) + fmt.Println(g.grid[4][5].South) + fmt.Println(g.grid[4][5].East) + fmt.Println(g.grid[4][5].West) +} From 79d1ccaeb75f3284b80bf3c142b685a4d80d72cd Mon Sep 17 00:00:00 2001 From: Wari Wahab Date: Mon, 16 Feb 2015 00:18:21 +0800 Subject: [PATCH 2/6] Iterators for rows/cells --- grid.go | 40 ++++++++++++++++++++++++++++++++++++++++ main.go | 6 ++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/grid.go b/grid.go index 42c794d..0dcdf5d 100644 --- a/grid.go +++ b/grid.go @@ -1,5 +1,10 @@ package main +import ( + "math/rand" + "time" +) + type Grid struct { Rows, Cols int grid [][]*Cell @@ -47,3 +52,38 @@ func (g *Grid) getCell(row, col int) *Cell { } return g.grid[row][col] } + +func (g *Grid) Size() int { + return g.Rows * g.Cols +} + +func (g *Grid) RandomCell() *Cell { + rand.Seed(time.Now().UnixNano()) + row := rand.Intn(g.Rows) + col := rand.Intn(g.Cols) + return g.grid[row][col] +} + +func (g *Grid) EachRow() chan []*Cell { + c := make(chan []*Cell) + go func() { + for _, r := range g.grid { + c <- r + } + close(c) + }() + return c +} + +func (g *Grid) EachCell() chan *Cell { + c := make(chan *Cell) + go func() { + for r := range g.EachRow() { + for _, i := range r { + c <- i + } + } + close(c) + }() + return c +} diff --git a/main.go b/main.go index e39b2b7..317f2ca 100644 --- a/main.go +++ b/main.go @@ -15,14 +15,12 @@ func main() { fmt.Println(d) fmt.Println(c.Links()) fmt.Println(c.Neighbors()) - fmt.Println(d.Neighbors()) fmt.Println(c.IsLinked(d)) c.Unlink(d, true) fmt.Println(c) fmt.Println(d) fmt.Println(c.Links()) fmt.Println(c.Neighbors()) - fmt.Println(d.Neighbors()) fmt.Println(c.IsLinked(d)) g := NewGrid(10, 10) @@ -33,4 +31,8 @@ func main() { fmt.Println(g.grid[4][5].South) fmt.Println(g.grid[4][5].East) fmt.Println(g.grid[4][5].West) + + for y := range g.EachRow() { + fmt.Println(y) + } } From 0ea9962bb006a27ac59898be308473a4b0cb7414 Mon Sep 17 00:00:00 2001 From: Wari Wahab Date: Mon, 16 Feb 2015 01:29:11 +0800 Subject: [PATCH 3/6] Updated with the btree algorithm One thing to note, in line 6 of the book, we check for north and east, and chose either one to link. Somehow, it does not work on this code, I have to use South and East. Will have to check why I can't follow the code as is given in the book --- README.md | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- btree.go | 29 +++++++++++++++++++++++++++++ grid.go | 39 +++++++++++++++++++++++++++++++++++++++ main.go | 35 ++++------------------------------- 4 files changed, 120 insertions(+), 32 deletions(-) create mode 100644 btree.go diff --git a/README.md b/README.md index 5752dfd..8f0835a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,53 @@ # Mazes Chapter 2 -Chapter 2 is all about building a grid class that contains cells. +Chapter 2 is all about building a grid class that contains cells. We can +populate our maze and print it out. + +Running this produces a random maze with the btree algorithm + +``` ++---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +| | | | | | | | | | ++---+ +---+ +---+ +---+ + +---+---+---+ + +---+---+---+ +---+ + +| | | | | | | | | ++---+ + + + +---+---+---+---+---+---+ + + +---+---+---+---+---+ + +| | | | | | | | | | ++ +---+---+---+---+ +---+ +---+---+---+---+---+ + + + + +---+ + +| | | | | | | | | | | | | | | ++---+ + +---+---+---+ + + + + +---+ + + + + +---+ + + +| | | | | | | | | | | | | | | | | | ++ +---+---+ + + + + + + + + + + + + + +---+ + + +| | | | | | | | | | | | | | ++---+ +---+ + + + +---+ + +---+ + + + +---+---+ +---+ + +| | | | | | | | | | | | | ++ +---+ +---+ +---+ +---+---+ + +---+ + +---+ + + +---+ + +| | | | | | | | | ++ + +---+---+ +---+ +---+---+---+---+ +---+---+ + +---+---+---+ + +| | | | | | | | | | | | | ++ +---+---+ + +---+ + +---+ + +---+ + +---+---+ + +---+ + +| | | | | | | | | | ++ + + + +---+---+ +---+---+---+---+ + +---+---+---+---+ +---+ + +| | | | | | | | | ++ +---+---+---+---+---+ + +---+---+---+---+ +---+---+ +---+ + + + +| | | | | | | | ++---+ +---+---+---+---+ + +---+---+ +---+---+---+---+ +---+---+ + + +| | | | | | | | | | | ++ +---+---+---+ +---+ + +---+---+ + + +---+---+ +---+ +---+ + +| | | | | | | | | | | | ++---+ + + + +---+ + + +---+---+---+---+---+---+ + +---+ + + +| | | | | | | | | | ++---+---+---+ + +---+---+---+---+ + +---+---+ +---+---+ + + + + +| | | | | | | | | | | | | | | ++ + +---+ +---+ +---+ +---+ + + + + + +---+ +---+ + + +| | | | | | | | | | | | ++ + +---+ +---+---+---+ + +---+ +---+---+ + + +---+ +---+ + +| | | | | | | ++---+ +---+---+ + +---+---+---+---+---+---+---+---+---+ + +---+---+ + +| | | | | | | | | | ++---+ +---+---+ + +---+---+---+ + +---+ +---+---+---+ +---+ + + +| | ++---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +``` The following code is just a port of the ruby code in the book diff --git a/btree.go b/btree.go new file mode 100644 index 0000000..2181ded --- /dev/null +++ b/btree.go @@ -0,0 +1,29 @@ +package main + +import ( + "math/rand" + "time" +) + +type BinaryTree struct{} + +func (b *BinaryTree) On(g *Grid) { + rand.Seed(time.Now().UnixNano()) + for c := range g.EachCell() { + neighbors := make([]*Cell, 0) + if c.South != nil { + neighbors = append(neighbors, c.South) + } + if c.East != nil { + neighbors = append(neighbors, c.East) + } + l := len(neighbors) + if l != 0 { + i := rand.Intn(len(neighbors)) + neighbor := neighbors[i] + if neighbor != nil { + c.Link(neighbor, true) + } + } + } +} diff --git a/grid.go b/grid.go index 0dcdf5d..6641d14 100644 --- a/grid.go +++ b/grid.go @@ -87,3 +87,42 @@ func (g *Grid) EachCell() chan *Cell { }() return c } + +func (g *Grid) String() string { + output := "+" + for i := 0; i < g.Cols; i++ { + output += "---+" + } + output += "\n" + + for r := range g.EachRow() { + top := "|" + bottom := "+" + for _, c := range r { + body := " " + eastBoundary := "" + if c.IsLinked(c.East) { + eastBoundary = " " + } else { + eastBoundary = "|" + } + top += body + top += eastBoundary + + southBoundary := "" + if c.IsLinked(c.South) { + southBoundary = " " + } else { + southBoundary = "---" + } + + corner := "+" + bottom += southBoundary + bottom += corner + } + output += top + "\n" + output += bottom + "\n" + } + + return output +} diff --git a/main.go b/main.go index 317f2ca..e70bb57 100644 --- a/main.go +++ b/main.go @@ -4,35 +4,8 @@ package main import "fmt" func main() { - c := NewCell(0, 0) - d := NewCell(0, 1) - c.Link(d, true) - c.North = d - d.South = c - d.Link(c, false) - - fmt.Println(c) - fmt.Println(d) - fmt.Println(c.Links()) - fmt.Println(c.Neighbors()) - fmt.Println(c.IsLinked(d)) - c.Unlink(d, true) - fmt.Println(c) - fmt.Println(d) - fmt.Println(c.Links()) - fmt.Println(c.Neighbors()) - fmt.Println(c.IsLinked(d)) - - g := NewGrid(10, 10) - fmt.Println(g.grid) - - fmt.Println(g.grid[4][5]) - fmt.Println(g.grid[4][5].North) - fmt.Println(g.grid[4][5].South) - fmt.Println(g.grid[4][5].East) - fmt.Println(g.grid[4][5].West) - - for y := range g.EachRow() { - fmt.Println(y) - } + g := NewGrid(20, 20) + b := new(BinaryTree) + b.On(g) + fmt.Println(g) } From ba2d155c32875a6db604c02e76e9c95eadd1c0c2 Mon Sep 17 00:00:00 2001 From: Wari Wahab Date: Tue, 17 Feb 2015 09:25:24 +0800 Subject: [PATCH 4/6] Fixed a bug that cause mazes to not be linked north wise. * Re-reading the source code from the book got me to spot my own mistake that makes bidirectional links to not join at all * The code now follows the book exactly --- btree.go | 6 +++--- cell.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/btree.go b/btree.go index 2181ded..3ce6f94 100644 --- a/btree.go +++ b/btree.go @@ -11,15 +11,15 @@ func (b *BinaryTree) On(g *Grid) { rand.Seed(time.Now().UnixNano()) for c := range g.EachCell() { neighbors := make([]*Cell, 0) - if c.South != nil { - neighbors = append(neighbors, c.South) + if c.North != nil { + neighbors = append(neighbors, c.North) } if c.East != nil { neighbors = append(neighbors, c.East) } l := len(neighbors) if l != 0 { - i := rand.Intn(len(neighbors)) + i := rand.Intn(l) neighbor := neighbors[i] if neighbor != nil { c.Link(neighbor, true) diff --git a/cell.go b/cell.go index cffd065..99f963e 100644 --- a/cell.go +++ b/cell.go @@ -25,7 +25,7 @@ func (c *Cell) Link(cell *Cell, bidi bool) *Cell { c.links[cell] = true if bidi { - c.Link(c, false) + cell.Link(c, false) } return c } @@ -33,7 +33,7 @@ func (c *Cell) Link(cell *Cell, bidi bool) *Cell { func (c *Cell) Unlink(cell *Cell, bidi bool) *Cell { delete(c.links, cell) if bidi { - c.Unlink(c, false) + cell.Unlink(c, false) } return c } From 0acd9138c12ca6496ff4d72ba1346cc8d07b442c Mon Sep 17 00:00:00 2001 From: Wari Wahab Date: Tue, 17 Feb 2015 10:57:53 +0800 Subject: [PATCH 5/6] Added the sidewinder algorithm from the book --- README.md | 86 +++++++++++++++++++++++++++------------------------ main.go | 8 ++++- sidewinder.go | 44 ++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 42 deletions(-) create mode 100644 sidewinder.go diff --git a/README.md b/README.md index 8f0835a..e660acd 100644 --- a/README.md +++ b/README.md @@ -6,47 +6,51 @@ populate our maze and print it out. Running this produces a random maze with the btree algorithm ``` -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -| | | | | | | | | | -+---+ +---+ +---+ +---+ + +---+---+---+ + +---+---+---+ +---+ + -| | | | | | | | | -+---+ + + + +---+---+---+---+---+---+ + + +---+---+---+---+---+ + -| | | | | | | | | | -+ +---+---+---+---+ +---+ +---+---+---+---+---+ + + + + +---+ + -| | | | | | | | | | | | | | | -+---+ + +---+---+---+ + + + + +---+ + + + + +---+ + + -| | | | | | | | | | | | | | | | | | -+ +---+---+ + + + + + + + + + + + + + +---+ + + -| | | | | | | | | | | | | | -+---+ +---+ + + + +---+ + +---+ + + + +---+---+ +---+ + -| | | | | | | | | | | | | -+ +---+ +---+ +---+ +---+---+ + +---+ + +---+ + + +---+ + -| | | | | | | | | -+ + +---+---+ +---+ +---+---+---+---+ +---+---+ + +---+---+---+ + -| | | | | | | | | | | | | -+ +---+---+ + +---+ + +---+ + +---+ + +---+---+ + +---+ + -| | | | | | | | | | -+ + + + +---+---+ +---+---+---+---+ + +---+---+---+---+ +---+ + -| | | | | | | | | -+ +---+---+---+---+---+ + +---+---+---+---+ +---+---+ +---+ + + + -| | | | | | | | -+---+ +---+---+---+---+ + +---+---+ +---+---+---+---+ +---+---+ + + -| | | | | | | | | | | -+ +---+---+---+ +---+ + +---+---+ + + +---+---+ +---+ +---+ + -| | | | | | | | | | | | -+---+ + + + +---+ + + +---+---+---+---+---+---+ + +---+ + + -| | | | | | | | | | -+---+---+---+ + +---+---+---+---+ + +---+---+ +---+---+ + + + + -| | | | | | | | | | | | | | | -+ + +---+ +---+ +---+ +---+ + + + + + +---+ +---+ + + -| | | | | | | | | | | | -+ + +---+ +---+---+---+ + +---+ +---+---+ + + +---+ +---+ + -| | | | | | | -+---+ +---+---+ + +---+---+---+---+---+---+---+---+---+ + +---+---+ + -| | | | | | | | | | -+---+ +---+---+ + +---+---+---+ + +---+ +---+---+---+ +---+ + + -| | -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +Binary Tree ++---+---+---+---+---+---+---+---+---+---+ +| | ++ + + + + +---+---+---+---+ + +| | | | | | | ++---+ +---+---+ +---+---+ +---+ + +| | | | | ++---+ +---+---+---+---+---+ +---+ + +| | | | ++ + + +---+ +---+---+---+ + + +| | | | | | | ++---+ + +---+ +---+ +---+---+ + +| | | | | | ++---+---+---+---+---+---+---+---+---+ + +| | ++ +---+---+---+ + +---+ +---+ + +| | | | | | ++---+---+---+ + + +---+ + + + +| | | | | | | ++ +---+ +---+---+ + +---+ + + +| | | | | | | ++---+---+---+---+---+---+---+---+---+---+ + +Sidewinder ++---+---+---+---+---+---+---+---+---+---+ +| | ++ + +---+---+ +---+---+ + + + +| | | | | | | ++ + +---+ +---+---+ +---+ + + +| | | | | | | ++ + + +---+ +---+---+---+ + + +| | | | | | | ++ + + + + +---+ +---+---+ + +| | | | | | | | ++ + +---+---+ + +---+ + +---+ +| | | | | | | ++---+ + +---+ + + +---+ + + +| | | | | | | | ++---+ +---+ +---+ + +---+ + + +| | | | | | | ++---+ +---+ +---+ + + + +---+ +| | | | | | | ++ + +---+ + +---+---+ +---+---+ +| | | | | | ++---+---+---+---+---+---+---+---+---+---+ ``` The following code is just a port of the ruby code in the book diff --git a/main.go b/main.go index e70bb57..14beca2 100644 --- a/main.go +++ b/main.go @@ -4,8 +4,14 @@ package main import "fmt" func main() { - g := NewGrid(20, 20) + fmt.Println("Binary Tree") + g := NewGrid(10, 10) b := new(BinaryTree) b.On(g) fmt.Println(g) + fmt.Println("Sidewinder") + g = NewGrid(10, 10) + s := new(Sidewinder) + s.On(g) + fmt.Println(g) } diff --git a/sidewinder.go b/sidewinder.go new file mode 100644 index 0000000..d83c541 --- /dev/null +++ b/sidewinder.go @@ -0,0 +1,44 @@ +package main + +import ( + "math/rand" + "time" +) + +type Sidewinder struct{} + +type cells []*Cell + +func (r cells) sample() *Cell { + l := len(r) + if l == 0 { + return nil + } else { + return r[rand.Intn(l)] + } +} + +func (s *Sidewinder) On(g *Grid) *Grid { + rand.Seed(time.Now().UnixNano()) + for r := range g.EachRow() { + run := make(cells, 0) + for _, c := range r { + run = append(run, c) + + atEasternBoundary := c.East == nil + atNorthernBoundary := c.North == nil + shouldCloseOut := atEasternBoundary || (!atNorthernBoundary && rand.Intn(2) == 0) + + if shouldCloseOut { + member := run.sample() + if member.North != nil { + member.Link(member.North, true) + } + run = nil // Clear out the cells + } else { + c.Link(c.East, true) + } + } + } + return g +} From 3d5c70f31a13df74c36756c3a8a1225a098d998d Mon Sep 17 00:00:00 2001 From: Wari Wahab Date: Tue, 17 Feb 2015 13:18:01 +0800 Subject: [PATCH 6/6] And finally, the imaging routine (phew) --- README.md | 2 ++ imager.go | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 4 +++ test.png | Bin 0 -> 1694 bytes 4 files changed, 86 insertions(+) create mode 100644 imager.go create mode 100644 test.png diff --git a/README.md b/README.md index e660acd..91a1b7d 100644 --- a/README.md +++ b/README.md @@ -53,5 +53,7 @@ Sidewinder +---+---+---+---+---+---+---+---+---+---+ ``` +![Image output](test.png) + The following code is just a port of the ruby code in the book diff --git a/imager.go b/imager.go new file mode 100644 index 0000000..cc3b69d --- /dev/null +++ b/imager.go @@ -0,0 +1,80 @@ +package main + +import ( + "image" + "image/color" + "image/draw" + "image/png" + "log" + "os" + "os/exec" +) + +var ( + white color.Color = color.RGBA{255, 255, 255, 255} + black color.Color = color.RGBA{0, 0, 0, 255} +) + +type Image struct { + size int +} + +func NewImage(size int) *Image { + return &Image{size: size} +} + +func (i *Image) DrawLine(img *image.RGBA, x1, y1, x2, y2 int, c color.Color) { + for i := x1; i < x2; i++ { + img.Set(i, y2, c) + } + for i := y1; i < y2; i++ { + img.Set(x2, i, c) + } +} + +func (i *Image) DrawGrid(g *Grid) *image.RGBA { + width := i.size * g.Cols + height := i.size * g.Rows + background := white + wall := black + + img := image.NewRGBA(image.Rect(0, 0, width+1, height+1)) + draw.Draw(img, img.Bounds(), &image.Uniform{background}, image.ZP, draw.Src) + + for c := range g.EachCell() { + x1 := c.Col() * i.size + y1 := c.Row() * i.size + x2 := (c.Col() + 1) * i.size + y2 := (c.Row() + 1) * i.size + + if c.North == nil { + i.DrawLine(img, x1, y1, x2, y1, wall) + } + if c.West == nil { + i.DrawLine(img, x1, y1, x1, y2, wall) + } + if !c.IsLinked(c.East) { + i.DrawLine(img, x2, y1, x2, y2, wall) + } + if !c.IsLinked(c.South) { + i.DrawLine(img, x1, y2, x2, y2, wall) + } + } + + return img +} + +func (i *Image) Save(filename string, img *image.RGBA) { + w, _ := os.Create(filename) + defer w.Close() + png.Encode(w, img) //Encode writes the Image m to w in PNG format. +} + +func Show(name string) { + command := "xdg-open" + cmd := exec.Command(command, name) + err := cmd.Run() + if err != nil { + log.Fatal(err) + } +} diff --git a/main.go b/main.go index 14beca2..d78595e 100644 --- a/main.go +++ b/main.go @@ -14,4 +14,8 @@ func main() { s := new(Sidewinder) s.On(g) fmt.Println(g) + fmt.Println("Showing image") + i := NewImage(40) + i.Save("test.png", i.DrawGrid(g)) + Show("test.png") } diff --git a/test.png b/test.png new file mode 100644 index 0000000000000000000000000000000000000000..5da2bd253d10dbf219a1deede0478cbcf116a72e GIT binary patch literal 1694 zcmeAS@N?(olHy`uVBq!ia0y~yV4MiT985qFZD&a!$(HKr;uumf=gsv%zE@@f4uLVL z|D($?cQ@4S?a?dlJMul@_|6CW?HFXwe=mMN_n#EQ|Mznq*NX)#igf5qV^p2RIwgay zoRh|;Kjsv_m!0|h--Y!PkJdfAW}R9vKYZ@<^LN7fO|vgtiSxg??Ov$ZKe1iXO!Rji zG)!zR$0u|bpW9oW_2suSySTM!)sbyq>rAqnbJJ(tf0oBV=RiZm)TbKz=X1WZ-><$e z|7(8kYgxlhCpRxTPfeBEUwwYRbC%WldyC6$f}5A0`(hUSUg-UeZw33G-@Gd@Fb)KU$`c>n zec$`e*go&+`FF0i{zZDpeD`O5kvq-@zrSc~TD>sz_nx=rnWqkg4QL_^Za#1M{ocx# z%KNRx2x{*Hqto}B2xamgEybgIr!2$=k}B8_b2YW zxAX6nGu&}+V;b+gwG($Xhwb(LV^i)t0Qm&s#7XH{A1u?ezL;(MwLQ0bU-H>qz;t={ zTf_2im9tkCZ~b6fG;ndt@PL2E_kXes4FCTZyxyX7FVdQ&MBb@0GX