在 Elixir 上输出一个简单的棋盘游戏,但变量不是递减的。如何解决这个问题?

Outputting a simple board game on Elixir, but a variable is not decrementing. How to fix this?

我有一个名为 main(row,col) 的函数,它将接受 2 个整数并将它们分别放入 row 和 col 中。然后它将创建一个板的输出,因此 main(2,3) 将创建一个 2 x 3 板。

spaces= row*col 

所以在这种情况下,每次创建单元格时,spaces=6 并且应该减 1。但是它不会这样做。我 运行 时的输出是

 Main.main(2,3)
+---+---+---+
|  6|  6|  6|
|   |   |   |
+---+---+---+
|  6|  6|  6|
|   |   |   |
+---+---+---+

我需要它

 Main.main(2,3)
+---+---+---+
|  6|  5|  4|
|   |   |   |
+---+---+---+
|  3|  2|  1|
|   |   |   |
+---+---+---+

这是我的代码:

defmodule Main do

  def main(row,col) do
    spaces = row*col

    for i <- 0..(row-1) do
      for j <- 0..(col-1) do
        if j == 0 do
          IO.write "+"
        end 

        IO.write "---+"
      end
      IO.puts ""
      columns = col

      for columns <- 1..columns do
        if columns == 1 do
          IO.write "|"
        end

        if spaces < 10 do
          IO.write "  "
          IO.write spaces
          IO.write "|"
        else if spaces < 100 do
          IO.write " "
          IO.write spaces
          IO.write "|"
        end

        if spaces > 99 do
          IO.write spaces
          IO.write "|"
        end
        spaces = (spaces - 1) 
      end
    end
    IO.puts ""
    columns = col
    for columns <- 1..columns do
      if columns == 1 do
        IO.write "|"
      end
      IO.write"   |"
    end

    IO.puts ""
    if i == row-1 do
      botside = col
      for botside <- 1..col do
        if botside == 1 do
          IO.write "+"
        end
        IO.write "---+"
      end
    end
  end
end

end

如您所见,

 spaces =(spaces - 1) 

无论出于何种原因都没有递减。感谢您的时间和帮助。

spaces = (spaces - 1)

被置于推导式中并没有达到您的预期。它将新的局部变量 spaces 声明为最外层的 spaces 减一。这个局部变量 spaces,尽管它与最外层变量同名,但在理解结束时死亡。

整个代码都不是灵丹妙药惯用的,很难在这里提出任何优雅的解决方案。一般来说,在 Elixir 中是要避免状态的。

作为拼凑,您可能会使用:

spaces = spaces + 1 - columns

正如@mudasobwa 指出的那样,很难告诉您如何解决这个问题,因为它从根本上与函数式编程中通常的做法背道而驰。

也就是说,这里有一个示例,说明您可以在 Elixir 中实现递减循环:

 defmodule Test do
   def decrementing_loop(initval) do
         IO.inspect initval
         if (initval > 0) do
           decrementing_loop(initval-1)
         end
   end
 end

除非您可能想将一个函数传递给 decrementing_loop——像这样:

defmodule Test do
  def decrementing_loop(initval, f) do
    f.(initval)
    if (initval > 0) do
      decrementing_loop(initval - 1, f)
    end
  end
end

然后会这样调用:

Test.decrementing_loop(10,&IO.inspect/1)

重点是我实际上并没有修改 initval,而是将当前 initval-1 的新参数传递给函数的递归调用。

综上所述,恕我直言,如果您认真学习 Elixir,那么明智的做法是投资一本好书,而不是通过在这里提出一系列问题来试图蚕食其中的一部分。

首先创建列表是我的意思

rows=3
cols=2
top = rows*cols

labels = Enum.to_list top..1  # [6,5,4,3,2,1]

c = Enum.to_list 1..rows # [1,2,3]
c = List.duplicate c, cols # [[1,2,3],[1,2,3]]
c = List.flatten c   # [1,2,3,1,2,3]

r = Enum.to_list 1..cols # [1,2]
r = List.duplicate r, rows #[[1,2],[1,2],[1,2]]
r = List.flatten r   # [1,2,1,2,1,2]

list = List.zip( [r, c, labels] )

board = list |> Enum.each( fn {r,c,label} -> print_cell r,c, label, rows, cols end)

defp print_cell r,c, label, rows,cols do
 # your conditional cases for each edge case here
end