追記: コメントでelmらしく書こうというアドバイスを頂いたので記事をかなり書き換えました
もしも書き換え前の記事を参考にした方がいたらごめんなさい
##はじめに
Elm歴はElm Guideや「基礎からわかるElm」を一通り読んだ程度
HTML, CSS JavaScirptは基本的な構文すら勉強してない
そんな奴が書いた記事読みたくないよ~って人はブラウザバック推奨ということで・・・
##ひな形を書く
module Main exposing (..)
import Browser
import Html exposing (..)
--MAIN--
main : Program () Model Msg
main =
Browser.element
{ init = init
, update = update
, subscriptions = subscriptions
, view = view
}
--MODEL--
type alias Model =
()
init : () -> ( Model, Cmd Msg )
init _ =
( (), Cmd.none )
--UPDATE--
type alias Msg =
Never
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
( model, Cmd.none )
--SUBSCRIPTIONS--
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
--VIEW--
view : Model -> Html Msg
view model =
div [] []
elm reactorで見てみると真っ白な画面が表示される
ひな型に追加していく形で進めていく
viewを書く
--VIEW--
view : Model -> Html Msg
view model =
div []
[ h1 [] [ text "Rock-paper-scissors" ]
, h2 [] [ text "Choice your hand" ]
, button [] [ text "Rock" ]
, button [] [ text "Paper" ]
, button [] [ text "Scissors" ]
, h2 [] [ text "Result: " ]
]
##Hand型を作る
type Hand
= Rock
| Paper
| Scissors
##モデルを書く
先ほど作ったHand型で相手の手と自分の手を定義する
--MODEL--
type alias Model =
{ opponentHand : Hand
, myHand : Hand
}
init : () -> ( Model, Cmd Msg )
init _ =
( Model Rock Rock
, Cmd.none
)
##RandomとHtml.Eventsのインポート
import Html.Events exposing (..)
import Random
Randomはelm install elm/random
でインストール
##1~3のランダムな手を生成するgenHandを作る
--UPDATE--
genHand : Cmd Msg
genHand =
Random.generate NewHand (Random.uniform Rock [Paper, Scissors])
##updateを書く
--UPDATE--
type Msg
= ChoiceRock
| ChoicePaper
| ChoiceScissors
| NewNumber Hand
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
ChoiceRock ->
( { model | myHand = Rock }
, genHand
)
ChoicePaper ->
( { model | myHand = Paper }
, genHand
)
ChoiceScissors ->
( { model | myHand = Scissors }
, genHand
)
NewHand newHand ->
( { model | opponentHand = newHand }
, Cmd.none
)
##ボタンをクリックするとメッセージが送られるようにする
--VIEW--
//... 略
, button [ onClick ChoiceRock ] [ text "Rock" ]
, button [ onClick ChoicePaper ] [ text "Paper" ]
, button [ onClick ChoiceScissors ] [ text "Scissors" ]
//... 略
##勝敗結果を表示する
createResult : Model -> String
createResult model =
case (model.myHand, model.opponentHand) of
(Rock, Rock) ->
"Draw"
(Rock, Paper) ->
"Lose"
(Rock, Scissors) ->
"Win"
(Paper, Rock) ->
"Win"
(Paper, Paper) ->
"Draw"
(Paper, Scissors) ->
"Lose"
(Scissors, Rock) ->
"Lose"
(Scissors, Paper) ->
"Win"
(Scissors, Scissors) ->
"Draw"
またVIEWを以下のように書き換える
--VIEW--
//... 略
h2 [] [ text "Result: " ]
↓
h2 [] [ text ("Result: " ++ (createResult model)) ]
//... 略
##完成したコード
module Main exposing (..)
import Browser
import Html exposing (..)
import Html.Events exposing (..)
import Random
--MAIN--
main : Program () Model Msg
main =
Browser.element
{ init = init
, update = update
, subscriptions = subscriptions
, view = view
}
--MODEL--
type Hand
= Rock
| Paper
| Scissors
type alias Model =
{ opponentHand : Hand
, myHand : Hand
}
init : () -> ( Model, Cmd Msg )
init _ =
( Model Rock Rock
, Cmd.none
)
--UPDATE--
genHand : Cmd Msg
genHand =
Random.generate NewHand (Random.uniform Rock [Paper, Scissors])
type Msg
= ChoiceRock
| ChoicePaper
| ChoiceScissors
| NewHand Hand
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ChoiceRock ->
( { model | myHand = Rock }
, genHand
)
ChoicePaper ->
( { model | myHand = Paper }
, genHand
)
ChoiceScissors ->
( { model | myHand = Scissors }
, genHand
)
NewHand newHand ->
( { model | opponentHand = newHand }
, Cmd.none
)
--subscriptions--
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
--VIEW--
view : Model -> Html Msg
view model =
div []
[ h1 [] [ text "Rock-paper-scissors" ]
, h2 [] [ text "Choice Hand" ]
, button [ onClick ChoiceRock ] [ text "Rock" ]
, button [ onClick ChoicePaper ] [ text "Paper" ]
, button [ onClick ChoiceScissors ] [ text "Scissors" ]
, h2 [] [ text ("Result: " ++ (createResult model)) ]
]
createResult : Model -> String
createResult model =
case (model.myHand, model.opponentHand) of
(Rock, Rock) ->
"Draw"
(Rock, Paper) ->
"Lose"
(Rock, Scissors) ->
"Win"
(Paper, Rock) ->
"Win"
(Paper, Paper) ->
"Draw"
(Paper, Scissors) ->
"Lose"
(Scissors, Rock) ->
"Lose"
(Scissors, Paper) ->
"Win"
(Scissors, Scissors) ->
"Draw"
##動作確認
elm make src/rock-paper-scissors.elm --debug
でindex.htmlが出力される
index.htmlを開いて右下にあるExplore Historyを開く
するとmodelの中身が表示されるのでボタンをクリックし中身が変化することを確認する
##まとめ
勝敗判定の関数はもっといいアイデアがあるはずなので考えてみたい(丸々書き直しになりそうだが)
初めて記事を書いたので構成がめちゃめちゃな気がするので直したい
マサカリ大歓迎なのでよろしくお願いします