board.go 2.7 KB

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