如何在Elixir中从地图集中的坐标(如0,0)打印栅格?
我正在学习长生不老药通过建立一个简单的井字游戏。现在我设置它的方法是在棋盘上有玩家选择单元,如如何在Elixir中从地图集中的坐标(如0,0)打印栅格?,elixir,Elixir,我正在学习长生不老药通过建立一个简单的井字游戏。现在我设置它的方法是在棋盘上有玩家选择单元,如{col,row}所以{0,0},{1,2}等等。所有的移动都存储在一个名为turns的地图集中 %TTT{turns: %{x: MapSet.new, o: MapSet.new}, last_player: :player} 我已经完成了基本游戏逻辑的实现,但是我很难尝试构建一个简单的游戏命令行表示,尤其是在显示棋盘的当前状态时。有什么建议吗?对于基于坐标的板,我通常使用{col,row}键将板
{col,row}
所以{0,0}
,{1,2}
等等。所有的移动都存储在一个名为turns的地图集中
%TTT{turns: %{x: MapSet.new, o: MapSet.new}, last_player: :player}
我已经完成了基本游戏逻辑的实现,但是我很难尝试构建一个简单的游戏命令行表示,尤其是在显示棋盘的当前状态时。有什么建议吗?对于基于坐标的板,我通常使用{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
对于基于坐标的板,我通常使用{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
@史蒂夫·帕伦(Steve Pallen)给出了一个很好的回答,但我想指出使用a而不是常规模块的好处:它允许使用handle\u 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
TictaToe使用该系统的一个例子是可用的。@Steve Pallen给出了一个很好的答案,但是我想指出使用一个而不是常规模块的好处:它将允许使用handle\u 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
使用该系统的tictactoe示例可用