Robots/Go
< Robots
Go
This hasn't been tested on Windows 10 but should work.
Note that this version uses the Z key (rather than the Y key) to move diagonally downwards to the left and the H key (rather than the Z key) to wait for the end. A leave key, L, has also been added in case one wants to end the game immediately. <lang go>package main
import (
"fmt" "github.com/nsf/termbox-go" "log" "math/rand" "time"
)
type coord struct{ x, y int }
const (
width = 62 height = 42 inc = 10
)
var (
board [width * height]rune robotsCount = 0 score = 0 aliveRobots = 0 bold = termbox.AttrBold cursor coord alive bool
)
var colors = [10]termbox.Attribute{
termbox.ColorDefault, termbox.ColorWhite, termbox.ColorBlack | bold, termbox.ColorBlue | bold, termbox.ColorGreen | bold, termbox.ColorCyan | bold, termbox.ColorRed | bold, termbox.ColorMagenta | bold, termbox.ColorYellow | bold, termbox.ColorWhite | bold,
}
func printAt(x, y int, s string, fg, bg termbox.Attribute) {
for _, r := range s { termbox.SetCell(x, y, r, fg, bg) x++ }
}
func clearBoard() {
for y := 0; y < height; y++ { for x := 0; x < width; x++ { board[x+width*y] = 32 if x == 0 || x == width-1 || y == 0 || y == height-1 { board[x+width*y] = '#' } } }
}
func createBoard() {
aliveRobots = robotsCount for x := 0; x < robotsCount; x++ { var a, b int for { a = rand.Intn(width) b = rand.Intn(height) if board[a+width*b] == 32 { break } } board[a+width*b] = '+' } printScore()
}
func displayBoard() {
var fg termbox.Attribute bg := colors[0] for y := 0; y < height; y++ { for x := 0; x < width; x++ { t := board[x+width*y] switch t { case ' ': fg = colors[0] case '#': fg = colors[3] case '+': fg = colors[8] case 'Å', '*': fg = colors[6] case '@': fg = colors[4] } printAt(x, y, string(t), fg, bg) } } termbox.Flush()
}
func teleport() {
board[cursor.x+width*cursor.y] = 32 cursor.x = rand.Intn(width-2) + 1 cursor.y = rand.Intn(height-2) + 1 x := cursor.x + width*cursor.y if board[x] == '*' || board[x] == '+' || board[x] == '~' { alive = false board[x] = 'Å' } else { board[x] = '@' }
}
func printScore() {
fg := colors[4] bg := termbox.ColorGreen s := fmt.Sprintf(" SCORE: %d ", score) printAt(0, height, s, fg, bg) termbox.Flush()
}
func execute(x, y int) {
board[cursor.x+width*cursor.y] = 32 cursor.x += x cursor.y += y board[cursor.x+width*cursor.y] = '@' moveRobots()
}
func waitForEnd() {
for aliveRobots != 0 && alive { moveRobots() displayBoard() time.Sleep(500 * time.Millisecond) }
}
func moveRobots() {
for y := 0; y < height; y++ { for x := 0; x < width; x++ { if board[x+width*y] != '+' { continue } tx, ty := x, y if tx < cursor.x { tx++ } else if tx > cursor.x { tx-- } if ty < cursor.y { ty++ } else if ty > cursor.y { ty-- } if tx != x || ty != y { board[x+width*y] = 32 if board[tx+width*ty] == 32 { board[tx+width*ty] = '~' } else { checkCollision(tx, ty) } } } } for x := 0; x < width*height; x++ { if board[x] == '~' { board[x] = '+' } }
}
func checkCollision(x, y int) {
if cursor.x == x && cursor.y == y { alive = false board[x+width*y] = 'Å' return } x += y * width if board[x] == '*' || board[x] == '+' || board[x] == '~' { if board[x] != '*' { aliveRobots-- score++ } board[x] = '*' aliveRobots-- score++ }
}
func check(err error) {
if err != nil { log.Fatal(err) }
}
func main() {
rand.Seed(time.Now().UnixNano()) err := termbox.Init() check(err) defer termbox.Close()
eventQueue := make(chan termbox.Event) go func() { for { eventQueue <- termbox.PollEvent() } }()
for { termbox.HideCursor() robotsCount = 10 score = 0 alive = true clearBoard() cursor.x = rand.Intn(width-2) + 1 cursor.y = rand.Intn(height-2) + 1 board[cursor.x+width*cursor.y] = '@' createBoard() for { displayBoard() select { case ev := <-eventQueue: if ev.Type == termbox.EventKey { switch ev.Ch { case 'q', 'Q': if cursor.x > 1 && cursor.y > 1 { execute(-1, -1) } case 'w', 'W': if cursor.y > 1 { execute(0, -1) } case 'e', 'E': if cursor.x < width-2 && cursor.y > 1 { execute(1, -1) } case 'a', 'A': if cursor.x > 1 { execute(-1, 0) } case 'd', 'D': if cursor.x < width-2 { execute(1, 0) } case 'z', 'Z': if cursor.x > 1 && cursor.y < height-2 { execute(-1, 1) } case 'x', 'X': if cursor.y < height-2 { execute(0, 1) } case 'c', 'C': if cursor.x < width-2 && cursor.y < height-2 { execute(1, 1) } case 't', 'T': teleport() moveRobots() case 'h', 'H': waitForEnd() case 'l', 'L': // leave key return } } else if ev.Type == termbox.EventResize { termbox.Flush() } } printScore() if aliveRobots == 0 { robotsCount += inc clearBoard() board[cursor.x+width*cursor.y] = '@' createBoard() } if !alive { break } } displayBoard() fg := colors[7] bg := colors[0] printAt(10, 8, "+----------------------------------------+", fg, bg) printAt(10, 9, "| GAME OVER |", fg, bg) printAt(10, 10, "| PLAY AGAIN(Y/N)? |", fg, bg) printAt(10, 11, "+----------------------------------------+", fg, bg) termbox.SetCursor(39, 10) termbox.Flush() select { case ev := <-eventQueue: if ev.Type == termbox.EventKey { if ev.Ch == 'y' || ev.Ch == 'Y' { break } else { return } } } }
}</lang>