clone

fifteen puzzle games for the terminal, with daily puzzles, weekly ladders and xp, built on bubble tea

feat/app-decomposition
puzzletea / games / rippleeffect / grid.go
grid.go 1.7K
1package rippleeffect23import (4 "errors"5 "strconv"6 "strings"7)89var errInvalidGridEncoding = errors.New("invalid ripple effect grid encoding")1011type point struct {12 x int13 y int14}1516type grid [][]int1718func newGrid(width, height int) grid {19 cells := make(grid, height)20 for y := range height {21 cells[y] = make([]int, width)22 }23 return cells24}2526func cloneGrid(src grid) grid {27 if src == nil {28 return nil29 }3031 height := len(src)32 width := 033 if height > 0 {34 width = len(src[0])35 }3637 dst := newGrid(width, height)38 for y := range height {39 copy(dst[y], src[y])40 }41 return dst42}4344func parseGrid(encoded string, width, height int) (grid, error) {45 cells := newGrid(width, height)46 rows := strings.Split(strings.TrimSpace(encoded), "\n")47 for y := range height {48 if y >= len(rows) {49 continue50 }51 fields := strings.Fields(rows[y])52 if len(fields) == 0 {53 fields = splitCompactFields(rows[y])54 }55 if len(fields) != width {56 return nil, errInvalidGridEncoding57 }58 for x := range width {59 if fields[x] == "." {60 continue61 }62 value, err := strconv.Atoi(fields[x])63 if err != nil {64 return nil, errInvalidGridEncoding65 }66 cells[y][x] = value67 }68 }6970 return cells, nil71}7273func encodeGrid(g grid) string {74 rows := make([]string, 0, len(g))75 for _, row := range g {76 fields := make([]string, len(row))77 for x, value := range row {78 if value == 0 {79 fields[x] = "."80 continue81 }82 fields[x] = strconv.Itoa(value)83 }84 rows = append(rows, strings.Join(fields, " "))85 }86 return strings.Join(rows, "\n")87}8889func splitCompactFields(row string) []string {90 fields := make([]string, 0, len(row))91 for _, r := range row {92 fields = append(fields, string(r))93 }94 return fields95}