【问题标题】:How to stop function being called non stop in lua如何停止在lua中不间断地调用函数
【发布时间】:2019-11-24 17:32:05
【问题描述】:

我正忙于阅读 lua 第 4 版书中的编程,而我正在努力阅读第二章。该程序实质上打印了一个带有 8 个皇后的棋盘,它们的放置方式使它们都不能互相攻击。我正在努力弄清楚为什么它会多次打印电路板。

我已经一步一步地检查了代码,一旦打印解决方案完成了第一块板的打印,我认为它会结束函数然后跳回主程序,但由于某种原因它一直在循环。我对 lua 也很陌生,刚从 C 语言学习,所以还习惯了。

它输出的其中一个板的图像。 X 是皇后 - https://ibb.co/KsT3R8X

N = 8 -- board size

-- check whether position (n,c) is free from attacks
function isplaceok (a, n, c)
    for i = 1, n - 1 do -- for each queen already placed
        if (a[i] == c) or -- same column?
        (a[i] - i == c - n) or -- same diagonal?
        (a[i] + i == c + n) then -- same diagonal?
            return false -- place can be attacked
        end
    end
    return true -- no attacks; place is OK
end

-- print a board
function printsolution (a)
    for i = 1, N do -- for each row
        for j = 1, N do -- and for each column
            -- write "X" or "-" plus a space
            io.write(a[i] == j and "X" or "-", " ")
        end
        io.write("\n")
    end
    io.write("\n")
end

-- add to board 'a' all queens from 'n' to 'N'
function addqueen (a, n)
    if n > N then -- all queens have been placed?
        printsolution(a)
    else -- try to place n-th queen
        for c = 1, N do
            if isplaceok(a, n, c) then
                a[n] = c -- place n-th queen at column 'c'
                addqueen(a, n + 1)
            end
        end
    end
end

-- run the program
addqueen({}, 1)

【问题讨论】:

  • 您能否将代码复制/粘贴到您的问题正文中。这使人们更容易将其放入调试环境中。如果他们必须从图像中编写代码,这通常意味着您将获得更少的参与度和扩展答案。
  • 抱歉,我会粘贴它。我没有这样做的唯一原因是,当我从 pdf 中复制它时,它看起来不那么整洁。
  • 我添加了代码

标签: lua scripting


【解决方案1】:

程序正在打印 8x8 棋盘的所有 92 种可能的解决方案。 这可能是意图,所以它似乎工作正常。

要在找到 1 个解决方案后停止,我们可以在程序中添加一个变量 found

local found = false

-- print a board
function printsolution (a)
    for i = 1, N do -- for each row
        for j = 1, N do -- and for each column
            -- write "X" or "-" plus a space
            io.write(a[i] == j and "X" or "-", " ")
        end
        io.write("\n")
    end
    io.write("\n")
    found = true
end

-- add to board 'a' all queens from 'n' to 'N'
function addqueen (a, n)
    if n > N then -- all queens have been placed?
        printsolution(a)
    else -- try to place n-th queen
        for c = 1, N do
            if isplaceok(a, n, c) and found == false then
                a[n] = c -- place n-th queen at column 'c'
                addqueen(a, n + 1)
            end
        end
    end
end

这个found 变量在我们向上移动堆栈时停止现有循环的继续递归。


现在为什么这段代码会这样工作,所有的解决方案都是从哪里来的?

这与addqueen 中的for 循环有关:

    for c = 1, N do
        if isplaceok(a, n, c) then
            a[n] = c
            addqueen(a, n + 1)
        end
    end

for 循环的每个循环都通过递归调用addqueen 将代码发送得更深。堆栈永远不会比 9 更深,因为这是N 设置的限制 114 次调用addqueen 后的第一个解决方案是:

X - - - - - - - 
- - - - X - - - 
- - - - - - - X 
- - - - - X - - 
- - X - - - - - 
- - - - - - X - 
- X - - - - - - 
- - - X - - - - 

第 5 个解决方案是我们第一次回到原来的调用 addqueen,你可以看到第一个 X 已经从 1x1 移动到 1x2(n=1 c=2,我们原来的第二步为循环):

- X - - - - - - 
- - - X - - - - 
- - - - - X - - 
- - - - - - - X 
- - X - - - - - 
X - - - - - - - 
- - - - - - X - 
- - - - X - - - 

最后我们调用addqueen 1952 次让程序检查所有可能的解决方案。

您可以调整代码以打印深度值,以便更好地了解程序运行时堆栈的外观:

-- add to board 'a' all queens from 'n' to 'N'
function addqueen (a, n)
    print(n .. "↓")
    if n > N then -- all queens have been placed?
        printsolution(a)
    else -- try to place n-th queen
        for c = 1, N do
            if isplaceok(a, n, c) then
                a[n] = c -- place n-th queen at column 'c'
                addqueen(a, n + 1)
            end
        end
    end
    print(n - 1 .. "↑")
end

【讨论】:

  • 非常感谢您的回答,对我理解这个问题有很大帮助。我正试图做这样的事情,但正在努力找出所有解决方案的来源,而您的回答非常好!
  • 我是 lua 的新手,但仍然习惯于基本的东西,以及事物的外观与 c 中的等价物。有一段代码“a[n] = c”,我只是想确保我理解它的作用。是说将 c 分配给名为 a 的数组中的第 n 部分吗?
  • @ExileVoid a[n] = cc 分配给表a 中的键n。在 lua 中,一个表有 2 个部分,一个数组部分和一个哈希部分。数组部分仅在您执行a = {'a', 'b', 'c'} 之类的操作时定义,如果您执行a[1] = 'a',它将进入哈希部分,直到调整表大小并再次评估数组部分。
  • 非常小的注释:found == false 写成not found 可能更好。
  • @val not foundfound = falsefound = nil 更接近found ~= true 都有效,这主要是我个人偏好在 lua 中使用错误检查明确跨度>
猜你喜欢
  • 2011-10-13
  • 1970-01-01
  • 2019-06-28
  • 1970-01-01
  • 2012-01-11
  • 1970-01-01
  • 2014-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多