package board import ( "bytes" "encoding/json" "fmt" "io" "log" "math/rand" ) type Board struct { Cols int `json:"cols"` Rows int `json:"rows"` Tiles []Tile `json:"tiles"` } const maxIceWidth = 26 // Create a new randomly generated board. func New(cols, rows int) *Board { b := &Board{cols, rows, make([]Tile, rows*cols)} for y := 0; y < rows; y++ { for x := 0; x < cols; x++ { b.randomizeTile(x, y) } } return b } // Set the tile in column x and row y to val. func (b Board) Set(x, y int, val Tile) { b.Tiles[y*b.Cols+x] = val } // Get the tile in column x and row y. func (b Board) Get(x, y int) Tile { return b.Tiles[y*b.Cols+x] } func (b Board) String() string { var buffer bytes.Buffer for y := 0; y < b.Rows; y++ { for x := 0; x < b.Cols; x++ { buffer.WriteString(b.Get(x, y).String()) } buffer.WriteString(fmt.Sprintln()) } return buffer.String() } type jsonTile struct { X int `json:"x"` Y int `json:"y"` Type string `json:"type"` Player string `json:"player,omitempty"` } func (b Board) WriteJSON(w io.Writer, startCol, startRow, cols, rows int) { fmt.Fprintf(w, "{x=\"%v\",y=\"%v\",rows=\"%v\",columns=\"%v\",tiles={", startCol, startRow, cols, rows) if startCol > b.Cols { startCol = b.Cols } if startCol < 0 { cols += startCol startCol = 0 } if startRow > b.Rows { startRow = b.Rows } if startRow < 0 { rows += startRow startRow = 0 } log.Printf("startCol: %v", startCol) if startCol+cols > b.Cols { cols = b.Cols - startCol } log.Printf("startRow: %v", startRow) if startRow+rows > b.Cols { rows = b.Cols - startRow } if cols < 0 { cols = 0 } if rows < 0 { rows = 0 } log.Printf("x=%v, y=%v, cols=%v, rows=%v \n", startCol, startRow, cols, rows) for y := startRow; y < startRow+rows; y++ { for x := startCol; x < startCol+cols; x++ { t := &jsonTile{x, y, b.Get(x, y).Name(), ""} bs, _ := json.Marshal(t) w.Write(bs) w.Write([]byte{','}) } } fmt.Fprintf(w, "}}") } func (b Board) randomizeTile(x, y int) { switch { case b.isIglo(x, y): b.Set(x, y, Iglo) case b.isRock(x, y): b.Set(x, y, Rock) case b.isIce(x, y): b.Set(x, y, Ice) default: b.Set(x, y, Water) } } func (b Board) isIglo(x, y int) bool { return x == (b.Cols-1) && y == (b.Rows-1)/2 } func (b Board) isRock(x, y int) bool { return rand.Intn(10) > 7 } func (b Board) isIce(x, y int) bool { leftLimit := (b.Cols - maxIceWidth) / 2 rightLimit := b.Cols/2 + maxIceWidth/2 return x > leftLimit && x < rightLimit && rand.Intn(maxIceWidth) >= abs((b.Cols/2)-x) } func abs(a int) int { if a < 0 { return -a } return a }