⚠️ Warning: This is a draft ⚠️
This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.
If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.
==Code== {{trans|C++}} {{libheader|termbox-go}} {{works with|Ubuntu 16.04}}
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.
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 } } } } }