refactore to new project structure

This commit is contained in:
2026-07-19 11:18:16 +02:00
parent 1ff0efb557
commit 9a69d4610c
12 changed files with 108 additions and 81 deletions
+10
View File
@@ -43,6 +43,12 @@ func (n *Notes) Remove(field *Field, cell *Cell, note int, trigger string, marks
} }
} }
func (n *Notes) Get() []int {
copySlice := make([]int, len(n.numbers))
copy(copySlice, n.numbers)
return copySlice
}
// ────────────────────────────────────────────────────────────────────────────── // // ────────────────────────────────────────────────────────────────────────────── //
// CELL STRUCTURE // // CELL STRUCTURE //
// ────────────────────────────────────────────────────────────────────────────── // // ────────────────────────────────────────────────────────────────────────────── //
@@ -98,3 +104,7 @@ func (c *Cell) RemoveNumber(field *Field, trigger string, marks []Mark) {
c.number = 0 c.number = 0
} }
func (c *Cell) GetNumber() int {
return c.number
}
+14 -1
View File
@@ -17,7 +17,7 @@ func (m *Mark) GetColor() color.Color {
} }
// ────────────────────────────────────────────────────────────────────────────── // // ────────────────────────────────────────────────────────────────────────────── //
// CHANGE STRUCTURE // // CHANGE_ACTION TYPE //
// ────────────────────────────────────────────────────────────────────────────── // // ────────────────────────────────────────────────────────────────────────────── //
type ChangeAction int type ChangeAction int
@@ -33,6 +33,19 @@ const (
// CHANGE STRUCTURE // // CHANGE STRUCTURE //
// ────────────────────────────────────────────────────────────────────────────── // // ────────────────────────────────────────────────────────────────────────────── //
type ExternalChange struct {
Cell *Cell
Marks []Mark
Action ChangeAction
Value int
From int
TriggerdBy string //strategy or manuell
}
// ────────────────────────────────────────────────────────────────────────────── //
// CHANGE STRUCTURE //
// ────────────────────────────────────────────────────────────────────────────── //
type Change struct { type Change struct {
Cell *Cell Cell *Cell
marks []Mark marks []Mark
+7 -7
View File
@@ -145,14 +145,14 @@ func (f *Field) ForEachCell(fn func(cell *Cell)) {
// MODIFIER // // MODIFIER //
// ────────────────────────────────────────────────────────────────────────────── // // ────────────────────────────────────────────────────────────────────────────── //
func (f *Field) AddChange(cell *Cell, action ChangeAction, value, from int, trigger string, marks []Mark) { func (f *Field) AddChange(eChange *ExternalChange) {
change := Change{ change := Change{
Cell: cell, Cell: eChange.Cell,
marks: marks, marks: eChange.Marks,
action: action, action: eChange.Action,
value: value, value: eChange.Value,
from: from, from: eChange.From,
triggerdBy: trigger, triggerdBy: eChange.TriggerdBy,
} }
change.do() change.do()
+6 -6
View File
@@ -8,23 +8,23 @@ import (
) )
type Parser interface { type Parser interface {
parse(data []byte) error Parse(data []byte) error
getField(i int) *Field GetField(i int) *Field
getAllFields() []Field GetAllFields() []Field
} }
type parserHelper struct { type parserHelper struct {
fields []Field fields []Field
} }
func (ph *parserHelper) getField(i int) *Field { func (ph *parserHelper) GetField(i int) *Field {
if i < 0 || i >= len(ph.fields) { if i < 0 || i >= len(ph.fields) {
return &Field{} return &Field{}
} }
return &ph.fields[i] return &ph.fields[i]
} }
func (ph *parserHelper) getAllFields() []Field { func (ph *parserHelper) GetAllFields() []Field {
if len(ph.fields) == 0 { if len(ph.fields) == 0 {
return nil return nil
} }
@@ -36,7 +36,7 @@ type PuzzleBank struct {
parserHelper parserHelper
} }
func (pb *PuzzleBank) parse(data []byte) error { func (pb *PuzzleBank) Parse(data []byte) error {
lines := bytes.Split(data, []byte("\n")) lines := bytes.Split(data, []byte("\n"))
for _, line := range lines { for _, line := range lines {
+10 -7
View File
@@ -1,30 +1,33 @@
package logic package logic
import "git.kleiax.de/homepage/libs/sudoku/board" import (
"git.kleiax.de/homepage/board"
"git.kleiax.de/homepage/logic/strategies"
)
// ────────────────────────────────────────────────────────────────────────────── // // ────────────────────────────────────────────────────────────────────────────── //
// SOLVER STRUCTURE // // SOLVER STRUCTURE //
// ────────────────────────────────────────────────────────────────────────────── // // ────────────────────────────────────────────────────────────────────────────── //
type Solver struct { type Solver struct {
strategies []Strategy strategies []strategies.Strategy
conf struct { conf struct {
all bool all bool
repeat bool repeat bool
} }
} }
func (s *Solver) Add(strategy Strategy) { func (s *Solver) Add(strategy strategies.Strategy) {
s.strategies = append(s.strategies, strategy) s.strategies = append(s.strategies, strategy)
} }
func (s *Solver) initStragies(field *board.Field) { func (s *Solver) InitStragies(field *board.Field) {
for _, strategy := range s.strategies { for _, strategy := range s.strategies {
strategy.Init(field) strategy.Init(field)
} }
} }
func (s *Solver) run(i int) bool { func (s *Solver) Run(i int) bool {
//TODO: clean und Fehlerauffangen //TODO: clean und Fehlerauffangen
s.strategies[i].SearchProgressableCells() s.strategies[i].SearchProgressableCells()
numberOfChanges := s.strategies[i].ApplyAll() numberOfChanges := s.strategies[i].ApplyAll()
@@ -34,10 +37,10 @@ func (s *Solver) run(i int) bool {
return true return true
} }
func (s *Solver) search() { func (s *Solver) Search() {
} }
func (s *Solver) getSolutionPath() []board.Change { func (s *Solver) GetSolutionPath() []board.ExternalChange {
return nil return nil
} }
+15 -13
View File
@@ -1,6 +1,6 @@
package strategies package strategies
import "git.kleiax.de/homepage/libs/sudoku/board" import "git.kleiax.de/homepage/board"
// ────────────────────────────────────────────────────────────────────────────── // // ────────────────────────────────────────────────────────────────────────────── //
// LAST_DIGIT STRUCTURE // // LAST_DIGIT STRUCTURE //
@@ -14,18 +14,20 @@ func (ld *LastDigit) SearchProgressableCells() int {
ld.field.ForEachPart(func(part board.Part) { ld.field.ForEachPart(func(part board.Part) {
missingNumbers := part.GetMissingNumbers() missingNumbers := part.GetMissingNumbers()
if len(missingNumbers) == 1 { if len(missingNumbers) == 1 {
// var emptyCell *Cell var emptyCell *board.Cell
// part.forEachCell(func(cell *Cell) { part.ForEachCell(func(cell *board.Cell) {
// if cell.number == 0 { if cell.GetNumber() == 0 {
// emptyCell = cell emptyCell = cell
// } }
// }) })
// change := Change{ change := board.ExternalChange{
// cell: emptyCell, Cell: emptyCell,
// action: ActionSetNumber, Action: board.ActionSetNumber,
// value: missingNumbers[0], Value: missingNumbers[0],
// } From: emptyCell.GetNumber(),
// ld.changes = append(ld.changes, change) TriggerdBy: ld.getName(),
}
ld.changes = append(ld.changes, change)
} }
}) })
//fmt.Printf("LastDigit Changes %d", len(ld.changes)) //fmt.Printf("LastDigit Changes %d", len(ld.changes))
+12 -10
View File
@@ -1,6 +1,6 @@
package strategies package strategies
import "git.kleiax.de/homepage/libs/sudoku/board" import "git.kleiax.de/homepage/board"
// ────────────────────────────────────────────────────────────────────────────── // // ────────────────────────────────────────────────────────────────────────────── //
// NAKED_SINGLE STRUCTURE // // NAKED_SINGLE STRUCTURE //
@@ -13,15 +13,17 @@ type NakedSingle struct {
func (ns *NakedSingle) SearchProgressableCells() int { func (ns *NakedSingle) SearchProgressableCells() int {
ns.field.ForEachPart(func(part board.Part) { ns.field.ForEachPart(func(part board.Part) {
part.ForEachCell(func(cell *board.Cell) { part.ForEachCell(func(cell *board.Cell) {
// candidates := cell.notes.numbers candidates := cell.Notes.Get()
// if len(candidates) == 1 { if len(candidates) == 1 {
// change := Change{ change := board.ExternalChange{
// cell: cell, Cell: cell,
// action: ActionSetNumber, Action: board.ActionSetNumber,
// value: candidates[0], Value: candidates[0],
// } From: cell.GetNumber(),
// ns.changes = append(ns.changes, change) TriggerdBy: ns.getName(),
// } }
ns.changes = append(ns.changes, change)
}
}) })
}) })
return len(ns.changes) return len(ns.changes)
+15 -17
View File
@@ -3,7 +3,7 @@ package strategies
import ( import (
"fmt" "fmt"
"git.kleiax.de/homepage/libs/sudoku/board" "git.kleiax.de/homepage/board"
) )
// ────────────────────────────────────────────────────────────────────────────── // // ────────────────────────────────────────────────────────────────────────────── //
@@ -14,11 +14,18 @@ type Strategy interface {
Init(f *board.Field) Init(f *board.Field)
ApplyAll() int ApplyAll() int
ApplyNext() bool ApplyNext() bool
ApplyOne(n int) bool
Name() string Name() string
SearchProgressableCells() int SearchProgressableCells() int
} }
// ────────────────────────────────────────────────────────────────────────────── //
// VISUALITION INTERFACE //
// ────────────────────────────────────────────────────────────────────────────── //
type StrategyVisualization interface {
pointOut(f *board.Field) []board.Mark
}
// ────────────────────────────────────────────────────────────────────────────── // // ────────────────────────────────────────────────────────────────────────────── //
// BASE STRUCTURE // // BASE STRUCTURE //
// ────────────────────────────────────────────────────────────────────────────── // // ────────────────────────────────────────────────────────────────────────────── //
@@ -26,7 +33,7 @@ type Strategy interface {
type Base struct { type Base struct {
name string name string
field *board.Field field *board.Field
changes []board.Change //eigener Typ muss her changes []board.ExternalChange
} }
func (b *Base) Init(f *board.Field) { func (b *Base) Init(f *board.Field) {
@@ -34,9 +41,9 @@ func (b *Base) Init(f *board.Field) {
} }
func (b *Base) ApplyAll() int { func (b *Base) ApplyAll() int {
// for _, change := range sb.changes { for _, change := range b.changes {
// //change.do() b.field.AddChange(&change)
// } }
return len(b.changes) return len(b.changes)
} }
@@ -44,24 +51,15 @@ func (b *Base) ApplyNext() bool {
if len(b.changes) < 1 { if len(b.changes) < 1 {
return false return false
} }
//sb.changes[0].do() b.field.AddChange(&b.changes[0])
b.changes = b.changes[1:] b.changes = b.changes[1:]
return true return true
} }
func (b *Base) ApplyOne(n int) bool {
if len(b.changes) <= n || n < 0 {
return false
}
//sb.changes[n].do()
b.changes = append(b.changes[:n], b.changes[n+1:]...)
return true
}
func (b *Base) getName() string { func (b *Base) getName() string {
return "Unkown" return "Unkown"
} }
func (b *Base) Name() string { func (b *Base) Name() string {
return fmt.Sprintf("Die Strategie heißt: %s", b.getName()) return fmt.Sprintf("Diese Strategie heißt: %s", b.getName())
} }
+9 -6
View File
@@ -5,14 +5,17 @@ import (
"io" "io"
"os" "os"
"git.kleiax.de/homepage/libs/sudoku" "git.kleiax.de/homepage/board"
"git.kleiax.de/homepage/logic"
"git.kleiax.de/homepage/logic/strategies"
"git.kleiax.de/homepage/sudoku"
) )
func main() { func main() {
solver := sudoku.Solver{} solver := logic.Solver{}
solver.Add(&sudoku.LastDigit{}) solver.Add(&strategies.LastDigit{})
solver.Add(&sudoku.NakedSingle{}) solver.Add(&strategies.NakedSingle{})
game, err := sudoku.New(&sudoku.PuzzleBank{}, solver, openFile()) game, err := sudoku.New(&board.PuzzleBank{}, solver, openFile())
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
os.Exit(1) os.Exit(1)
@@ -31,7 +34,7 @@ func main() {
} }
func openFile() []byte { func openFile() []byte {
file, err := os.Open("libs/sudoku/data/sudoku-exchange-puzzle-bank/easy3.txt") file, err := os.Open("data/sudoku-exchange-puzzle-bank/easy3.txt")
if err != nil { if err != nil {
fmt.Println("Kann datei nicht öffnen") fmt.Println("Kann datei nicht öffnen")
os.Exit(3) os.Exit(3)
+9 -9
View File
@@ -4,8 +4,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"git.kleiax.de/homepage/libs/sudoku/board" "git.kleiax.de/homepage/board"
"git.kleiax.de/homepage/libs/sudoku/logic" "git.kleiax.de/homepage/logic"
) )
type Game struct { type Game struct {
@@ -13,16 +13,16 @@ type Game struct {
solver logic.Solver solver logic.Solver
} }
func New(parser Parser, solver Solver, data []byte) (*Game, error) { func New(parser board.Parser, solver logic.Solver, data []byte) (*Game, error) {
err := parser.parse(data) err := parser.Parse(data)
if err != nil { if err != nil {
return &Game{}, fmt.Errorf("can not create game: %w", err) return &Game{}, fmt.Errorf("can not create game: %w", err)
} }
return &Game{solver: solver, field: parser.getField(0)}, nil return &Game{solver: solver, field: parser.GetField(0)}, nil
} }
func (g *Game) Solve() error { func (g *Game) Solve() error {
g.solver.initStragies(g.field) g.solver.InitStragies(g.field)
for !g.isFinished() { for !g.isFinished() {
if !g.nextSolveStep() { if !g.nextSolveStep() {
return errors.New("no strategy can solve the puzzle") return errors.New("no strategy can solve the puzzle")
@@ -32,7 +32,7 @@ func (g *Game) Solve() error {
} }
func (g *Game) nextSolveStep() bool { func (g *Game) nextSolveStep() bool {
return g.solver.run(0) return g.solver.Run(0)
} }
func (g *Game) prevSolveStep() { func (g *Game) prevSolveStep() {
@@ -40,9 +40,9 @@ func (g *Game) prevSolveStep() {
} }
func (g *Game) isFinished() bool { func (g *Game) isFinished() bool {
return g.field.isSolved() return g.field.IsSolved()
} }
func (g *Game) GetField() Field { func (g *Game) GetField() board.Field {
return *g.field return *g.field
} }
+1
View File
@@ -0,0 +1 @@
- Parser kann eigenes Package sein nur das Interface und die Helfer funktionen im Board lassen, jeder kann einen Parser für sseine Quelle schreiben. Vielleicht ein Standardparser in Board für gängige Typen oder Hilfsfunktionen
-5
View File
@@ -1,5 +0,0 @@
package sudoku
// type StrategyVisualization interface {
// pointOut(f *Field) []Mark
// }