From 27abcd076bd4af77ab51fcc7701d59cac260f9e9 Mon Sep 17 00:00:00 2001 From: Guillermo Ramos Date: Mon, 5 Apr 2021 10:55:35 +0200 Subject: Improve directory structure --- cmd/gosnake.go | 188 --------------------------------------------------------- go.mod | 2 +- main.go | 188 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 189 insertions(+), 189 deletions(-) delete mode 100644 cmd/gosnake.go create mode 100644 main.go diff --git a/cmd/gosnake.go b/cmd/gosnake.go deleted file mode 100644 index 3d77877..0000000 --- a/cmd/gosnake.go +++ /dev/null @@ -1,188 +0,0 @@ -package main - -import ( - "bytes" - "fmt" - tea "github.com/charmbracelet/bubbletea" - "math/rand" - "os" - "time" -) - -type point struct { - x, y int -} - -type direction int - -const ( - up = iota - right - down - left -) - -func (d direction) toByte() byte { - return []byte{'^', '>', 'v', '<'}[d] -} - -type tickMsg time.Time - -type model struct { - dx, dy int - head point - tail []point - maxLen int - dir, newDir direction - food point - points int -} - -func (m model) toOffset(p point) int { - return p.y*(m.dx+1) + p.x -} - -func (m model) isEmpty(p point) bool { - // Check collision with head - if p == m.head { - return false - } - - // Check collision with borders - if p.x < 0 || p.x >= m.dx || p.y < 0 || p.y >= m.dy { - return false - } - - // Check collision with tail - for _, t := range m.tail { - if p == t { - return false - } - } - - return true -} - -func (m model) randFood() point { - candidate := point{x: rand.Intn(m.dx), y: rand.Intn(m.dy)} - for !m.isEmpty(candidate) { - candidate = point{x: rand.Intn(m.dx), y: rand.Intn(m.dy)} - } - return candidate -} - -func initialModel() model { - m := model{ - dx: 20, - dy: 10, - head: point{1, 1}, - tail: make([]point, 0, 10), - maxLen: 5, - dir: right, - newDir: right, - points: 0, - } - m.food = m.randFood() - return m -} - -func tickCmd(points int) func() tea.Msg { - base := 300 - scaled := base - (10 * points) - return tea.Tick(time.Millisecond*time.Duration(scaled), func(t time.Time) tea.Msg { - return tickMsg(t) - }) -} - -func (m model) Init() tea.Cmd { - return tickCmd(m.points) -} - -func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - var newDir direction - switch msg.String() { - case "ctrl+c": - return m, tea.Quit - case "up", "k": - newDir = up - case "right", "l": - newDir = right - case "down", "j": - newDir = down - case "left", "h": - newDir = left - } - - // Prevent from going in the reverse direction - if (newDir+2)%4 != m.dir { - m.newDir = newDir - } - - case tickMsg: - // Calculate new head position - var newHead point - switch m.newDir { - case up: - newHead = point{m.head.x, m.head.y - 1} - case right: - newHead = point{m.head.x + 1, m.head.y} - case down: - newHead = point{m.head.x, m.head.y + 1} - case left: - newHead = point{m.head.x - 1, m.head.y} - } - m.dir = m.newDir - - if !m.isEmpty(newHead) { - fmt.Println("DEP, siempre saludaba.") - return m, tea.Quit - } - - // Good to go; update head and tail - m.tail = append(m.tail, m.head) - if len(m.tail) >= m.maxLen { - m.tail = m.tail[1:] - } - m.head = newHead - - // Finally, when the snake eats the food: - if m.head == m.food { - m.food = m.randFood() - m.maxLen += 1 - m.points += 1 - } - - return m, tickCmd(m.points) - } - return m, nil -} - -func (m model) View() string { - // Generate board - row := append(bytes.Repeat([]byte{'-'}, m.dx), '\n') - board := bytes.Repeat(row, m.dy) - - // Draw head - board[m.toOffset(m.head)] = m.dir.toByte() - - // Draw tail - for _, p := range m.tail { - board[m.toOffset(p)] = '#' - } - - // Draw food - board[m.toOffset(m.food)] = 'o' - - return fmt.Sprintf("%s\nPoints: %d\n", string(board), m.points) -} - -func main() { - rand.Seed(time.Now().UnixNano()) - p := tea.NewProgram(initialModel()) - if err := p.Start(); err != nil { - fmt.Println(err) - os.Exit(1) - } -} diff --git a/go.mod b/go.mod index 4d575a0..393ebb0 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module git.gramos.me/gosnake.git +module git.gramos.me/gosnake go 1.16 diff --git a/main.go b/main.go new file mode 100644 index 0000000..3d77877 --- /dev/null +++ b/main.go @@ -0,0 +1,188 @@ +package main + +import ( + "bytes" + "fmt" + tea "github.com/charmbracelet/bubbletea" + "math/rand" + "os" + "time" +) + +type point struct { + x, y int +} + +type direction int + +const ( + up = iota + right + down + left +) + +func (d direction) toByte() byte { + return []byte{'^', '>', 'v', '<'}[d] +} + +type tickMsg time.Time + +type model struct { + dx, dy int + head point + tail []point + maxLen int + dir, newDir direction + food point + points int +} + +func (m model) toOffset(p point) int { + return p.y*(m.dx+1) + p.x +} + +func (m model) isEmpty(p point) bool { + // Check collision with head + if p == m.head { + return false + } + + // Check collision with borders + if p.x < 0 || p.x >= m.dx || p.y < 0 || p.y >= m.dy { + return false + } + + // Check collision with tail + for _, t := range m.tail { + if p == t { + return false + } + } + + return true +} + +func (m model) randFood() point { + candidate := point{x: rand.Intn(m.dx), y: rand.Intn(m.dy)} + for !m.isEmpty(candidate) { + candidate = point{x: rand.Intn(m.dx), y: rand.Intn(m.dy)} + } + return candidate +} + +func initialModel() model { + m := model{ + dx: 20, + dy: 10, + head: point{1, 1}, + tail: make([]point, 0, 10), + maxLen: 5, + dir: right, + newDir: right, + points: 0, + } + m.food = m.randFood() + return m +} + +func tickCmd(points int) func() tea.Msg { + base := 300 + scaled := base - (10 * points) + return tea.Tick(time.Millisecond*time.Duration(scaled), func(t time.Time) tea.Msg { + return tickMsg(t) + }) +} + +func (m model) Init() tea.Cmd { + return tickCmd(m.points) +} + +func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case tea.KeyMsg: + var newDir direction + switch msg.String() { + case "ctrl+c": + return m, tea.Quit + case "up", "k": + newDir = up + case "right", "l": + newDir = right + case "down", "j": + newDir = down + case "left", "h": + newDir = left + } + + // Prevent from going in the reverse direction + if (newDir+2)%4 != m.dir { + m.newDir = newDir + } + + case tickMsg: + // Calculate new head position + var newHead point + switch m.newDir { + case up: + newHead = point{m.head.x, m.head.y - 1} + case right: + newHead = point{m.head.x + 1, m.head.y} + case down: + newHead = point{m.head.x, m.head.y + 1} + case left: + newHead = point{m.head.x - 1, m.head.y} + } + m.dir = m.newDir + + if !m.isEmpty(newHead) { + fmt.Println("DEP, siempre saludaba.") + return m, tea.Quit + } + + // Good to go; update head and tail + m.tail = append(m.tail, m.head) + if len(m.tail) >= m.maxLen { + m.tail = m.tail[1:] + } + m.head = newHead + + // Finally, when the snake eats the food: + if m.head == m.food { + m.food = m.randFood() + m.maxLen += 1 + m.points += 1 + } + + return m, tickCmd(m.points) + } + return m, nil +} + +func (m model) View() string { + // Generate board + row := append(bytes.Repeat([]byte{'-'}, m.dx), '\n') + board := bytes.Repeat(row, m.dy) + + // Draw head + board[m.toOffset(m.head)] = m.dir.toByte() + + // Draw tail + for _, p := range m.tail { + board[m.toOffset(p)] = '#' + } + + // Draw food + board[m.toOffset(m.food)] = 'o' + + return fmt.Sprintf("%s\nPoints: %d\n", string(board), m.points) +} + +func main() { + rand.Seed(time.Now().UnixNano()) + p := tea.NewProgram(initialModel()) + if err := p.Start(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} -- cgit v1.2.3