HTMLify

Snake Game in Go lang
Views: 32 | Author: abh
// Snake game

package main

import (
	"fmt"
	"math/rand"
	"time"
	"github.com/eiannone/keyboard"
    "strconv"
)

type Snake struct {
    head [2]int
    body []([2]int)
    direction rune 
    live bool
}

func (snake *Snake) turn(d rune) {
    switch d {
    case 'u':
        switch snake.direction {
        case 'l':
            snake.direction = 'u'
        case 'r':
            snake.direction = 'u'
        }
    case 'l':
        switch snake.direction {
        case 'u':
            snake.direction = 'l'
        case 'd':
            snake.direction = 'l'
        }
    case 'r':
        switch snake.direction {
        case 'u':
            snake.direction = 'r'
        case 'd':
            snake.direction = 'r'
        }
    case 'd':
        switch snake.direction {
        case 'r':
            snake.direction = 'd'
        case 'l':
            snake.direction = 'd'
        }
    }
}

func (snake *Snake) update() {
    old_pos := [...]int{snake.head[0], snake.head[1]}
    
    switch snake.direction {
    case 'u':
        snake.head[0] -= 1
    case 'l':
        snake.head[1] -= 1
    case 'd':
        snake.head[0] += 1
    case 'r':
        snake.head[1] += 1
    }

    for i,_ := range snake.body {
        snake.body[i][0], old_pos[0] = old_pos[0], snake.body[i][0]
        snake.body[i][1], old_pos[1] = old_pos[1], snake.body[i][1]
    }

    if snake.head[0] == food_i && snake.head[1] == food_j {
        snake.body = append(snake.body, old_pos)
    }

    if snake.head[0] == 0 || snake.head[1] == 0 || snake.head[0] == board_h - 1 || snake.head[1] == board_w - 1 {
        snake.die()
    }
}

func (snake *Snake) die() {
    snake.live = false
}

func (snake Snake) draw(board [][]rune) {
    // clearnig board
    for i:=0;i<board_h;i++ {
        for j:=0;j<board_w;j++ {
            if board[i][j] == '%' {
                continue
            }
            if i == 0 || j == 0 || i == board_h - 1 || j == board_w - 1 {
                board[i][j] = '#'
            } else {
                board[i][j] = ' '
            }
        }
    }

    // snake head
    board[snake.head[0]][snake.head[1]] = '@'
    
    // snake body
    for _, b := range snake.body {
        board[b[0]][b[1]] = '*'
    }
}

func print_board(board [][]rune) {
    for _, l := range board {
        for _, c := range l {
            fmt.Printf("%c", c)
        }
        fmt.Printf("\n")
    }
}

func add_food(board [][]rune) {
    food_i = rand.Intn(board_h-1)+1
    food_j = rand.Intn(board_w-1)+1
    if board[food_i][food_j] == ' ' {
        board[food_i][food_j] = '%'
    } else {
        add_food(board)
    }
}

func food_eaten(board [][]rune) bool {
    return board[food_i][food_j] != '%'
}

func input_loop(snake *Snake) {
    err := keyboard.Open()
	if err != nil {
		fmt.Println("Let me guess, windows?")
        fmt.Println("Sorry but I only test it on Linux")
		snake.die()
	}
	defer keyboard.Close()
    for ;snake.live; {
        _, key, err := keyboard.GetKey()
        if err != nil {
            continue
        }
        defer keyboard.Close() // reset the terminal settings
        // still don't know why it messed up
        switch key {
        case keyboard.KeyArrowUp:
            snake.turn('u')
        case keyboard.KeyArrowDown:
            snake.turn('d')
        case keyboard.KeyArrowLeft:
            snake.turn('l')
        case keyboard.KeyArrowRight:
            snake.turn('r')
        case keyboard.KeyEsc:
            snake.die()
        }
        time.Sleep(10 * time.Millisecond)
    }
}

// Constants

const es_clear = "\033[H\033[2J"
const es_BG_white = "\033[47m"
const es_reset = "\033[0m"
const board_w = 80
const board_h = 24

// Globals

var food_i int = rand.Intn(board_h-1)+1
var food_j int = rand.Intn(board_w-1)+1
 

func main() {
    board := make([][]rune, board_h)
    for i := range board {
        board[i] = make([]rune, board_w)
    }

    var snake Snake
    snake.head[0] = board_h / 2
    snake.head[1] = board_w / 2
    snake.direction = 'r'
    snake.live = true

    go input_loop(&snake)

    for ;snake.live; {
        snake.update()
        snake.draw(board)
        if food_eaten(board) {
            add_food(board)
        }
        fmt.Print(es_clear)
        print_board(board)
        time.Sleep(100 * time.Millisecond)
    }

    // end screen
    score := len(snake.body)
    score_string := "| Your Score is " + strconv.Itoa(score) + " |"
    cf := 0

    for ;cf<board_h+board_w-1;cf++ {
        for i:=0;i<board_h;i++ {
            for j:=0;j<board_w;j++ {
                if i + j == cf {
                    board[i][j] = '+'
                }
            }
        }
        fmt.Print(es_clear)
        print_board(board)
        time.Sleep(100 * time.Millisecond)
    }

    i := board_h / 2
    j := (board_w / 2) - (len(score_string) / 2)

    for index, v := range score_string {
        board[i-1][j+index] = '-'
        board[i][j+index] = v
        board[i+1][j+index] = '-'
    }

    fmt.Print(es_clear)
    print_board(board)

}

Comments