Lua / Love — мой печатный текст продолжает исчезать

#for-loop #lua #love2d

#для цикла #lua #love2d

Вопрос:

Я создаю игру палача. Прямо сейчас мне нужно, чтобы, если пользователь нажимает клавишу буквы, которая находится в заданном слове, она отображается на экране в правильном порядке. Например: когда слово «word», нажатие «w» покажет w _ _ _ на экране. Затем, если затем нажать d, будет указано w _ _ d . Однако этого не происходит. Вместо этого он показывает _ _ _ d, когда d нажимается после w и стирает w с экрана. Я думаю, что моя проблема может быть связана с моим циклом for в love.draw или чем-то в ключе.нажат. Я очень озадачен, поэтому буду признателен за любую помощь! Я скопировал love.keypressed , love.draw и другие важные переменные ниже в том порядке, в котором они вызываются в моем коде.

Код:

 wrongCount=0
randomWord = "word"
wordSpots = {}
wordList = {}
numBlanks = string.len(randomWord)
Ltext = " "

function love.keypressed(key)
    pressed = key
    if key == "escape" then --one of the letters in the word
        love.event.quit()
    elseif key == "a" or key == "b" or key == "c" or key == 'd' or key == "e" or key == 'f' or key == 'g' or key == "h" or key == "i" or key == 'j' or key == 'k' or key == 'l' or key == 'm' or key == 'n' or key == "o" or key == "p" or key == 'q' or key == 'r' or key == 's' or key == 't' or key == 'u' or key == "v" or key == "w" or key == 'x' or key == 'y' or key == 'z' then
        Ltext = pressed
--guess function
        LrandomWord = string.lower(randomWord) --ensure no problems with capitalization
        letterWrong=0
        wordSpots = {}
        for i=1, #LrandomWord, 1 do
            c = LrandomWord:sub(i,i)
            if Ltext == c then
                Cguess=Ltext
                table.insert(wordSpots, i)
            else
                letterWrong= letterWrong   1
            end
        
        end
        if letterWrong == #LrandomWord then
            wrongCount = wrongCount   1
        end
    end
end

function love.draw()
    push:apply('start')
    love.graphics.clear(40/255,45/255,52/255,255/255)
    love.graphics.printf(Ltext, 0, 80, VIRTUAL_WIDTH 30, "center")
    love.graphics.printf("Welcome to Hardcore Hangman!", 0, 10, VIRTUAL_WIDTH, "center")

    --hanging pole
    love.graphics.rectangle('fill', VIRTUAL_WIDTH/2 -80, VIRTUAL_HEIGHT/2  40, 160, 5) --base
    love.graphics.rectangle('fill', VIRTUAL_WIDTH/2 - 60, VIRTUAL_HEIGHT/2 - 80, 5, 120) --pole
    love.graphics.rectangle('fill', VIRTUAL_WIDTH/2-60, VIRTUAL_HEIGHT/2 -80, 45, 5) --upper base
    love.graphics.rectangle('fill', VIRTUAL_WIDTH/2 - 15, VIRTUAL_HEIGHT/2 -80, 5, 15) -- small down pole
    
    for i=1, 4,1 do
        love.graphics.rectangle('fill', VIRTUAL_WIDTH/2-4, VIRTUAL_HEIGHT/2 - 15*i, 20,5)
    end
        -- creates blanks for guessing
    blankPos = VIRTUAL_WIDTH/6
    for i=1, #randomWord,1 do
        love.graphics.rectangle('fill', blankPos, VIRTUAL_HEIGHT/2  80, 25, 5)
        blankPos= blankPos   35
    end
    push:apply('end')
    tableLen = #wordSpots
    love.graphics.printf(tableLen, 0, 80, VIRTUAL_WIDTH 30, "center")
    for i=1, tableLen, 1 do
        spot = wordSpots[i]
        love.graphics.print(Cguess, blankPos*spot   10, VIRTUAL_HEIGHT/2  80)
    end
    
end
 

Комментарии:

1. Каждый раз, когда вы вызываете love.keypressed , вы устанавливаете wordSpots = {} , стирая все предыдущие достижения. Удалите эту строку из функции.

