我正在通过构建一个简单的井字游戏来学习Elixir。现在,我设置的方式是将棋盘上的玩家选择单元格设置为{col, row}
,因此{0, 0}
,{1, 2}
等将所有移动存储在{{1 }}称为转弯。
MapSet
我已经完成了基本的游戏逻辑,但是我很难建立一个简单的游戏命令行表示,特别是在显示棋盘的当前状态时。有什么建议吗?
答案 0 :(得分:1)
对于基于坐标的板,我通常使用{col,row}键将板创建为地图。
这是具有打印功能的示例板:
defmodule Ttt do
def new_board do
for col <- 1..3, row <- 1..3, into: %{}, do: {{col, row}, " "}
end
def put(board, {col, row}, val) do
put(board, col, row, val)
end
def put(board, col, row, val), do: Map.put(board, {col, row}, val)
def fill(board, list, which) do
Enum.reduce(list, board, fn point, acc -> put(acc, point, which) end)
end
def fill_example_1(board) do
xs = [{1, 1}, {2, 2}, {3, 3}]
ys = [{2, 1}, {3, 1}, {1, 2}]
board
|> fill(xs, "X")
|> fill(ys, "O")
end
def print(board) do
for row <- 1..3 do
for col <- 1..3 do
" " <> board[{col, row}]
end
|> Enum.join(" |")
end
|> Enum.join("\n---+---+---\n")
|> IO.puts()
end
def run do
new_board()
|> fill_example_1()
|> print
end
end
输出:
iex(2)> Ttt.run()
X | O | O
---+---+---
O | X |
---+---+---
| | X
:ok
答案 1 :(得分:1)
@Steve Pallen提供了一个很好的答案,但是我想指出使用GenServer
而不是常规模块的好处:它将允许使用handle_info
回调来显示面板。长生不老药的这一功能具有许多优点:
GenServer
。下面的代码可以使您了解如何执行此操作:
defmodule Tictactoe do
use GenServer
def start_link(opts), do: GenServer.start_link(__MODULE__, :ok, opts)
def init(:ok) do
schedule_work()
{:ok, state}
end
# ...
# game code + print function defined in Steve Pallen's answer
# ...
def handle_info(:work, state) do
print(state) # use function defined by Steve Pallen above
schedule_work()
{:noreply, state}
end
# function used by the callback to refresh display every 100ms
defp schedule_work(), do: Process.send_after(self(), :work, 100)
end
here提供了使用该系统的针线虫的示例。