State tests 100%

This commit is contained in:
Madison Rye Progress
2025-08-28 22:16:29 -07:00
parent 29bd181e4f
commit bef9cd248e
6 changed files with 82 additions and 27 deletions

View File

@ -51,10 +51,10 @@ func (c cell) vivify() cell {
// kill sets the state of the cell to dead.
func (c cell) kill() cell {
c = c &^ statebit
if c.flagged() {
return c.setCorrect(true)
} else {
if c.marked() {
return c.setCorrect(false)
} else {
return c.setCorrect(true)
}
}
@ -99,6 +99,13 @@ func (c cell) flag() cell {
}
// clear clears all bits except for the status.
func (c cell) clear() cell {
return c &^ (markbit | flagbit | correctbit | completebit)
func (c cell) clear(deadCorrect bool) cell {
// Unset all bits except status
c = c &^ (markbit | flagbit | correctbit | completebit)
// If a dead cell is to be marked correct so long as it is *not* marked, set the correct bit
if deadCorrect && !c.state() {
c |= correctbit
}
return c
}

View File

@ -89,7 +89,7 @@ func TestCell(t *testing.T) {
So(c.flagged(), ShouldBeFalse)
So(c.correct(), ShouldBeTrue)
So(c.complete(), ShouldBeTrue)
c = c.clear()
c = c.clear(false)
So(c.state(), ShouldBeTrue)
So(c.marked(), ShouldBeFalse)
So(c.flagged(), ShouldBeFalse)

View File

@ -94,6 +94,6 @@ func (f *field) flag(p Point) {
}
// clear clears all but the cell's state.
func (f *field) clear(p Point) {
f.cells[f.i(p)] = f.cells[f.i(p)].clear()
func (f *field) clear(p Point, deadCorrect bool) {
f.cells[f.i(p)] = f.cells[f.i(p)].clear(deadCorrect)
}

View File

@ -44,7 +44,7 @@ func TestField(t *testing.T) {
So(f.marked(p), ShouldBeTrue)
f.flag(p)
So(f.flagged(p), ShouldBeTrue)
f.clear(p)
f.clear(p, false)
So(f.correct(p), ShouldBeFalse)
So(f.complete(p), ShouldBeFalse)
So(f.marked(p), ShouldBeFalse)

View File

@ -42,7 +42,7 @@ func (s *State) String() string {
for x := 0; x < s.sectionSize*s.cellsPerSection; x++ {
for y := 0; y < s.sectionSize*s.cellsPerSection; y++ {
p := Point{x, y}
if s.cells.correct(p) {
if s.cells.correct(p) && (s.cells.marked(p) || s.cells.flagged(p)) {
if s.cells.state(p) {
buf.WriteString("O")
} else {
@ -53,11 +53,15 @@ func (s *State) String() string {
buf.WriteString("o")
} else if s.cells.flagged(p) {
buf.WriteString("x")
} else {
if s.cells.state(p) {
buf.WriteString(".")
} else {
buf.WriteString(" ")
}
}
}
}
buf.WriteString("\n")
}
return buf.String()
@ -72,19 +76,19 @@ func (s *State) Flag() []bool {
}
func (s *State) Clear() {
s.clear(*s.cursor)
s.clear(*s.cursor, true)
}
func (s *State) view(cursor []int) {
}
func (s *State) initSection(p Point) {
s.sections.clear(p)
s.sections.clear(p, false)
startX := p.X * s.cellsPerSection
startY := p.Y * s.cellsPerSection
for x := 0; x < s.cellsPerSection; x++ {
for y := 0; y < s.cellsPerSection; y++ {
s.cells.clear(Point{x + startX, y + startY})
s.cells.clear(Point{x + startX, y + startY}, true)
if rand.Int()%2 == 0 {
s.cells.kill(Point{x + startX, y + startY})
} else {
@ -92,6 +96,7 @@ func (s *State) initSection(p Point) {
}
}
}
s.update(p)
}
func (s *State) mark(p Point) []bool {
@ -104,8 +109,8 @@ func (s *State) flag(p Point) []bool {
return s.update(p)
}
func (s *State) clear(p Point) {
s.cells.clear(p)
func (s *State) clear(p Point, deadCorrect bool) {
s.cells.clear(p, deadCorrect)
s.update(p)
}
@ -113,7 +118,7 @@ func (s *State) sectionCorrect(p Point) bool {
sectionCorrect := true
for x := 0; x < s.cellsPerSection; x++ {
for y := 0; y < s.cellsPerSection; y++ {
sectionCorrect = sectionCorrect && s.cells.correct(Point{p.X + x, p.Y + y})
sectionCorrect = sectionCorrect && s.cells.correct(Point{p.X*s.cellsPerSection + x, p.Y*s.cellsPerSection + y})
}
}
return sectionCorrect
@ -137,15 +142,15 @@ func (s *State) clearValidCompletedSections() []bool {
cleared := make([]bool, s.sections.size*s.sections.size)
for x := 0; x < s.sectionSize; x++ {
for y := 0; y < s.sectionSize; y++ {
clearable := s.sections.complete(Point{x, y})
s.sections.complete(Point{x + 1%s.sectionSize, y})
s.sections.complete(Point{x, y + 1%s.sectionSize})
s.sections.complete(Point{x + 1%s.sectionSize, y + 1%s.sectionSize})
clearable := s.sections.complete(Point{x, y}) &&
s.sections.complete(Point{(x + 1) % s.sectionSize, y}) &&
s.sections.complete(Point{x, (y + 1) % s.sectionSize}) &&
s.sections.complete(Point{(x + 1) % s.sectionSize, (y + 1) % s.sectionSize})
if clearable {
cleared[y*s.sectionSize+x] = true
cleared[y*s.sectionSize+(x+1%s.sectionSize)] = true
cleared[(y*s.sectionSize+s.sectionSize%len(cleared))+x] = true
cleared[(y*s.sectionSize+s.sectionSize%len(cleared))+(x+1%s.sectionSize)] = true
cleared[(y*s.sectionSize + (x+1)%s.sectionSize)] = true
cleared[((y*s.sectionSize+s.sectionSize)%(len(cleared)) + x)] = true
cleared[((y*s.sectionSize+s.sectionSize)+(x+1%s.sectionSize))%len(cleared)] = true
}
}
}

View File

@ -9,6 +9,14 @@ import (
func TestState(t *testing.T) {
Convey("Given a game state", t, func() {
s := New(2, 2)
for x := 0; x < 4; x++ {
for y := 0; y < 4; y++ {
s.cells.kill(Point{x, y})
if x < 2 && y < 2 {
s.sections.clear(Point{x, y}, false)
}
}
}
Convey("You can get the size", func() {
So(s.size(), ShouldEqual, 4)
@ -23,20 +31,55 @@ func TestState(t *testing.T) {
Convey("It shows correct guesses", func() {
s.Mark()
s.flag(Point{0, 1})
So(s.String(), ShouldEqual, "OX \n \n \n \n")
So(s.String(), ShouldEqual, "OX \n. \n \n \n")
})
Convey("It shows incorrect guesses", func() {
s.Flag()
s.mark(Point{0, 1})
So(s.String(), ShouldEqual, "xo \n \n \n \n")
So(s.String(), ShouldEqual, "xo \n. \n \n \n")
})
Convey("It shows cleared guesses as empty", func() {
s.Flag()
s.mark(Point{0, 1})
s.Clear()
So(s.String(), ShouldEqual, " o \n \n \n \n")
So(s.String(), ShouldEqual, ".o \n. \n \n \n")
})
})
Convey("You can complete sections and clear portions of the board", func() {
s.cells.vivify(Point{0, 0})
s.cells.vivify(Point{2, 0})
s.cells.vivify(Point{0, 2})
s.cells.vivify(Point{2, 2})
Convey("It marks sections as correct when they are correctly guessed", func() {
res := s.mark(Point{0, 0})
So(s.cells.correct(Point{0, 0}), ShouldBeTrue)
So(s.sections.correct(Point{0, 0}), ShouldBeTrue)
So(s.String(), ShouldEqual, "O . \n \n. . \n \n")
So(res, ShouldResemble, make([]bool, 4))
})
Convey("It marks sections as complete if they meet the criteria", func() {
s.mark(Point{0, 0})
s.mark(Point{2, 0})
res := s.mark(Point{0, 2})
So(res, ShouldResemble, make([]bool, 4))
So(s.String(), ShouldEqual, "O O \n \nO . \n \n")
So(s.sections.correct(Point{0, 0}), ShouldBeTrue)
So(s.sections.correct(Point{1, 0}), ShouldBeTrue)
So(s.sections.correct(Point{0, 1}), ShouldBeTrue)
So(s.sections.complete(Point{0, 0}), ShouldBeTrue)
})
Convey("It clears sections when they meet the criteria", func() {
s.mark(Point{0, 0})
s.mark(Point{2, 0})
s.mark(Point{0, 2})
res := s.mark(Point{2, 2})
So(res, ShouldResemble, []bool{true, true, true, true})
})
})
})