package main import "math" // A Positioned is something that has a position in a 2-D space type Positioned interface { Position() (int, int) } // A Hex is a location in a 2-D hexagonal grid type Hex struct { row, col int } // Position returns the coordinates of a Hex in a 2-D hex grid func (h *Hex) Position() (int, int) { return h.row, h.col } // Cartesian returns the (x,y) coordinates of the center of Hex in // a 2-D hex grid when the grid is drawn in Cartesian space func (h *Hex) Cartesian() (float64, float64) { // convert to float x := float64(h.col) // odd rows have columns offset by 1/2 a hex from if h.row%2 == 1 { x = x + 0.5 } // centerline of rows are spaced by sqrt(3)/2 high y := float64(h.row) * math.Sqrt(3) / 2.0 return x, y } // Distance returns the distance between the centers of two Hex spaces // in a hexagonal grid when embedded in Cartesian space func (h *Hex) Distance(h2 Hex) float64 { x1, y1 := h.Cartesian() x2, y2 := h2.Cartesian() return math.Sqrt(math.Pow(x1-x2, 2) + math.Pow(y1-y2, 2)) } // Adjacent determines if the receiver and parameter are adjacent in // a hexagonal grid func (h *Hex) Adjacent(h2 Hex) bool { dist := h.Distance(h2) return dist > 0.0 && dist < 1.1 } // Closer modifies the receiver to be one hex grid space closer to the // parameter. If the two Hexes are equal then there is no change. func (h *Hex) Closer(h2 Hex) { min := h.Distance(h2) closest := h for dr := -1; dr <= 1; dr++ { for dc := -1; dc <= 1; dc++ { cand := Hex{h.row + dr, h.col + dc} if cand.Adjacent(*h) && h2.Distance(cand) < min { min = h2.Distance(cand) closest = &cand } } } h.row = closest.row h.col = closest.col } // Copy makes the receiver Hex have the same coordinates as the parameter Hex. func (h *Hex) Copy(h2 Hex) { h.row = h2.row h.col = h2.col }