refactore to new project structure
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,5 +0,0 @@
|
||||
package sudoku
|
||||
|
||||
// type StrategyVisualization interface {
|
||||
// pointOut(f *Field) []Mark
|
||||
// }
|
||||
Reference in New Issue
Block a user