Skip to content

Commit

Permalink
implement endless mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Jan Steinke committed Feb 12, 2024
1 parent 1378f11 commit 06d69fb
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 124 deletions.
63 changes: 29 additions & 34 deletions logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"math/big"
"time"

"github.com/jan-xyz/simon-says/ui"
"github.com/maxence-charriere/go-app/v9/pkg/app"
)

Expand All @@ -20,10 +21,10 @@ const (
hard
)

var difficulties = map[difficulty]sequenceLength{
easy: 4,
medium: 8,
hard: 12,
var difficulties = map[ui.Difficulty]int{
ui.Easy: 4,
ui.Medium: 8,
ui.Hard: 12,
}

type gameState int
Expand All @@ -37,16 +38,15 @@ const (
)

func NewLogic() *logic {
return &logic{
sequence: []int64{},
}
return &logic{}
}

type logic struct {
sequence []int64
clicks int
stage int
state gameState
difficulty ui.Difficulty
sequence []int64
clicks int
stage int
state gameState
}

func (g *logic) simonSays(ctx app.Context, a app.Action) {
Expand All @@ -55,32 +55,32 @@ func (g *logic) simonSays(ctx app.Context, a app.Action) {
fmt.Println("wrong type")
return
}
fmt.Println("sequence:", sequence)

go func() {
<-time.After(200 * time.Millisecond)
for _, btnIndex := range sequence {
fmt.Println("sending", btnIndex)
ctx.NewAction(fmt.Sprintf(eventPlayButton, btnIndex))
ctx.NewAction(fmt.Sprintf(ui.EventPlayButton, btnIndex))
<-time.After(time.Second)
}
g.state = gameStatePlayerSays
ctx.NewActionWithValue(eventStateChange, g.state)
ctx.NewActionWithValue(ui.EventStateChange, "Repeat what Simon said...")
}()
}

func (g *logic) handleNewGame(ctx app.Context, a app.Action) {
d, ok := a.Value.(difficulty)
d, ok := a.Value.(ui.Difficulty)
if !ok {
fmt.Println("wrong type")
return
}
g.difficulty = d
g.clicks = 0
g.sequence = GenerateSequence(difficulties[d])
g.sequence = []int64{NextNumber()}
g.stage = 1
g.state = gameStateSimonSays
ctx.NewActionWithValue(eventStateChange, g.state)
ctx.NewActionWithValue(eventSimonSays, g.sequence[:1])
ctx.NewActionWithValue(ui.EventStateChange, "Simon says...")
ctx.NewActionWithValue(ui.EventSimonSays, g.sequence)
}

func (g *logic) handleClick(ctx app.Context, a app.Action) {
Expand All @@ -93,38 +93,33 @@ func (g *logic) handleClick(ctx app.Context, a app.Action) {
return
}

fmt.Println("received click:", click)
if g.sequence[g.clicks] != click {
g.state = gameStateLost
ctx.NewActionWithValue(eventStateChange, g.state)
ctx.NewActionWithValue(ui.EventStateChange, fmt.Sprintf("You Lost in %s mode with %d colors", g.difficulty, g.clicks))
return
}
g.clicks++
if len(g.sequence) == g.clicks {
if g.difficulty != ui.Endless && difficulties[g.difficulty] == g.clicks {
g.state = gameStateWon
ctx.NewActionWithValue(eventStateChange, g.state)
ctx.NewActionWithValue(ui.EventStateChange, fmt.Sprintf("You Won in %s mode. Start a New Game", g.difficulty))
return
}
if g.clicks == g.stage {
g.clicks = 0
g.stage++
g.state = gameStateSimonSays
ctx.NewActionWithValue(eventStateChange, g.state)
g.sequence = append(g.sequence, NextNumber())
ctx.NewActionWithValue(ui.EventStateChange, "Simon says...")
ctx.After(1*time.Second, func(ctx app.Context) {
ctx.NewActionWithValue(eventSimonSays, g.sequence[:g.stage])
ctx.NewActionWithValue(ui.EventSimonSays, g.sequence)
})
}
}

func GenerateSequence(l sequenceLength) []int64 {
seq := []int64{}
for i := 0; i < int(l); i++ {
n, err := rand.Int(rand.Reader, big.NewInt(4))
if err != nil {
panic(err)
}
seq = append(seq, n.Int64())

func NextNumber() int64 {
n, err := rand.Int(rand.Reader, big.NewInt(4))
if err != nil {
panic(err)
}
return seq
return n.Int64()
}
9 changes: 5 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"log"
"net/http"

"github.com/jan-xyz/simon-says/ui"
"github.com/maxence-charriere/go-app/v9/pkg/app"
)

Expand All @@ -26,11 +27,11 @@ func main() {
// TODO: add tests
// TODO: add dependabot
// TODO: add linter
app.Handle(eventSimonSays, l.simonSays)
app.Handle(eventClick, l.handleClick)
app.Handle(eventNewGame, l.handleNewGame)
app.Handle(ui.EventSimonSays, l.simonSays)
app.Handle(ui.EventClick, l.handleClick)
app.Handle(ui.EventNewGame, l.handleNewGame)

g := NewUI()
g := ui.NewUI()
app.Route("/", g)

// When executed on the client-side, the RunWhenOnBrowser() function
Expand Down
61 changes: 0 additions & 61 deletions menu.go

This file was deleted.

2 changes: 1 addition & 1 deletion styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ html, body {
font-size: 12px;
justify-content: center;
line-height: 1em;
max-width: 250px;
max-width: 340px;
min-width: 140px;
padding: 3px;
text-decoration: none;
Expand Down
6 changes: 3 additions & 3 deletions button.go → ui/button.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package ui

import (
"fmt"
Expand All @@ -21,7 +21,7 @@ func NewButton(id int64) *button {
}

func (b *button) OnMount(ctx app.Context) {
ctx.Handle(fmt.Sprintf(eventPlayButton, b.id), b.handleActivate)
ctx.Handle(fmt.Sprintf(EventPlayButton, b.id), b.handleActivate)
}

func (b *button) Render() app.UI {
Expand All @@ -42,7 +42,7 @@ func (b *button) handleClick(ctx app.Context, _ app.Event) {
b.Active = true
ctx.After(400*time.Millisecond, func(_ app.Context) {
b.Active = false
ctx.NewActionWithValue(eventClick, b.id)
ctx.NewActionWithValue(EventClick, b.id)
})
})
}
Expand Down
59 changes: 59 additions & 0 deletions ui/menu.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package ui

import (
"github.com/maxence-charriere/go-app/v9/pkg/app"
)

type (
Difficulty string
)

const (
Easy Difficulty = "easy"
Medium Difficulty = "medium"
Hard Difficulty = "hard"
Endless Difficulty = "endless"
)

type menu struct {
app.Compo
selectedDifficulty Difficulty
}

func NewMenu() *menu {
return &menu{selectedDifficulty: Easy}
}

func (g *menu) Render() app.UI {
return app.Div().Body(

app.Button().
Class("simon-button", "new-game").
Body(app.Span().Text("New Game")).
OnClick(func(ctx app.Context, _ app.Event) {
ctx.NewActionWithValue(EventNewGame, g.selectedDifficulty)
}),
app.Div().Class("difficulty").Body(
app.Input().Type("radio").Name("difficulty-setting").ID("difficulty%d", Easy).Value(Easy).Checked(true).OnClick(func(ctx app.Context, _ app.Event) {
val := ctx.JSSrc().Get("value").String()
g.selectedDifficulty = Difficulty(val)
}),
app.Label().For("difficulty%d", Easy).Body(app.Span().Text("easy")),
app.Input().Type("radio").Name("difficulty-setting").ID("difficulty%d", Medium).Value(Medium).OnClick(func(ctx app.Context, _ app.Event) {
val := ctx.JSSrc().Get("value").String()
g.selectedDifficulty = Difficulty(val)
}),
app.Label().For("difficulty%d", Medium).Body(app.Span().Text("medium")),
app.Input().Type("radio").Name("difficulty-setting").ID("difficulty%d", Hard).Value(Hard).OnClick(func(ctx app.Context, _ app.Event) {
val := ctx.JSSrc().Get("value").String()
g.selectedDifficulty = Difficulty(val)
}),
app.Label().For("difficulty%d", Hard).Body(app.Span().Text("hard")),
app.Input().Type("radio").Name("difficulty-setting").ID("difficulty%d", Endless).Value(Endless).OnClick(func(ctx app.Context, _ app.Event) {
val := ctx.JSSrc().Get("value").String()
g.selectedDifficulty = Difficulty(val)
}),
app.Label().For("difficulty%d", Endless).Body(app.Span().Text("endless")),
),
)
}
29 changes: 8 additions & 21 deletions ui.go → ui/ui.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package ui

import (
"fmt"
Expand All @@ -9,11 +9,11 @@ import (
type events = string

const (
eventClick events = "click"
eventSimonSays events = "playSequence"
eventPlayButton events = "play%d"
eventNewGame events = "newGame"
eventStateChange events = "stateChange"
EventClick events = "click"
EventSimonSays events = "playSequence"
EventPlayButton events = "play%d"
EventNewGame events = "newGame"
EventStateChange events = "stateChange"
)

func NewUI() *ui {
Expand All @@ -27,7 +27,7 @@ type ui struct {
}

func (g *ui) OnMount(ctx app.Context) {
ctx.Handle(eventStateChange, g.handleStateChange)
ctx.Handle(EventStateChange, g.handleStateChange)
}

func (g *ui) Render() app.UI {
Expand Down Expand Up @@ -60,24 +60,11 @@ func (g *ui) Render() app.UI {
}

func (b *ui) handleStateChange(ctx app.Context, a app.Action) {
state, ok := a.Value.(gameState)
txt, ok := a.Value.(string)
if !ok {
fmt.Println("wrong type")
return
}
txt := ""
switch state {
case gameStateNoGame:
txt = "Start a New Game"
case gameStatePlayerSays:
txt = "Repeat what Simon said..."
case gameStateSimonSays:
txt = "Simon says..."
case gameStateLost:
txt = "You Lost. Start a New Game"
case gameStateWon:
txt = "You Won. Start a New Game"
}
ctx.Dispatch(func(_ app.Context) {
b.Text = txt
})
Expand Down

0 comments on commit 06d69fb

Please sign in to comment.