board.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package board
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "math/rand"
  8. "time"
  9. )
  10. type Board struct {
  11. Cols int `json:"cols"`
  12. Rows int `json:"rows"`
  13. Finish Coordinate `json:"finish"`
  14. Tiles []Tile `json:"-"`
  15. }
  16. const maxIceWidth = 26
  17. // Create a new randomly generated board.
  18. func New(cols, rows int) *Board {
  19. r := rand.New(rand.NewSource(time.Now().UnixNano()))
  20. return new(cols, rows, r)
  21. }
  22. func new(cols, rows int, r *rand.Rand) *Board {
  23. b := &Board{
  24. Cols: cols,
  25. Rows: rows,
  26. Tiles: make([]Tile, rows*cols, rows*cols)}
  27. for y := 0; y < rows; y++ {
  28. for x := 0; x < cols; x++ {
  29. switch {
  30. case r.Intn(10) > 7:
  31. b.Set(x, y, Rock)
  32. case x > (b.Cols-maxIceWidth)/2 && x < b.Cols/2+maxIceWidth/2 && r.Intn(maxIceWidth) >= abs((b.Cols/2)-x):
  33. b.Set(x, y, Ice)
  34. default:
  35. b.Set(x, y, Water)
  36. }
  37. }
  38. }
  39. igloY := r.Intn(rows-2) + 1
  40. b.Set(cols-2, igloY, Iglo)
  41. b.Finish.X = cols - 2
  42. b.Finish.Y = igloY
  43. b.Set(cols-2, igloY-1, Water)
  44. b.Set(cols-2, igloY+1, Water)
  45. return b
  46. }
  47. // Set the tile in column x and row y to val.
  48. func (b *Board) Set(x, y int, val Tile) {
  49. b.Tiles[y*b.Cols+x] = val
  50. }
  51. // Get the tile in column x and row y.
  52. func (b *Board) Get(x, y int) Tile {
  53. return b.Tiles[y*b.Cols+x]
  54. }
  55. func (b *Board) String() string {
  56. var buffer bytes.Buffer
  57. for y := 0; y < b.Rows; y++ {
  58. for x := 0; x < b.Cols; x++ {
  59. buffer.WriteString(b.Get(x, y).String())
  60. }
  61. buffer.WriteString(fmt.Sprintln())
  62. }
  63. return buffer.String()
  64. }
  65. func (b *Board) WriteJSON(w io.Writer, startCol, startRow, cols, rows int) {
  66. sc, sr, cols, rows := sanitizeViewPort(b, startCol, startRow, cols, rows)
  67. fmt.Fprintf(w, "{\"x\":%v,\"y\":%v,\"rows\":%v,\"cols\":%v,\"tiles\":[", sc, sr, cols, rows)
  68. for y := startRow; y < sr+rows; y++ {
  69. for x := startCol; x < sc+cols; x++ {
  70. if !(x == startCol && y == startRow) {
  71. w.Write([]byte{','})
  72. }
  73. t := &jsonTile{x, y, b.Get(x, y).Name(), ""}
  74. bs, _ := json.Marshal(t)
  75. w.Write(bs)
  76. }
  77. }
  78. fmt.Fprintf(w, "]}")
  79. }
  80. func sanitizeViewPort(b *Board, startCol, startRow, cols, rows int) (int, int, int, int) {
  81. if startCol > b.Cols {
  82. startCol = b.Cols
  83. }
  84. if startCol < 0 {
  85. cols += startCol
  86. startCol = 0
  87. }
  88. if startRow > b.Rows {
  89. startRow = b.Rows
  90. }
  91. if startRow < 0 {
  92. rows += startRow
  93. startRow = 0
  94. }
  95. if startCol+cols > b.Cols {
  96. cols = b.Cols - startCol
  97. }
  98. if startRow+rows > b.Rows {
  99. rows = b.Rows - startRow
  100. }
  101. if cols < 0 {
  102. cols = 0
  103. }
  104. if rows < 0 {
  105. rows = 0
  106. }
  107. return startCol, startRow, cols, rows
  108. }
  109. func abs(a int) int {
  110. if a < 0 {
  111. return -a
  112. }
  113. return a
  114. }