Knight's tour: Difference between revisions
Content added Content deleted
(→{{header|Elm}}: Updated to Elm 0.19.1) |
|||
Line 2,522: | Line 2,522: | ||
=={{header|Elm}}== |
=={{header|Elm}}== |
||
<lang elm> |
<lang elm>module Main exposing (main) |
||
⚫ | |||
import List exposing (concatMap, foldl, head,member,filter,length,minimum,concat,map,map2,tail) |
|||
import List.Extra exposing (minimumBy, andThen) |
import List.Extra exposing (minimumBy, andThen) |
||
import String exposing (join) |
import String exposing (join) |
||
import Html as H |
import Html as H |
||
import Html.Attributes as HA |
import Html.Attributes as HA |
||
import |
import Time exposing (Posix, every) |
||
⚫ | |||
import Svg exposing (rect, line, svg, g) |
import Svg exposing (rect, line, svg, g) |
||
import Svg.Events exposing (onClick) |
import Svg.Events exposing (onClick) |
||
Line 2,537: | Line 2,539: | ||
rowCount=20 |
rowCount=20 |
||
colCount=20 |
colCount=20 |
||
dt = 0.03 |
|||
type alias Cell = (Int, Int) |
type alias Cell = (Int, Int) |
||
type alias Model = |
type alias Model = |
||
{ path : List Cell |
{ path : List Cell |
||
, board : List Cell |
, board : List Cell |
||
} |
} |
||
type Msg |
|||
type Msg = NoOp | Tick Time | SetStart Cell |
|||
= NoOp |
|||
| Tick Time.Posix |
|||
| SetStart Cell |
|||
init : (Model,Cmd Msg) |
init : () -> (Model,Cmd Msg) |
||
init |
init _ = |
||
let board = |
let board = (List.range 0 (rowCount-1)) |
||
|> andThen |
|||
(\r -> |
|||
(List.range 0 (colCount-1)) |
|||
|> andThen |
|||
(\c -> |
|||
[(r, c)] |
|||
) |
|||
) |
|||
path = [] |
path = [] |
||
in (Model path board, Cmd.none) |
in (Model path board, Cmd.none) |
||
view : Model -> H.Html Msg |
view : Model -> H.Html Msg |
||
view model = |
view model = |
||
let |
let |
||
showChecker row col = |
showChecker row col = |
||
rect [ x <| |
rect [ x <| String.fromInt col |
||
, y <| |
, y <| String.fromInt row |
||
, width "1" |
, width "1" |
||
, height "1" |
, height "1" |
||
, fill <| if (row + col) |
, fill <| if modBy 2 (row + col) == 0 then "blue" else "grey" |
||
, onClick <| SetStart (row, col) |
, onClick <| SetStart (row, col) |
||
] |
] |
||
[] |
[] |
||
showMove (row0,col0) (row1,col1) = |
showMove (row0,col0) (row1,col1) = |
||
line [ x1 <| |
line [ x1 <| String.fromFloat ((toFloat col0) + 0.5) |
||
, y1 <| |
, y1 <| String.fromFloat ((toFloat row0) + 0.5) |
||
, x2 <| |
, x2 <| String.fromFloat ((toFloat col1) + 0.5) |
||
, y2 <| |
, y2 <| String.fromFloat ((toFloat row1) + 0.5) |
||
, style "stroke:yellow;stroke-width:0.05" |
, style "stroke:yellow;stroke-width:0.05" |
||
] |
] |
||
[] |
[] |
||
render |
render mdl = |
||
let checkers = |
let checkers = mdl.board |
||
|> andThen |
|||
(\(r,c) -> |
|||
[showChecker r c] |
|||
) |
|||
moves = case List.tail mdl.path of |
|||
Nothing -> [] |
Nothing -> [] |
||
Just tl -> List.map2 showMove |
Just tl -> List.map2 showMove mdl.path tl |
||
in checkers ++ moves |
in checkers ++ moves |
||
unvisited = length model.board - length model.path |
unvisited = length model.board - length model.path |
||
center = HA.style |
center = [ HA.style "text-align" "center" ] |
||
in |
in |
||
H.div |
H.div |
||
[] |
[] |
||
[ H.h2 |
[ H.h2 center [H.text "Knight's Tour"] |
||
, H.h2 |
, H.h2 center [H.text <| "Unvisited count : " ++ String.fromInt unvisited ] |
||
, H.h2 |
, H.h2 center [H.text "(pick a square)"] |
||
, H.div |
, H.div |
||
center |
|||
[ svg |
[ svg |
||
[ version "1.1" |
[ version "1.1" |
||
, width ( |
, width (String.fromInt w) |
||
, height ( |
, height (String.fromInt h) |
||
, viewBox (join " " |
, viewBox (join " " |
||
[ |
[ String.fromInt 0 |
||
, |
, String.fromInt 0 |
||
, |
, String.fromInt colCount |
||
, |
, String.fromInt rowCount ]) |
||
] |
] |
||
[ g [] <| render model] |
[ g [] <| render model] |
||
] |
] |
||
] |
] |
||
nextMoves : Model -> Cell -> List Cell |
nextMoves : Model -> Cell -> List Cell |
||
nextMoves model (stRow,stCol) = |
nextMoves model (stRow,stCol) = |
||
let c = [ 1, 2, -1, -2] |
let c = [ 1, 2, -1, -2] |
||
km = c |
km = c |
||
|> andThen |
|||
(\cRow -> |
|||
c |
|||
|> andThen |
|||
(\cCol -> |
|||
if abs(cRow) == abs(cCol) then [] else [(cRow,cCol)] |
|||
) |
|||
) |
|||
jumps = List.map (\(kmRow,kmCol) -> (kmRow + stRow, kmCol + stCol)) km |
jumps = List.map (\(kmRow,kmCol) -> (kmRow + stRow, kmCol + stCol)) km |
||
Line 2,625: | Line 2,644: | ||
bestMove : Model -> Maybe Cell |
bestMove : Model -> Maybe Cell |
||
bestMove model = |
bestMove model = |
||
case List.head (model.path) of |
case List.head (model.path) of |
||
Nothing -> Nothing |
Nothing -> Nothing |
||
Line 2,633: | Line 2,652: | ||
update msg model = |
update msg model = |
||
let mo = case msg of |
let mo = case msg of |
||
SetStart start -> |
SetStart start -> |
||
{model | path = [start]} |
{model | path = [start]} |
||
Tick |
Tick posix -> |
||
case model.path of |
case model.path of |
||
[] -> model |
[] -> model |
||
Line 2,645: | Line 2,664: | ||
subscriptions : Model -> Sub Msg |
subscriptions : Model -> Sub Msg |
||
subscriptions _ = |
subscriptions _ = |
||
Time.every |
Time.every 10 Tick |
||
main = |
main = |
||
element |
|||
program |
|||
{ init = init |
{ init = init |
||
, view = view |
, view = view |
||
, update = update |
, update = update |
||
, subscriptions = subscriptions |
, subscriptions = subscriptions |
||
} |
} |
||
</lang> |
|||
Link to live demo: http://dc25.github.io/knightsTourElm/ |
Link to live demo: http://dc25.github.io/knightsTourElm/ |