如何防止renderBlocks()函数进入无限循环?

-- 这是Minecraft,但是是2D和Lua。

-- **************************************
-- ID 0:Air
-- ID 1:Stone
-- ID 2 Logs
-- ID 3:Leaves
-- ID 4:Planks
-- ID 5:工作台
-- ID 6:熔炉
-- ID 7:玩家位置探测器块
-- **************************************

blockTable = { -- 存储所有块
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6}
}
tableRow = 1 --块渲染指针在Y轴上的值
tableColumn = 1 --块渲染指针在X轴上的值
runOnce = true --仅仅运行一个循环
tickNum = 0 --自启动以来的滴答数
function renderBlock(X, Y, K) --渲染一个块
    if K == 1 then --如果块ID== 1,则绘制一个灰色正方形
        screen.setColor(100,100,100)
        print(X, Y)
        screen.drawRectF(X, Y, 8, 8)
    end
    if K == 6 then --如果块ID ==绘制灰色正方形
        screen.setColor(100,100,100)
        screen.drawRectF(X, Y, 8, 8)
    end
end

function renderBlocks() --渲染所有块(以光栅模式扫描块表)
        while runOnce == true --运行此代码一次
    do
    while #blockTable >= tableRow
    do
        while #blockTable[tableRow] >= tableColumn
        do
            print("TC " .. tableColumn)
            tableColumn = tableColumn + 1

            blockID = blockTable[tableRow][tableColumn]
            renderBlock(tableRow, tableColumn, blockID)
            if tableColumn > #blockTable[tableRow] then tableColumn = 1 end
        end
        runOnce = false
    end
        print("TR " .. tableRow)
        tableRow = tableRow + 1
    end
end

function onTick()
    print("Tick! Tick count: " .. tickNum) --打印当前滴答,以及说有一个滴答
    tickNum = tickNum + 1
end

function onDraw()
    while runOnce == true --运行此代码一次
    do
    renderBlocks()
    runOnce = false
    end
end

这是我在框架IDE中的代码:链接

我不知道为什么会出现这种情况,我感到迷茫。

点赞
用户14979083
用户14979083

在遍历表格时,使用for循环比使用while或repeat循环更好,因为后者更难理解和修复错误。

如果你想获取表格中的索引(即表格中的数字)和相关的值,则使用for index,value in ipairs(yourtable) do,如果想获取键(通常是作为值的键使用的字符串:yourTable ["key"] = 0)和与之关联的值,则使用for key,value in pairs(yourtable) do

for row,innerTable in ipairs(blockTable) do
    for col,value in ipairs(innerTable) do
        print("TC " .. col)
        blockID = value
        renderBlock(row, col, blockID)
    end
end

最后一个语句应该放在你的renderBlock函数中。但是这个while循环不是很好。如果它只需要执行一次,就不要把它放在循环中!

此外,更好的代码缩进能够更快地了解正在发生的事情。在处理不同问题的代码块之间添加一些空格也会有所帮助。

编辑:因此,你的函数应该像这样:

function renderBlocks()
    if runOnce then
        runOnce = false
        for row,innerTable in ipairs(blockTable) do
            for col,value in ipairs(innerTable) do
                blockID = value
                renderBlock(row, col, blockID)
            end
        end
    end
end
2021-04-21 19:54:18
用户7396148
用户7396148

您的 renderBlocks() 函数存在几个问题:

function renderBlocks()
  while runOnce == true do
    while #blockTable >= tableRow do
      while #blockTable[tableRow] >= tableColumn do
        print("TC " .. tableColumn)
        tableColumn = tableColumn + 1

        blockID = blockTable[tableRow][tableColumn]
        renderBlock(tableRow, tableColumn, blockID)
        if tableColumn > #blockTable[tableRow] then
          tableColumn = 1
        end
      end
      runOnce = false
    end
    print("TR " .. tableRow)
    tableRow = tableRow + 1
  end
end

首先,我们可以看一下最内层的循环。在这里,我们有一个与循环相关的问题,以及如何增加问题。

while #blockTable[tableRow] >= tableColumn do
  print("TC " .. tableColumn)
  tableColumn = tableColumn + 1 -- 在此处增加

  blockID = blockTable[tableRow][tableColumn]
  renderBlock(tableRow, tableColumn, blockID)
  if tableColumn > #blockTable[tableRow] then
    tableColumn = 1 -- 在此处重置
  end
end

在循环体中,您执行了 tableColumn = tableColumn + 1,稍后在相同的循环体中,您执行了 if tableColumn > #blockTable[tableRow] then tableColumn = 1 end,因此当 tableColumn 增加到会结束循环的值时,我们将它重置为 1,从而防止循环结束。

现在让我们再来看一下外层的循环。这里我们从不增加 tableRow,它仅在此循环结束后增加,因此循环不可能结束。

while #blockTable >= tableRow do
    while #blockTable[tableRow] >= tableColumn do
        ...
    end
    runOnce = false
end

我认为您打算将

print("TR " .. tableRow)
tableRow = tableRow + 1

放在此循环内而不是外面。

2021-04-21 20:35:30
用户3342050
用户3342050

少了一些区块定义。否则你可能看不到结果

function renderBlock(X, Y, blockID)  --  渲染一个方块
  if blockID == 0 then  --  空气
    --  screen.setColor(10, 20, 220, 0) -- 是否有 alpha 通道?
    screen.setColor(10, 20, 220)

  elseif blockID == 1 then  --  石头
    screen.setColor(100, 100, 100)

  elseif blockID == 2 then  --  木头
    screen.setColor(200, 50, 50)

  elseif blockID == 3 then  --  树叶
    screen.setColor(20, 220, 40)

  elseif blockID == 4 then  --  木板
    screen.setColor(180, 30, 10)

  elseif blockID == 5 then  --  工作台
    screen.setColor(180, 30, 10)

  elseif blockID == 6 then  --  火炉
    screen.setColor(100, 100, 100)

  elseif blockID == 7 then  --  玩家检测
    screen.setColor(220, 30, 30)
  end

  print(X, Y)
  screen.drawRectF(X, Y, 8, 8)
end

循环 for 很容易。设置起始条件和最终完成条件,然后让它自动运行。

function renderBlocks() -- 渲染所有块(以栅格方式扫描 blockTable)
  for row = 1,  #blockTable do
    for col = 1, #blockTable[row] do
      print("TC " ..col)
      local blockID = blockTable[row][col]
      renderBlock(row, col, blockID)
    end
    print("TR " ..row)
  end
end

你可能不需要 runOnce。如果你发现你需要用到它,那就去吧,但在嵌套循环中不需要。

function onDraw()
  renderBlocks()
end
2021-04-22 01:06:43