2. Изменил несколько вещей, чтобы заставить эти буквы выстраиваться в линию — github.com/doyousketch2/hangman — Я напечатаю объяснение сегодня днем.

Ответ №1:

Здесь много чего нужно распаковать. Вкратце:

     elseif key == "a" or key == "b" -- etc.
        Ltext = pressed -- <<< overwrites Ltext
--guess function
        LrandomWord = string.lower(randomWord) --ensure no problems with capitalization
        letterWrong=0
        wordSpots = {}  -- <<< clears wordSpots
 

Вероятно, это (часть) вашей проблемы. Глядя дальше, кажется, вы решили переписывать wordSpots каждый раз, потому что чуть ниже вы используете

             if Ltext == c then
                Cguess=Ltext
                table.insert(wordSpots, i)
            else
 

несмотря wordSpots на то, что он не «похож на массив». Вы также не присваиваете ему значение для вставки, поэтому table.insert переместите все вправо i на одно место дальше вправо, а затем вставьте nil — обе вещи, которые вам не нужны. Вы, наверное, просто хотите сказать wordSpots[i] = Ltext .

Далее, в функции рисования:

tableLen = #wordSpots — учитывая, что вы задаете только отдельные значения wordSpots , wordSpots не является массивом и не имеет реальной длины — поэтому в большинстве случаев вы получите 0. Если вы хотите использовать # , вы должны инициализировать wordSpots с false помощью во всех слотах — например.

 randomWord = "word"
wordSpots = {}
for i = 1, #randomWord do  wordSpots[i] = false  end
 

но в качестве альтернативы (это, вероятно, лучший подход) вы могли бы выполнить итерацию до #randomWord вместо #wordSpots или (еще один подход) выполнить итерацию pairs( wordSpots ) , если вы просто хотите получить все (position,letter) пары из wordSpots (они могут встречаться в любом порядке! но здесь все должно быть в порядке.)

Надеюсь, после того, как вы разобрались со всем этим, это должно сработать. (Но это действительно предположение, потому что я не могу следовать вашему коду… Кроме того, я не могу запустить ваш код, потому что некоторые части, похоже, отсутствуют. Что касается вашего следующего вопроса, постарайтесь (а) сделать его работоспособным, (б) постарайтесь сохранить как можно больше материала local (иначе вы рискуете жутким (взаимодействующим) действием на расстоянии) и (в) удалить материал, который не имеет значения — например, рисование арки. Также есть много «шума», который вы могли бы сначала убрать — например for i=1, tableLen, 1 do , не требуется ,1 в конце — по умолчанию используются шаги размером 1 — и удаление всех этих дополнительных символов облегчит понимание того, что на самом деле имеет значение. Глядя на весь пример кода, похоже, что в какой-то момент вы добавили ошибку, которая вас смутила, а затем добавили все больше и больше вещей сверху, чтобы попытаться исправить это, и просто сделали это еще более запутанным. Идите в другом направлении, удаляйте материал, пока не увидите, почему что-то (не) работает.)


Совершенно несвязанное замечание по стилю:

Вы, наверное, заметили, как elseif key == "a" or key == "b" or key == "c" or … «немного» неудобно.

Есть хороший шаблон для обработки входных данных:

 typed_letter = function( key )
     -- body of the elseif goes here
end

keys = {
  escape = love.event.quit,
}
for key in ("abcdefghijklmnopqrstuvwxyz"):gmatch "." do -- copy to a thru z
  keys[key] = typed_letter
end

function love.keypressed( key )
  local action = keys[key]
  if action then  return action( key )  end
end
 

Это превращает статическую elseif цепочку, написанную вручную, в динамическую структуру данных, которую легко сгенерировать или изменить. (Например, после того, как вы нажали букву, вы можете отключить ее, чтобы нажатие в другой раз ничего не дало — просто удалив ее из таблицы; конечно, в следующем раунде вам придется заново скопировать слоты обратно. Вы также можете заменить всю таблицу другой, если добавите что-то вроде меню, и вам не нужно ничего менять love.keypressed .)


Ваше соглашение об именах также сбивает с толку. Что означает префикс ‘L’? Для чего ‘C’? Если вы хотите использовать «пробелы в именах», вы можете просто использовать реальные таблицы!(И тогда вы также можете дать им лучшие имена …)