如何在Lua中将停止功能称为不停止

时间:2019-07-16 03:00:28

标签: lua scripting

我正忙着阅读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)

1 个答案:

答案 0 :(得分: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变量在我们返回堆栈时停止了现有循环的继续递归。


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

这与for中的addqueen循环有关:<​​/ p>

    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,这是我们第二步原始的for循环):

- 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