mirror of
https://github.com/cjdenio/crossword.git
synced 2026-10-03 11:06:19 +00:00
many improvements
This commit is contained in:
3 files changed
+311
-247
No files matched your search
@@ -5,4 +5,4 @@ todo
|
|||||||
- check puzzle when grid is filled
|
- 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
|
||||||
- handle multiple keypresses in one `read`
|
- timer
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/cjdenio/crossword/puz"
|
||||||
|
)
|
||||||
|
|
||||||
|
type State struct {
|
||||||
|
Puzzle *puz.Puzzle
|
||||||
|
PuzzleState []rune
|
||||||
|
SelectedCell int
|
||||||
|
SelectedClue *puz.Clue
|
||||||
|
Goodbye bool
|
||||||
|
LastKeySequence string
|
||||||
|
DebugMode bool
|
||||||
|
SolveState int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *State) MoveCursor(direction int) {
|
||||||
|
switch direction {
|
||||||
|
case 0: // up
|
||||||
|
if state.SelectedCell < state.Puzzle.Width { // if already in the top row, do nothing
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := state.SelectedCell - state.Puzzle.Width; i >= 0; i -= state.Puzzle.Width {
|
||||||
|
if state.PuzzleState[i] != '.' {
|
||||||
|
state.SelectedCell = i
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 1: // right
|
||||||
|
if (state.SelectedCell+1)%state.Puzzle.Width == 0 { // if already in the right column, do nothing
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := state.SelectedCell + 1; i%state.Puzzle.Width != 0; i += 1 {
|
||||||
|
if state.PuzzleState[i] != '.' {
|
||||||
|
state.SelectedCell = i
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 2: // down
|
||||||
|
if (state.SelectedCell) >= (state.Puzzle.Width*state.Puzzle.Height)-state.Puzzle.Width { // if already in the bottom row, do nothing
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := state.SelectedCell + state.Puzzle.Width; i < (state.Puzzle.Width * state.Puzzle.Height); i += state.Puzzle.Width {
|
||||||
|
if state.PuzzleState[i] != '.' {
|
||||||
|
state.SelectedCell = i
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 3: // left
|
||||||
|
if state.SelectedCell%state.Puzzle.Width == 0 { // if already in the left column, do nothing
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := state.SelectedCell - 1; (i+1)%state.Puzzle.Width != 0; i -= 1 {
|
||||||
|
if state.PuzzleState[i] != '.' {
|
||||||
|
state.SelectedCell = i
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *State) FirstUnfilledCellForClue(clue *puz.Clue) int {
|
||||||
|
for _, cell := range clue.Cells {
|
||||||
|
if state.PuzzleState[cell] == '-' {
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return clue.Cells[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *State) NextWord() {
|
||||||
|
if state.SelectedClue == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
foundSelectedClue := false
|
||||||
|
|
||||||
|
for _, clue := range state.Puzzle.Clues {
|
||||||
|
if !foundSelectedClue && clue == state.SelectedClue {
|
||||||
|
foundSelectedClue = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if foundSelectedClue && clue.Direction == state.SelectedClue.Direction {
|
||||||
|
state.SelectedClue = clue
|
||||||
|
state.SelectedCell = state.FirstUnfilledCellForClue(clue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, clue := range state.Puzzle.Clues {
|
||||||
|
if clue.Direction != state.SelectedClue.Direction {
|
||||||
|
state.SelectedClue = clue
|
||||||
|
state.SelectedCell = state.FirstUnfilledCellForClue(clue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *State) GridFilled() bool {
|
||||||
|
return !slices.Contains(state.PuzzleState, '-')
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *State) CheckPuzzle() bool {
|
||||||
|
for i, cell := range state.PuzzleState {
|
||||||
|
if cell == '.' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if cell != rune(state.Puzzle.Solution[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *State) RenderUI() int {
|
||||||
|
selectedClueCells := []int{}
|
||||||
|
if state.SelectedClue != nil {
|
||||||
|
selectedClueCells = state.SelectedClue.Cells
|
||||||
|
}
|
||||||
|
|
||||||
|
uiHeight := 0
|
||||||
|
|
||||||
|
fmt.Printf("\r\nTITLE: %s\r\n", state.Puzzle.Title)
|
||||||
|
uiHeight += 2
|
||||||
|
fmt.Printf("AUTHOR: %s\r\n", state.Puzzle.Author)
|
||||||
|
uiHeight += 1
|
||||||
|
fmt.Print(RenderPuzzle(state.PuzzleState, state.Puzzle.Width, state.Puzzle.Height, selectedClueCells, state.SelectedCell) + "\r\n")
|
||||||
|
uiHeight += state.Puzzle.Height + 3
|
||||||
|
if state.SelectedClue != nil {
|
||||||
|
if state.SelectedClue.Direction == puz.DirectionAcross {
|
||||||
|
fmt.Printf("%d-across: %s\r\n\r\n", state.SelectedClue.Number, state.SelectedClue.Clue)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("%d-down: %s\r\n\r\n", state.SelectedClue.Number, state.SelectedClue.Clue)
|
||||||
|
}
|
||||||
|
uiHeight += 2
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\r\n", state.Puzzle.Copyright)
|
||||||
|
uiHeight += 1
|
||||||
|
|
||||||
|
switch state.SolveState {
|
||||||
|
case 1:
|
||||||
|
fmt.Print("\r\nThe puzzle was filled, but at least 1 letter is incorrect...\r\n")
|
||||||
|
uiHeight += 2
|
||||||
|
case 2:
|
||||||
|
fmt.Printf("\r\n%s\r\n", AnsiGreen("The puzzle was solved!"))
|
||||||
|
uiHeight += 2
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.LastKeySequence != "" && state.DebugMode {
|
||||||
|
fmt.Printf("\r\n%s\r\n", AnsiDimmed(state.LastKeySequence))
|
||||||
|
uiHeight += 2
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.Goodbye {
|
||||||
|
fmt.Print("\r\nsee ya\r\n")
|
||||||
|
uiHeight += 2
|
||||||
|
}
|
||||||
|
|
||||||
|
return uiHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
AnsiInvert string = "\x1b[7m"
|
||||||
|
AnsiReset string = "\x1b[m"
|
||||||
|
AnsiWhiteBackground string = "\x1b[100m"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AnsiInverted(s string) string {
|
||||||
|
return AnsiInvert + s + AnsiReset
|
||||||
|
}
|
||||||
|
func AnsiWhiteBackgrounded(s string) string {
|
||||||
|
return AnsiWhiteBackground + s + AnsiReset
|
||||||
|
}
|
||||||
|
func AnsiDimmed(s string) string {
|
||||||
|
return fmt.Sprintf("\x1b[2m%s\x1b[0m", s)
|
||||||
|
}
|
||||||
|
func AnsiGreen(s string) string {
|
||||||
|
return fmt.Sprintf("\x1b[32m%s\x1b[0m", s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RenderPuzzle(puzzle []rune, width, height int, selectedClueCells []int, selectedCell int) string {
|
||||||
|
b := strings.Builder{}
|
||||||
|
|
||||||
|
b.WriteRune('┌')
|
||||||
|
for range (width * 2) + 1 {
|
||||||
|
b.WriteRune('─')
|
||||||
|
}
|
||||||
|
b.WriteString("┐\r\n")
|
||||||
|
|
||||||
|
for index, char := range puzzle {
|
||||||
|
if index%width == 0 {
|
||||||
|
b.WriteString("│ ")
|
||||||
|
}
|
||||||
|
|
||||||
|
cell := ""
|
||||||
|
switch char {
|
||||||
|
case '.':
|
||||||
|
cell = string(rune(0x2588))
|
||||||
|
case '-':
|
||||||
|
cell = AnsiDimmed("_")
|
||||||
|
default:
|
||||||
|
cell = string(char)
|
||||||
|
}
|
||||||
|
|
||||||
|
if selectedCell == index {
|
||||||
|
cell = AnsiInverted(cell)
|
||||||
|
} else if slices.Contains(selectedClueCells, index) {
|
||||||
|
cell = AnsiWhiteBackgrounded(cell)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString(cell)
|
||||||
|
|
||||||
|
if (index+1)%width == 0 {
|
||||||
|
b.WriteString(" │\r\n")
|
||||||
|
} else if char == '.' && puzzle[index+1] == '.' {
|
||||||
|
b.WriteRune(0x2588)
|
||||||
|
} else {
|
||||||
|
// inefficient
|
||||||
|
if slices.Contains(selectedClueCells, index) && slices.Contains(selectedClueCells, index+1) {
|
||||||
|
b.WriteString(AnsiWhiteBackgrounded(" "))
|
||||||
|
} else {
|
||||||
|
b.WriteRune(' ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteRune('└')
|
||||||
|
for range (width * 2) + 1 {
|
||||||
|
b.WriteRune('─')
|
||||||
|
}
|
||||||
|
b.WriteString("┘\r\n")
|
||||||
|
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
@@ -1,237 +1,19 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"github.com/cjdenio/crossword/puz"
|
"github.com/cjdenio/crossword/puz"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
AnsiInvert string = "\x1b[7m"
|
|
||||||
AnsiReset string = "\x1b[m"
|
|
||||||
AnsiWhiteBackground string = "\x1b[100m"
|
|
||||||
)
|
|
||||||
|
|
||||||
func AnsiInverted(s string) string {
|
|
||||||
return AnsiInvert + s + AnsiReset
|
|
||||||
}
|
|
||||||
func AnsiWhiteBackgrounded(s string) string {
|
|
||||||
return AnsiWhiteBackground + s + AnsiReset
|
|
||||||
}
|
|
||||||
func AnsiDimmed(s string) string {
|
|
||||||
return fmt.Sprintf("\x1b[2m%s\x1b[0m", s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RenderPuzzle(puzzle []rune, width, height int, selectedClueCells []int, selectedCell int) string {
|
|
||||||
b := strings.Builder{}
|
|
||||||
|
|
||||||
b.WriteRune('┌')
|
|
||||||
for range (width * 2) + 1 {
|
|
||||||
b.WriteRune('─')
|
|
||||||
}
|
|
||||||
b.WriteString("┐\r\n")
|
|
||||||
|
|
||||||
for index, char := range puzzle {
|
|
||||||
if index%width == 0 {
|
|
||||||
b.WriteString("│ ")
|
|
||||||
}
|
|
||||||
|
|
||||||
cell := ""
|
|
||||||
switch char {
|
|
||||||
case '.':
|
|
||||||
cell = string(rune(0x2588))
|
|
||||||
case '-':
|
|
||||||
cell = AnsiDimmed("_")
|
|
||||||
default:
|
|
||||||
cell = string(char)
|
|
||||||
}
|
|
||||||
|
|
||||||
if selectedCell == index {
|
|
||||||
cell = AnsiInverted(cell)
|
|
||||||
} else if slices.Contains(selectedClueCells, index) {
|
|
||||||
cell = AnsiWhiteBackgrounded(cell)
|
|
||||||
}
|
|
||||||
|
|
||||||
b.WriteString(cell)
|
|
||||||
|
|
||||||
if (index+1)%width == 0 {
|
|
||||||
b.WriteString(" │\r\n")
|
|
||||||
} else if char == '.' && puzzle[index+1] == '.' {
|
|
||||||
b.WriteRune(0x2588)
|
|
||||||
} else {
|
|
||||||
// inefficient
|
|
||||||
if slices.Contains(selectedClueCells, index) && slices.Contains(selectedClueCells, index+1) {
|
|
||||||
b.WriteString(AnsiWhiteBackgrounded(" "))
|
|
||||||
} else {
|
|
||||||
b.WriteRune(' ')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b.WriteRune('└')
|
|
||||||
for range (width * 2) + 1 {
|
|
||||||
b.WriteRune('─')
|
|
||||||
}
|
|
||||||
b.WriteString("┘\r\n")
|
|
||||||
|
|
||||||
return b.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
type State struct {
|
|
||||||
Puzzle *puz.Puzzle
|
|
||||||
PuzzleState []rune
|
|
||||||
SelectedCell int
|
|
||||||
SelectedClue *puz.Clue
|
|
||||||
Goodbye bool
|
|
||||||
LastKeySequence string
|
|
||||||
DebugMode bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (state *State) MoveCursor(direction int) {
|
|
||||||
switch direction {
|
|
||||||
case 0: // up
|
|
||||||
if state.SelectedCell < state.Puzzle.Width { // if already in the top row, do nothing
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := state.SelectedCell - state.Puzzle.Width; i >= 0; i -= state.Puzzle.Width {
|
|
||||||
if state.PuzzleState[i] != '.' {
|
|
||||||
state.SelectedCell = i
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 1: // right
|
|
||||||
if (state.SelectedCell+1)%state.Puzzle.Width == 0 { // if already in the right column, do nothing
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := state.SelectedCell + 1; i%state.Puzzle.Width != 0; i += 1 {
|
|
||||||
if state.PuzzleState[i] != '.' {
|
|
||||||
state.SelectedCell = i
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 2: // down
|
|
||||||
if (state.SelectedCell) >= (state.Puzzle.Width*state.Puzzle.Height)-state.Puzzle.Width { // if already in the bottom row, do nothing
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := state.SelectedCell + state.Puzzle.Width; i < (state.Puzzle.Width * state.Puzzle.Height); i += state.Puzzle.Width {
|
|
||||||
if state.PuzzleState[i] != '.' {
|
|
||||||
state.SelectedCell = i
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 3: // left
|
|
||||||
if state.SelectedCell%state.Puzzle.Width == 0 { // if already in the left column, do nothing
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := state.SelectedCell - 1; (i+1)%state.Puzzle.Width != 0; i -= 1 {
|
|
||||||
if state.PuzzleState[i] != '.' {
|
|
||||||
state.SelectedCell = i
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (state *State) FirstUnfilledCellForClue(clue *puz.Clue) int {
|
|
||||||
for _, cell := range clue.Cells {
|
|
||||||
if state.PuzzleState[cell] == '-' {
|
|
||||||
return cell
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return clue.Cells[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (state *State) NextWord() {
|
|
||||||
if state.SelectedClue == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
foundSelectedClue := false
|
|
||||||
|
|
||||||
for _, clue := range state.Puzzle.Clues {
|
|
||||||
if !foundSelectedClue && clue == state.SelectedClue {
|
|
||||||
foundSelectedClue = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if foundSelectedClue && clue.Direction == state.SelectedClue.Direction {
|
|
||||||
state.SelectedClue = clue
|
|
||||||
state.SelectedCell = state.FirstUnfilledCellForClue(clue)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, clue := range state.Puzzle.Clues {
|
|
||||||
if clue.Direction != state.SelectedClue.Direction {
|
|
||||||
state.SelectedClue = clue
|
|
||||||
state.SelectedCell = state.FirstUnfilledCellForClue(clue)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func RenderUI(state *State) int {
|
|
||||||
selectedClueCells := []int{}
|
|
||||||
if state.SelectedClue != nil {
|
|
||||||
selectedClueCells = state.SelectedClue.Cells
|
|
||||||
}
|
|
||||||
|
|
||||||
uiHeight := 0
|
|
||||||
|
|
||||||
fmt.Printf("\r\nTITLE: %s\r\n", state.Puzzle.Title)
|
|
||||||
uiHeight += 2
|
|
||||||
fmt.Printf("AUTHOR: %s\r\n", state.Puzzle.Author)
|
|
||||||
uiHeight += 1
|
|
||||||
fmt.Print(RenderPuzzle(state.PuzzleState, state.Puzzle.Width, state.Puzzle.Height, selectedClueCells, state.SelectedCell) + "\r\n")
|
|
||||||
uiHeight += state.Puzzle.Height + 3
|
|
||||||
if state.SelectedClue != nil {
|
|
||||||
if state.SelectedClue.Direction == puz.DirectionAcross {
|
|
||||||
fmt.Printf("%d-across: %s\r\n\r\n", state.SelectedClue.Number, state.SelectedClue.Clue)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("%d-down: %s\r\n\r\n", state.SelectedClue.Number, state.SelectedClue.Clue)
|
|
||||||
}
|
|
||||||
uiHeight += 2
|
|
||||||
}
|
|
||||||
fmt.Printf("%s\r\n", state.Puzzle.Copyright)
|
|
||||||
uiHeight += 1
|
|
||||||
|
|
||||||
if state.LastKeySequence != "" && state.DebugMode {
|
|
||||||
fmt.Printf("\r\n%s\r\n", AnsiDimmed(state.LastKeySequence))
|
|
||||||
uiHeight += 2
|
|
||||||
}
|
|
||||||
|
|
||||||
if state.Goodbye {
|
|
||||||
fmt.Print("\r\nsee ya\r\n")
|
|
||||||
uiHeight += 2
|
|
||||||
}
|
|
||||||
|
|
||||||
return uiHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Print("\x1b[?25l")
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
fmt.Print("\x1b[?25h")
|
|
||||||
}()
|
|
||||||
termState, err := term.MakeRaw(int(os.Stdin.Fd()))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer term.Restore(int(os.Stdin.Fd()), termState)
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
fmt.Print("!!! PROGRAM CRASHED !!! Error:\r\n", r, "\r\n")
|
fmt.Print("!!! PROGRAM CRASHED !!! Error:\r\n", r, "\r\n")
|
||||||
@@ -252,6 +34,18 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Print("\x1b[?25l")
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
fmt.Print("\x1b[?25h")
|
||||||
|
}()
|
||||||
|
termState, err := term.MakeRaw(int(os.Stdin.Fd()))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer term.Restore(int(os.Stdin.Fd()), termState)
|
||||||
|
|
||||||
state := State{
|
state := State{
|
||||||
Puzzle: puzzle,
|
Puzzle: puzzle,
|
||||||
PuzzleState: []rune(puzzle.State),
|
PuzzleState: []rune(puzzle.State),
|
||||||
@@ -262,14 +56,28 @@ func main() {
|
|||||||
state.DebugMode = *debugMode
|
state.DebugMode = *debugMode
|
||||||
}
|
}
|
||||||
|
|
||||||
uiHeight := RenderUI(&state)
|
uiHeight := state.RenderUI()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
|
scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||||
|
if len(data) == 0 {
|
||||||
|
return 0, nil, bufio.ErrFinalToken
|
||||||
|
}
|
||||||
|
|
||||||
|
if data[0] == 0x1b {
|
||||||
|
if len(data) < 3 {
|
||||||
|
return 0, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return 3, data[0:3], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1, data[0:1], nil
|
||||||
|
})
|
||||||
|
|
||||||
for {
|
for {
|
||||||
buffer := make([]byte, 3)
|
scanner.Scan()
|
||||||
_, err = os.Stdin.Read(buffer)
|
buffer := scanner.Bytes()
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
state.LastKeySequence = fmt.Sprintf("%v", buffer)
|
state.LastKeySequence = fmt.Sprintf("%v", buffer)
|
||||||
|
|
||||||
@@ -279,7 +87,7 @@ func main() {
|
|||||||
state.Goodbye = true
|
state.Goodbye = true
|
||||||
fmt.Printf("\r\x1b[%dA", uiHeight)
|
fmt.Printf("\r\x1b[%dA", uiHeight)
|
||||||
fmt.Print("\x1b[J")
|
fmt.Print("\x1b[J")
|
||||||
RenderUI(&state)
|
state.RenderUI()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,6 +124,16 @@ func main() {
|
|||||||
state.SelectedCell = state.SelectedClue.Cells[i+1]
|
state.SelectedCell = state.SelectedClue.Cells[i+1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if state.GridFilled() {
|
||||||
|
if state.CheckPuzzle() {
|
||||||
|
state.SolveState = 2
|
||||||
|
} else {
|
||||||
|
state.SolveState = 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state.SolveState = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if buffer[0] == 0x7f {
|
if buffer[0] == 0x7f {
|
||||||
@@ -335,33 +153,35 @@ func main() {
|
|||||||
state.NextWord()
|
state.NextWord()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer[2] == 68 || buffer[2] == 67) && state.SelectedClue != nil && state.SelectedClue.Direction == puz.DirectionDown {
|
if string(buffer[0:2]) == "\x1b[" {
|
||||||
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][0]
|
if (buffer[2] == 68 || buffer[2] == 67) && state.SelectedClue != nil && state.SelectedClue.Direction == puz.DirectionDown {
|
||||||
} else if (buffer[2] == 65 || buffer[2] == 66) && state.SelectedClue != nil && state.SelectedClue.Direction == puz.DirectionAcross {
|
|
||||||
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][1]
|
|
||||||
} else {
|
|
||||||
switch buffer[2] {
|
|
||||||
case 68: // left
|
|
||||||
state.MoveCursor(3)
|
|
||||||
case 67: // right
|
|
||||||
state.MoveCursor(1)
|
|
||||||
case 65: // up
|
|
||||||
state.MoveCursor(0)
|
|
||||||
case 66: // down
|
|
||||||
state.MoveCursor(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch state.SelectedClue.Direction {
|
|
||||||
case puz.DirectionAcross:
|
|
||||||
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][0]
|
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][0]
|
||||||
case puz.DirectionDown:
|
} else if (buffer[2] == 65 || buffer[2] == 66) && state.SelectedClue != nil && state.SelectedClue.Direction == puz.DirectionAcross {
|
||||||
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][1]
|
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][1]
|
||||||
|
} else {
|
||||||
|
switch buffer[2] {
|
||||||
|
case 68: // left
|
||||||
|
state.MoveCursor(3)
|
||||||
|
case 67: // right
|
||||||
|
state.MoveCursor(1)
|
||||||
|
case 65: // up
|
||||||
|
state.MoveCursor(0)
|
||||||
|
case 66: // down
|
||||||
|
state.MoveCursor(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch state.SelectedClue.Direction {
|
||||||
|
case puz.DirectionAcross:
|
||||||
|
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][0]
|
||||||
|
case puz.DirectionDown:
|
||||||
|
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][1]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("\r\x1b[%dA", uiHeight)
|
fmt.Printf("\r\x1b[%dA", uiHeight)
|
||||||
fmt.Print("\x1b[J")
|
fmt.Print("\x1b[J")
|
||||||
|
|
||||||
uiHeight = RenderUI(&state)
|
uiHeight = state.RenderUI()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user