- OverView
さて、番外編です。
ゲームのプログラミングだと、
初期化 -> ゲーム本体(無限ループ) -> ゲーム終了処理
なんて処理をするじゃないですか、あれ、どう書くべきかってお話です。
Discordで教わったので、まとめておこうとかと思いまして。
2 解説
2.1 まずは、オーソドックスに再帰呼び出し
はいはい、最近気に入っております、再帰呼び出しであります。
LISPとかElixirって、再帰やりやすいしね…と言うわけで行ってみましょう。
defmodule InfiniteLoop do
def loop do
IO.puts("This loop will run forever")
loop() <----ここに注目してください。
end
end
InfiniteLoop.loop()
関数loopから自分を呼び出しております。
2.2 Streamを利用する
Elixirの遅延評価ライブラリ、Streamで作ります。
目的は、下記の二つの関数を使うためですね。
Stream.cycle/1: 無限に繰り返されるストリームを作成します。
Stream.unfold/2: 初期状態と次の状態を生成する関数を使用してストリームを作成します。
それぞれ、例を見てみましょう。
2.2.1 Stream.cycle
流れを説明しておくと、Stream.cycle(["Looping..."])でストリームを作成、その一つ一つに
このStreamを、それぞれ(Stream.each)を使用し、Stream.run()で実行すれば良いだけです。
Stream.cycle(["Looping..."])
|> Stream.each(&IO.puts/1)
|> Stream.run()
2.2.2 Stream.unfold
Stream.unfold/2は、初期状態と次の状態を生成する関数を受け取り、ストリームを生成するための関数です。
使い方は先ほど同じ、ここでは、無名関数を作成して、そいつを無限にくりかえしております。
ここで、この関数がnilを返せば、そこで終了します。
まずは無限ループ
Stream.unfold(0, fn state ->
IO.puts("This loop will run forever with state: #{state}")
{state, state + 1}
end)
|> Stream.run()
戻り値のstateが10以上になったら、nilを返す様にしてみましょうか。
iex(2)> Stream.unfold(0, fn state ->
...(2)> if state < 10 do
...(2)> IO.puts("Current state: #{state}")
...(2)> {state, state + 1}
...(2)> else
...(2)> nil
...(2)> end
...(2)> end)
#Function<64.118167795/2 in Stream.unfold/2>
iex(3)> |> Enum.to_list()
Current state: 0
Current state: 1
Current state: 2
Current state: 3
Current state: 4
Current state: 5
Current state: 6
Current state: 7
Current state: 8
Current state: 9
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3. まとめ
今の目的はゲームなので、Stream.unfoldが良いのかなと感じております。
処理の流れが「初期化 -> ゲーム本体(無限ループ) -> ゲーム終了処理」ですからね。
それでは、スカッシュゲームを書くとしますか…早く書け>俺