mirror of
https://github.com/cjdenio/crossword.git
synced 2026-10-03 11:06:19 +00:00
we cooking
This commit is contained in:
3 files changed
+127
-6
No files matched your search
@@ -1,8 +1,5 @@
|
|||||||
todo
|
todo
|
||||||
|
|
||||||
- When pressing enter, skip filled words
|
|
||||||
- Shift-enter
|
|
||||||
- check puzzle when grid is filled
|
|
||||||
- fix bug with that one 6x6 puzzle
|
- fix bug with that one 6x6 puzzle
|
||||||
- correctly calculate uiHeight with multi-line clues
|
- correctly calculate uiHeight with multi-line clues
|
||||||
- timer
|
- timer
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -68,6 +70,16 @@ func (state *State) MoveCursor(direction int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (state *State) ClueFilled(clue *puz.Clue) bool {
|
||||||
|
for _, cell := range clue.Cells {
|
||||||
|
if state.PuzzleState[cell] == '-' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (state *State) FirstUnfilledCellForClue(clue *puz.Clue) int {
|
func (state *State) FirstUnfilledCellForClue(clue *puz.Clue) int {
|
||||||
for _, cell := range clue.Cells {
|
for _, cell := range clue.Cells {
|
||||||
if state.PuzzleState[cell] == '-' {
|
if state.PuzzleState[cell] == '-' {
|
||||||
@@ -90,7 +102,7 @@ func (state *State) NextWord() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if foundSelectedClue && clue.Direction == state.SelectedClue.Direction {
|
if foundSelectedClue && clue.Direction == state.SelectedClue.Direction && !state.ClueFilled(clue) {
|
||||||
state.SelectedClue = clue
|
state.SelectedClue = clue
|
||||||
state.SelectedCell = state.FirstUnfilledCellForClue(clue)
|
state.SelectedCell = state.FirstUnfilledCellForClue(clue)
|
||||||
return
|
return
|
||||||
@@ -98,7 +110,62 @@ func (state *State) NextWord() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, clue := range state.Puzzle.Clues {
|
for _, clue := range state.Puzzle.Clues {
|
||||||
if clue.Direction != state.SelectedClue.Direction {
|
if clue.Direction != state.SelectedClue.Direction && !state.ClueFilled(clue) {
|
||||||
|
state.SelectedClue = clue
|
||||||
|
state.SelectedCell = state.FirstUnfilledCellForClue(clue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, clue := range state.Puzzle.Clues {
|
||||||
|
if clue == state.SelectedClue {
|
||||||
|
return
|
||||||
|
} else if clue.Direction == state.SelectedClue.Direction && !state.ClueFilled(clue) {
|
||||||
|
state.SelectedClue = clue
|
||||||
|
state.SelectedCell = state.FirstUnfilledCellForClue(clue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *State) PreviousWord() {
|
||||||
|
if state.SelectedClue == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
foundSelectedClue := false
|
||||||
|
|
||||||
|
for i := len(state.Puzzle.Clues) - 1; i >= 0; i-- {
|
||||||
|
clue := state.Puzzle.Clues[i]
|
||||||
|
|
||||||
|
if !foundSelectedClue && clue == state.SelectedClue {
|
||||||
|
foundSelectedClue = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if foundSelectedClue && clue.Direction == state.SelectedClue.Direction && !state.ClueFilled(clue) {
|
||||||
|
state.SelectedClue = clue
|
||||||
|
state.SelectedCell = state.FirstUnfilledCellForClue(clue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := len(state.Puzzle.Clues) - 1; i >= 0; i-- {
|
||||||
|
clue := state.Puzzle.Clues[i]
|
||||||
|
|
||||||
|
if clue.Direction != state.SelectedClue.Direction && !state.ClueFilled(clue) {
|
||||||
|
state.SelectedClue = clue
|
||||||
|
state.SelectedCell = state.FirstUnfilledCellForClue(clue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := len(state.Puzzle.Clues) - 1; i >= 0; i-- {
|
||||||
|
clue := state.Puzzle.Clues[i]
|
||||||
|
|
||||||
|
if clue == state.SelectedClue {
|
||||||
|
return
|
||||||
|
} else if clue.Direction == state.SelectedClue.Direction && !state.ClueFilled(clue) {
|
||||||
state.SelectedClue = clue
|
state.SelectedClue = clue
|
||||||
state.SelectedCell = state.FirstUnfilledCellForClue(clue)
|
state.SelectedCell = state.FirstUnfilledCellForClue(clue)
|
||||||
return
|
return
|
||||||
@@ -242,3 +309,36 @@ func RenderPuzzle(puzzle []rune, width, height int, selectedClueCells []int, sel
|
|||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SaveFile struct {
|
||||||
|
State string `json:"state"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *State) CreateSaveFile() ([]byte, error) {
|
||||||
|
return json.Marshal(SaveFile{
|
||||||
|
State: string(state.PuzzleState),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *State) LoadSaveFile(f []byte) error {
|
||||||
|
var save SaveFile
|
||||||
|
err := json.Unmarshal(f, &save)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify the save file matches the shape of the puzzle
|
||||||
|
if len(save.State) != state.Puzzle.Width*state.Puzzle.Height {
|
||||||
|
return errors.New("save is invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, cell := range state.Puzzle.Solution {
|
||||||
|
if (save.State[i] == '.' && cell != '.') || (save.State[i] != '.' && cell == '.') {
|
||||||
|
return errors.New("save is invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.PuzzleState = []rune(save.State)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -29,6 +29,11 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileInfo, err := os.Stat(filename)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
puzzle, err := puz.ParsePuz(file)
|
puzzle, err := puz.ParsePuz(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@@ -56,6 +61,15 @@ func main() {
|
|||||||
state.DebugMode = *debugMode
|
state.DebugMode = *debugMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try to load a saveFile
|
||||||
|
saveFile, err := os.ReadFile(filename + ".save")
|
||||||
|
if err == nil {
|
||||||
|
err = state.LoadSaveFile(saveFile)
|
||||||
|
if state.DebugMode && err != nil {
|
||||||
|
state.LastKeySequence = fmt.Sprintf("failed to read savefile: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uiHeight := state.RenderUI()
|
uiHeight := state.RenderUI()
|
||||||
|
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
@@ -82,6 +96,13 @@ func main() {
|
|||||||
state.LastKeySequence = fmt.Sprintf("%v", buffer)
|
state.LastKeySequence = fmt.Sprintf("%v", buffer)
|
||||||
|
|
||||||
if buffer[0] == 3 {
|
if buffer[0] == 3 {
|
||||||
|
saveFile, err := state.CreateSaveFile()
|
||||||
|
if err == nil {
|
||||||
|
err = os.WriteFile(filename+".save", saveFile, fileInfo.Mode())
|
||||||
|
if err != nil && state.DebugMode {
|
||||||
|
state.LastKeySequence = fmt.Sprintf("failed to write savefile: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
state.SelectedClue = nil
|
state.SelectedClue = nil
|
||||||
state.SelectedCell = -1
|
state.SelectedCell = -1
|
||||||
state.Goodbye = true
|
state.Goodbye = true
|
||||||
@@ -149,9 +170,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if buffer[0] == 0x0d {
|
if buffer[0] == '\r' {
|
||||||
state.NextWord()
|
state.NextWord()
|
||||||
}
|
}
|
||||||
|
if buffer[0] == '~' {
|
||||||
|
state.PreviousWord()
|
||||||
|
}
|
||||||
|
|
||||||
if string(buffer[0:2]) == "\x1b[" {
|
if string(buffer[0:2]) == "\x1b[" {
|
||||||
if (buffer[2] == 68 || buffer[2] == 67) && state.SelectedClue != nil && state.SelectedClue.Direction == puz.DirectionDown {
|
if (buffer[2] == 68 || buffer[2] == 67) && state.SelectedClue != nil && state.SelectedClue.Direction == puz.DirectionDown {
|
||||||
|
|||||||
Reference in new issue
Block a user