A search moves from a cell to its neighbors, so the neighbor list is the graph's edges. Today you enumerate the four orthogonal neighbors in one fixed order, skipping walls and edges, which is the single most important decision for making every path reproducible.
Return a cell's walkable four-directional neighbors in a fixed, deterministic order.
This is where the grid becomes a graph. In graph terms each walkable cell is a
node, and an edge connects two cells you can step between. On a grid the
edges are implicit: a cell’s neighbors are the cells one step North, East, South, or
West, as long as they are walkable. Neighbors is how the search reads those edges.
The order matters more than it looks. When two shortest paths tie, the one a search
returns depends entirely on the order it visited neighbors, so we fix that order
once, here, as North, East, South, West, and never vary it. That single
convention, together with the tie-breaking we add to the priority queue later, is
what makes every path in this project a specific, reproducible answer rather than
“some shortest path.” Walls and off-grid cells simply never make it into the list,
because Walkable already screens them out.
// one fixed order, used by every search from here onvar dir4 = []Coord{{0, -1}, {1, 0}, {0, 1}, {-1, 0}} // N, E, S, Wfunc (g *Grid) Neighbors(c Coord) []Coord {out := []Coord{}for _, d := range dir4 {n := Coord{c.X + d.X, c.Y + d.Y}if g.Walkable(n) { out = append(out, n) }}return out}