Skip to content

Commit

Permalink
game; not just a generator/solver (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
jedib0t authored Sep 14, 2022
1 parent 1bfe6ad commit 2069c08
Show file tree
Hide file tree
Showing 33 changed files with 1,288 additions and 522 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
# Run some demos
- name: Demo
run: |
make demo demo-solve
make demo-generator demo-solver
# Run all the unit-tests
- name: Test
Expand Down
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@
.coverprofile
/.idea/
/dist
/go-sudoku
/go-sudoku.exe
/go-sudoku*
38 changes: 26 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,45 @@ default: run

all: test

build:
go build .
build: build-game build-generator

demo: build
./go-sudoku generate
./go-sudoku -type jigsaw generate
./go-sudoku -type samurai generate
build-game:
go build -o go-sudoku ./cmd/game

demo-solve: build
./go-sudoku -format csv generate | ./go-sudoku -progress solve
build-generator:
go build -o go-sudoku-generator ./cmd/generator

dist:
demo-generator: build-generator
./go-sudoku-generator generate
./go-sudoku-generator -type jigsaw generate
./go-sudoku-generator -type samurai generate

demo-solver: build-generator
./go-sudoku-generator -format csv generate | ./go-sudoku-generator -progress solve

dist: dist-game dist-generator

dist-game:
gox -ldflags="-s -w -X main.version=${VERSION}" \
-os="linux darwin windows" \
-arch="amd64" \
-output="./dist/go-sudoku_{{.OS}}_{{.Arch}}_${VERSION}" \
./cmd/game

dist-generator:
gox -ldflags="-s -w -X main.version=${VERSION}" \
-os="linux darwin windows" \
-arch="amd64" \
-output="./dist/{{.Dir}}_{{.OS}}_{{.Arch}}" \
.
-output="./dist/go-sudoku-generator_{{.OS}}_{{.Arch}}_${VERSION}" \
./cmd/generator

fmt: tidy
go fmt $(shell go list ./...)

gen: gen-readme

gen-readme: build
./scripts/generate_readme.sh > README.md
./docs/generate_readme.sh > README.md

get-tools:
go install github.com/mitchellh/[email protected]
Expand Down
92 changes: 42 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,68 +1,59 @@
# go-sudoku
<!----------------------------------------------------------------------------------------------------------------------
-- Please note that this file is auto-generated using the 'scripts/generate_readme.sh' script. Changes to this file will
-- be over-written in the next build. If you need to change this file, make the changes to 'scripts/README.md.template'
-- Please note that this file is auto-generated using the 'docs/generate_readme.sh' script. Changes to this file will
-- be over-written in the next build. If you need to change this file, make the changes to 'docs/README.md.template'
-- instead.
---------------------------------------------------------------------------------------------------------------------->

[![Build Status](https://github.com/jedib0t/go-sudoku/workflows/CI/badge.svg?branch=main)](https://github.com/jedib0t/go-sudoku/actions?query=workflow%3ACI+event%3Apush+branch%3Amain)

An implementation of Sudoku generators and solvers in GoLang.
An implementation of Sudoku game, generators and solvers for the command line in
GoLang.

## Usage
# Install

### Help
```
$ ./go-sudoku --help
go-sudoku: A GoLang based Sudoku generator and solver.
You can download the latest release for your OS [here](https://github.com/jedib0t/go-sudoku/releases/latest).

Usage: go-sudoku [flags] <action>
## Screenshot

Version: dev
<img src="docs/game.png" alt="Game"/>

Actions:
--------
* generate: Generate a Sudoku Grid and apply the specified difficulty on it
* solve: Solve a Sudoku puzzle provided in a text (CSV) file
# Usage

Examples:
---------
* ./go-sudoku
* ./go-sudoku -algorithm back-tracking -theme green -seed 42 generate
* ./go-sudoku -format csv generate
* ./go-sudoku -input puzzle.csv solve
* ./go-sudoku -difficulty hard -format csv generate | ./go-sudoku solve
## Game
```
$ ./go-sudoku -help
go-sudoku: A GoLang implementation of the Sudoku game.
Version: dev
Optional Flags:
---------------
-algorithm string
Algorithm (back-tracking/brute-force) (default "back-tracking")
-debug
Enable Debug Logging?
Flags
=====
-allow-wrong
Allow incorrect values?
-demo
play automatically? (this cheats to win)
-difficulty string
Difficulty (none/easy/medium/hard/insane) (default "medium")
-format string
Rendering Format (csv/table) (default "table")
Difficulty (none/kids/easy/medium/hard/insane) (default "medium")
-help
Display this usage and help text
-input string
File containing a Sudoku Puzzle in CSV format
-no-color
Disable colors in rendering? [$NO_COLOR]
Show this help-text?
-hints
Highlight possible values in the Keyboard?
-pattern string
Pattern to use instead of Difficulty (diamond/octagon/square/star/target/triangle)
-progress
Show progress in real-time with an artificial delay?
-refresh-rate int
Refresh-rate per second (default 20)
-seed int
RNG Seed (0 => random number based on time) [$SEED]
-type string
Sudoku Type (default/jigsaw/samurai) (default "default")
Randomizer Seed value (will use random number if ZERO)
-show-wrong
Highlight incorrect values in Red?
```

### Generator
*Note: all the commands below were run with SEED=42 to keep the results reproducible.*
## Generator
*Note: all the commands below were run with the environment variable `SEED=42`
to keep the results reproducible.*
```
$ ./go-sudoku generate
$ ./go-sudoku-generator generate
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 8 5 │ 6 │ 2 1 ┃
┃ 7 │ 9 2 │ ┃
Expand All @@ -80,7 +71,7 @@ $ ./go-sudoku generate
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
## custom difficulty
$ ./go-sudoku -difficulty insane generate
$ ./go-sudoku-generator -difficulty insane generate
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 8 │ 6 │ 2 ┃
┃ │ │ ┃
Expand All @@ -98,7 +89,7 @@ $ ./go-sudoku -difficulty insane generate
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
## custom pattern
$ ./go-sudoku -pattern diamond generate
$ ./go-sudoku-generator -pattern diamond generate
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ │ 6 │ ┃
┃ │ 9 2 3 │ ┃
Expand All @@ -116,7 +107,7 @@ $ ./go-sudoku -pattern diamond generate
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
## samurai sudoku
$ ./go-sudoku -type samurai generate
$ ./go-sudoku-generator -type samurai generate
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 1 │ 2 8 │ 5 6 │ │ 4 8 │ 2 1 │ ┃
┃ 5 │ │ │ │ 9 │ 8 4 7 │ 6 3 ┃
Expand All @@ -130,7 +121,7 @@ $ ./go-sudoku -type samurai generate
┃ 6 2 │ │ 1 │ 9 2 │ │ 3 │ 1 2 ┃
┃ 4 5 │ │ 2 │ │ │ 5 2 │ 8 6 ┃
┃ ─────────┴─────────┼─────────┼─────────┼─────────┼─────────┴───────── ┃
┃ │ │ 7 3 │ ┃
┃ │ │ 7 3 │ ┃
┃ │ │ 4 2 │ 5 │ ┃
┃ │ 7 │ 3 9 │ 2 8 │ ┃
┃ ─────────┬─────────┼─────────┼─────────┼─────────┼─────────┬───────── ┃
Expand All @@ -150,11 +141,12 @@ $ ./go-sudoku -type samurai generate
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
```

### Solver
*Note: all the commands below were run with SEED=42 to keep the results reproducible.*
## Solver
*Note: all the commands below were run with the environment variable `SEED=42`
to keep the results reproducible.*
```
## generate a new puzzle and feed it to the solver to solve
$ ./go-sudoku -format csv generate | ./go-sudoku solve
$ ./go-sudoku-generator -format csv generate | ./go-sudoku-generator solve
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ INPUT ┃ OUTPUT ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
Expand Down
51 changes: 51 additions & 0 deletions cmd/game/actions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package main

import "github.com/jedib0t/go-sudoku/sudoku"

func handleActionHelp() {
numOccurringMost, numOccurrencesMost := 1, 0
for n := 1; n <= 9; n++ {
numOccurrences := grid.CountValue(n)
if numOccurrences > numOccurrencesMost {
numOccurringMost = n
numOccurrencesMost = numOccurrences
}
}

easiestBlock := cursor
var possibilities *sudoku.Possibilities
for x := 0; x < 9; x++ {
for y := 0; y < 9; y++ {
p := grid.Possibilities(x, y)
if p != nil && (possibilities == nil || possibilities.AvailableLen() > p.AvailableLen()) {
easiestBlock = sudoku.Location{X: x, Y: y}
possibilities = p

// stop early if we've found a number that occurs most, and fits
// a block like nothing else
if possibilities.AvailableLen() == 1 && possibilities.AvailableMap()[numOccurringMost] {
cursor = easiestBlock
return
}
}
}
}
cursor = easiestBlock
}

func handleActionQuit() {
userQuit = true
}

func handleActionReset() {
renderMutex.Lock()
defer renderMutex.Unlock()

generateSudoku()
}

func handleActionInput(char rune) {
renderMutex.Lock()
defer renderMutex.Unlock()

}
53 changes: 53 additions & 0 deletions cmd/game/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package main

import (
"flag"
"fmt"
"math/rand"
"os"
"strings"
"time"

"github.com/jedib0t/go-sudoku/sudoku/difficulty"
"github.com/jedib0t/go-sudoku/sudoku/pattern"
)

var (
difficulties = strings.ToLower(strings.Join(difficulty.Names(), "/"))
patterns = strings.ToLower(strings.Join(pattern.Names(), "/"))

flagAllowWrong = flag.Bool("allow-wrong", false, "Allow incorrect values?")
flagDemo = flag.Bool("demo", false, "play automatically? (this cheats to win)")
flagDifficulty = flag.String("difficulty", "medium", "Difficulty ("+difficulties+")")
flagHelp = flag.Bool("help", false, "Show this help-text?")
flagHints = flag.Bool("hints", false, "Highlight possible values in the Keyboard?")
flagPattern = flag.String("pattern", "", "Pattern to use instead of Difficulty ("+patterns+")")
flagRefreshRate = flag.Int("refresh-rate", 20, "Refresh-rate per second")
flagSeed = flag.Int64("seed", 0, "Randomizer Seed value (will use random number if ZERO)")
flagShowWrong = flag.Bool("show-wrong", false, "Highlight incorrect values in Red?")
)

func initFlags() {
flag.Parse()
if *flagHelp {
printHelp()
}

gameDiff = difficulty.From(*flagDifficulty)
gamePtrn = pattern.Get(*flagPattern)
if *flagSeed == 0 {
*flagSeed = time.Now().UnixNano() % 10000
}
rng = rand.New(rand.NewSource(*flagSeed))
}

func printHelp() {
fmt.Println(`go-sudoku: A GoLang implementation of the Sudoku game.
Version: ` + version + `
Flags
=====`)
flag.PrintDefaults()
os.Exit(0)
}
Loading

0 comments on commit 2069c08

Please sign in to comment.