feat(fsharp): m01-m06 util, model, rules, random, spawn, game, view with Expecto tests
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
183821737e
commit
9cbefeb2be
@@ -0,0 +1,38 @@
|
||||
/// m06 view: the picture is plain data (a list of shapes); drawing it is somebody else's job (m07).
|
||||
module Snake.View
|
||||
|
||||
open Snake.Model
|
||||
|
||||
/// A thing to draw.
|
||||
type Shape =
|
||||
| Rect of x: int * y: int * w: int * h: int * color: string
|
||||
| Text of x: int * y: int * text: string * color: string * size: int * align: string
|
||||
|
||||
/// A picture: shapes drawn in order.
|
||||
type Scene = Shape list
|
||||
|
||||
let CELL = 20
|
||||
|
||||
let private text x y str size align = Text(x, y, str, "#ffffff", size, align)
|
||||
|
||||
// One cell, inset by 1px so neighbouring segments show a gap.
|
||||
let private cell (p: Point) color =
|
||||
Rect(p.X * CELL + 1, p.Y * CELL + 1, CELL - 2, CELL - 2, color)
|
||||
|
||||
let private overlay (state: GameState) : Scene =
|
||||
let cx = state.Width * CELL / 2
|
||||
let cy = state.Height * CELL / 2
|
||||
let banner title hint = [ text cx cy title 32 "center"; text cx (cy + 30) hint 16 "center" ]
|
||||
|
||||
match state.Status with
|
||||
| Paused -> banner "Paused" "Press Space to resume"
|
||||
| GameOver -> banner "Game Over" "Press R to restart"
|
||||
| Won -> banner "You Win!" "Press R to restart"
|
||||
| Playing -> []
|
||||
|
||||
let view (state: GameState) : Scene =
|
||||
[ Rect(0, 0, state.Width * CELL, state.Height * CELL, "#111111") ]
|
||||
@ (state.Apple |> Option.map (fun a -> cell a "#e53935") |> Option.toList)
|
||||
@ (state.Snake |> List.mapi (fun i p -> cell p (if i = 0 then "#7cb342" else "#43a047")))
|
||||
@ [ text 6 18 $"Score: {state.Score}" 16 "left" ]
|
||||
@ overlay state
|
||||
Reference in New Issue
Block a user