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 //
// ────────────────────────────────────────────────────────────────────────────── //
@@ -98,3 +104,7 @@ func (c *Cell) RemoveNumber(field *Field, trigger string, marks []Mark) {
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
@@ -33,6 +33,19 @@ const (
// 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 {
Cell *Cell
marks []Mark
+7 -7
View File
@@ -145,14 +145,14 @@ func (f *Field) ForEachCell(fn func(cell *Cell)) {
// MODIFIER //
// ────────────────────────────────────────────────────────────────────────────── //
func (f *Field) AddChange(cell *Cell, action ChangeAction, value, from int, trigger string, marks []Mark) {
func (f *Field) AddChange(eChange *ExternalChange) {
change := Change{
Cell: cell,
marks: marks,
action: action,
value: value,
from: from,
triggerdBy: trigger,
Cell: eChange.Cell,
marks: eChange.Marks,
action: eChange.Action,
value: eChange.Value,
from: eChange.From,
triggerdBy: eChange.TriggerdBy,
}
change.do()
+6 -6
View File
@@ -8,23 +8,23 @@ import (
)
type Parser interface {
parse(data []byte) error
getField(i int) *Field
getAllFields() []Field
Parse(data []byte) error
GetField(i int) *Field
GetAllFields() []Field
}
type parserHelper struct {
fields []Field
}
func (ph *parserHelper) getField(i int) *Field {
func (ph *parserHelper) GetField(i int) *Field {
if i < 0 || i >= len(ph.fields) {
return &Field{}
}
return &ph.fields[i]
}
func (ph *parserHelper) getAllFields() []Field {
func (ph *parserHelper) GetAllFields() []Field {
if len(ph.fields) == 0 {
return nil
}
@@ -36,7 +36,7 @@ type PuzzleBank struct {
parserHelper
}
func (pb *PuzzleBank) parse(data []byte) error {
func (pb *PuzzleBank) Parse(data []byte) error {
lines := bytes.Split(data, []byte("\n"))
for _, line := range lines {
+10 -7
View File
@@ -1,30 +1,33 @@
package logic
import "git.kleiax.de/homepage/libs/sudoku/board"
import (
"git.kleiax.de/homepage/board"
"git.kleiax.de/homepage/logic/strategies"
)
// ────────────────────────────────────────────────────────────────────────────── //
// SOLVER STRUCTURE //
// ────────────────────────────────────────────────────────────────────────────── //
type Solver struct {
strategies []Strategy
strategies []strategies.Strategy
conf struct {
all bool
repeat bool
}
}
func (s *Solver) Add(strategy Strategy) {
func (s *Solver) Add(strategy 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 {
strategy.Init(field)
}
}
func (s *Solver) run(i int) bool {
func (s *Solver) Run(i int) bool {
//TODO: clean und Fehlerauffangen
s.strategies[i].SearchProgressableCells()
numberOfChanges := s.strategies[i].ApplyAll()
@@ -34,10 +37,10 @@ func (s *Solver) run(i int) bool {
return true
}
func (s *Solver) search() {
func (s *Solver) Search() {
}
func (s *Solver) getSolutionPath() []board.Change {
func (s *Solver) GetSolutionPath() []board.ExternalChange {
return nil
}
+15 -13
View File
@@ -1,6 +1,6 @@
package strategies
import "git.kleiax.de/homepage/libs/sudoku/board"
import "git.kleiax.de/homepage/board"
// ────────────────────────────────────────────────────────────────────────────── //
// LAST_DIGIT STRUCTURE //
@@ -14,18 +14,20 @@ func (ld *LastDigit) SearchProgressableCells() int {
ld.field.ForEachPart(func(part board.Part) {
missingNumbers := part.GetMissingNumbers()
if len(missingNumbers) == 1 {
// var emptyCell *Cell
// part.forEachCell(func(cell *Cell) {
// if cell.number == 0 {
// emptyCell = cell
// }
// })
// change := Change{
// cell: emptyCell,
// action: ActionSetNumber,
// value: missingNumbers[0],
// }
// ld.changes = append(ld.changes, change)
var emptyCell *board.Cell
part.ForEachCell(func(cell *board.Cell) {
if cell.GetNumber() == 0 {
emptyCell = cell
}
})
change := board.ExternalChange{
Cell: emptyCell,
Action: board.ActionSetNumber,
Value: missingNumbers[0],
From: emptyCell.GetNumber(),
TriggerdBy: ld.getName(),
}
ld.changes = append(ld.changes, change)
}
})
//fmt.Printf("LastDigit Changes %d", len(ld.changes))
+12 -10
View File
@@ -1,6 +1,6 @@
package strategies
import "git.kleiax.de/homepage/libs/sudoku/board"
import "git.kleiax.de/homepage/board"
// ────────────────────────────────────────────────────────────────────────────── //
// NAKED_SINGLE STRUCTURE //
@@ -13,15 +13,17 @@ type NakedSingle struct {
func (ns *NakedSingle) SearchProgressableCells() int {
ns.field.ForEachPart(func(part board.Part) {
part.ForEachCell(func(cell *board.Cell) {
// candidates := cell.notes.numbers
// if len(candidates) == 1 {
// change := Change{
// cell: cell,
// action: ActionSetNumber,
// value: candidates[0],
// }
// ns.changes = append(ns.changes, change)
// }
candidates := cell.Notes.Get()
if len(candidates) == 1 {
change := board.ExternalChange{
Cell: cell,
Action: board.ActionSetNumber,
Value: candidates[0],
From: cell.GetNumber(),
TriggerdBy: ns.getName(),
}
ns.changes = append(ns.changes, change)
}
})
})
return len(ns.changes)
+15 -17
View File
@@ -3,7 +3,7 @@ package strategies
import (
"fmt"
"git.kleiax.de/homepage/libs/sudoku/board"
"git.kleiax.de/homepage/board"
)
// ────────────────────────────────────────────────────────────────────────────── //
@@ -14,11 +14,18 @@ type Strategy interface {
Init(f *board.Field)
ApplyAll() int
ApplyNext() bool
ApplyOne(n int) bool
Name() string
SearchProgressableCells() int
}
// ────────────────────────────────────────────────────────────────────────────── //
// VISUALITION INTERFACE //
// ────────────────────────────────────────────────────────────────────────────── //
type StrategyVisualization interface {
pointOut(f *board.Field) []board.Mark
}
// ────────────────────────────────────────────────────────────────────────────── //
// BASE STRUCTURE //
// ────────────────────────────────────────────────────────────────────────────── //
@@ -26,7 +33,7 @@ type Strategy interface {
type Base struct {
name string
field *board.Field
changes []board.Change //eigener Typ muss her
changes []board.ExternalChange
}
func (b *Base) Init(f *board.Field) {
@@ -34,9 +41,9 @@ func (b *Base) Init(f *board.Field) {
}
func (b *Base) ApplyAll() int {
// for _, change := range sb.changes {
// //change.do()
// }
for _, change := range b.changes {
b.field.AddChange(&change)
}
return len(b.changes)
}
@@ -44,24 +51,15 @@ func (b *Base) ApplyNext() bool {
if len(b.changes) < 1 {
return false
}
//sb.changes[0].do()
b.field.AddChange(&b.changes[0])
b.changes = b.changes[1:]
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 {
return "Unkown"
}
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"
"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() {
solver := sudoku.Solver{}
solver.Add(&sudoku.LastDigit{})
solver.Add(&sudoku.NakedSingle{})
game, err := sudoku.New(&sudoku.PuzzleBank{}, solver, openFile())
solver := logic.Solver{}
solver.Add(&strategies.LastDigit{})
solver.Add(&strategies.NakedSingle{})
game, err := sudoku.New(&board.PuzzleBank{}, solver, openFile())
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
@@ -31,7 +34,7 @@ func main() {
}
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 {
fmt.Println("Kann datei nicht öffnen")
os.Exit(3)
+9 -9
View File
@@ -4,8 +4,8 @@ import (
"errors"
"fmt"
"git.kleiax.de/homepage/libs/sudoku/board"
"git.kleiax.de/homepage/libs/sudoku/logic"
"git.kleiax.de/homepage/board"
"git.kleiax.de/homepage/logic"
)
type Game struct {
@@ -13,16 +13,16 @@ type Game struct {
solver logic.Solver
}
func New(parser Parser, solver Solver, data []byte) (*Game, error) {
err := parser.parse(data)
func New(parser board.Parser, solver logic.Solver, data []byte) (*Game, error) {
err := parser.Parse(data)
if err != nil {
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 {
g.solver.initStragies(g.field)
g.solver.InitStragies(g.field)
for !g.isFinished() {
if !g.nextSolveStep() {
return errors.New("no strategy can solve the puzzle")
@@ -32,7 +32,7 @@ func (g *Game) Solve() error {
}
func (g *Game) nextSolveStep() bool {
return g.solver.run(0)
return g.solver.Run(0)
}
func (g *Game) prevSolveStep() {
@@ -40,9 +40,9 @@ func (g *Game) prevSolveStep() {
}
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
}
+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
// }