Refactor Sudoku field and solver implementation

This commit is contained in:
2026-09-16 22:52:44 +02:00
parent 8a5ae8c640
commit f7f9c16184
24 changed files with 1574 additions and 603 deletions
+42 -88
View File
@@ -1,123 +1,77 @@
package field
// ────────────────────────────────────────────────────────────────────────────── //
// NOTES STRUCTURE //
// ────────────────────────────────────────────────────────────────────────────── //
import "slices"
type Notes struct {
numbers []int
}
func (n *Notes) Add(field *Field, cell *Cell, note int, trigger string, marks []Mark) {
if slices.Contains(n.numbers, note) {
return // Note already exists
func (n *Notes) Add(f *Field, cell *Cell, note int, trigger string, marks []Mark) error {
if n == nil || cell == nil || cell.notes != n {
return ErrInvalidCell
}
field.changes = append(field.changes, Change{
Cell: cell,
marks: marks,
action: ActionSetNote,
value: note,
from: 0,
triggerdBy: trigger,
})
n.numbers = append(n.numbers, note)
return f.AddChange(&ExternalChange{Cell: cell, Marks: marks, Action: ActionSetNote, Value: note, TriggerdBy: trigger})
}
func (n *Notes) Remove(field *Field, cell *Cell, note int, trigger string, marks []Mark) {
for i, existing := range n.numbers {
if existing == note {
field.changes = append(field.changes, Change{
Cell: cell,
marks: marks,
action: ActionRemoveNote,
value: 0,
from: note,
triggerdBy: trigger,
})
n.numbers = append(n.numbers[:i], n.numbers[i+1:]...)
return
}
func (n *Notes) Remove(f *Field, cell *Cell, note int, trigger string, marks []Mark) error {
if n == nil || cell == nil || cell.notes != n {
return ErrInvalidCell
}
return f.AddChange(&ExternalChange{Cell: cell, Marks: marks, Action: ActionRemoveNote, From: note, TriggerdBy: trigger})
}
func (n *Notes) Get() []int {
copySlice := make([]int, len(n.numbers))
copy(copySlice, n.numbers)
return copySlice
if n == nil {
return nil
}
return slices.Clone(n.numbers)
}
func (n *Notes) Has(i int) bool {
return slices.Contains(n.numbers, i)
func (n *Notes) Has(number int) bool {
return n != nil && slices.Contains(n.numbers, number)
}
// ────────────────────────────────────────────────────────────────────────────── //
// CELL STRUCTURE //
// ────────────────────────────────────────────────────────────────────────────── //
type Cell struct {
number int
Notes *Notes
Pos *Position
notes *Notes
pos *Position
}
func NewCell(number int, pos *Position) *Cell {
cell := Cell{
number: number,
Pos: pos,
Notes: &Notes{},
}
return &cell
return &Cell{number: number, notes: &Notes{}, pos: pos}
}
func (c *Cell) SetNumber(field *Field, n int, trigger string, marks []Mark) {
if c.number == n {
return
func (c *Cell) SetNumber(f *Field, number int, trigger string, marks []Mark) error {
if c == nil {
return ErrInvalidCell
}
if field == nil {
return
}
if n <= 0 || n > field.props.Rows || n > field.props.Columns {
return
}
field.changes = append(field.changes, Change{
Cell: c,
marks: marks,
action: ActionSetNumber,
value: n,
from: c.number,
triggerdBy: trigger,
})
c.number = n
return f.AddChange(&ExternalChange{Cell: c, Marks: marks, Action: ActionSetNumber, Value: number, From: c.number, TriggerdBy: trigger})
}
func (c *Cell) RemoveNumber(field *Field, trigger string, marks []Mark) {
if c.number == 0 {
return
func (c *Cell) RemoveNumber(f *Field, trigger string, marks []Mark) error {
if c == nil {
return ErrInvalidCell
}
if field == nil {
return
}
field.changes = append(field.changes, Change{
action: ActionSetNumber,
Cell: c,
value: 0,
from: c.number,
marks: marks,
triggerdBy: trigger,
})
c.number = 0
return f.AddChange(&ExternalChange{Cell: c, Marks: marks, Action: ActionRemoveNumber, From: c.number, TriggerdBy: trigger})
}
func (c *Cell) GetNumber() int {
if c == nil {
return 0
}
return c.number
}
func (c *Cell) GetNotes() *Notes {
if c == nil {
return nil
}
return c.notes
}
func (c *Cell) GetPosition() *Position {
if c == nil {
return nil
}
return c.pos
}