Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

Herói Duplicado???

Olá, estou com um problema em meu código que parece não ter muito nexo. Ao invés de mover meu herói para qualquer lugar, quantas vezes eu quiser (menos onde há os muros), ele apenas faz uma cópia do herói e limita-me à apenas duas jogadas. O código está abaixo:

require_relative 'ui'

def le_mapa(numero)
    arquivo = "mapa#{numero}.txt"
    texto = File.read arquivo
    mapa = texto.split "\n"
end

def encontra_jogador(mapa)
    caractere_do_heroi = "H"
    mapa.each_with_index do |linha_atual, linha|
        coluna_do_heroi = linha_atual.index caractere_do_heroi
        if coluna_do_heroi
            return [linha, coluna_do_heroi]
        end    
    end    
    #não achei!    
end

def calcula_nova_posição(heroi, direção)
    case direção
        when "W"
            heroi[0] -= 1
        when "S"
            heroi[0] += 1
        when "A"
            heroi[1] -= 1
        when "D"
            heroi[1] += 1
    end    
    heroi
end

def joga(nome)
    mapa = le_mapa 1

    while true
        desenha mapa
        direção = pede_movimento
        heroi = encontra_jogador mapa
        nova_posição = calcula_nova_posição heroi, direção    

        if nova_posição[0] < 0
            next
        end

        if nova_posição[1] < 0
            next
        end

        if nova_posição[0] >= mapa.size
            next
        end

        if nova_posição[1] >= mapa[0].size
            next
        end

        if mapa[nova_posição[0]] [nova_posição[1]] == "X"
            next
        end

        mapa[heroi[0]][heroi[1]] = " "
        mapa[nova_posição[0]] [nova_posição[1]] = "H"
    end
end

def inicia_fogefoge
    nome = da_boas_vindas
    joga nome
end

Já agradeço de antemão a qualquer um que queira tentar ajudar.

Obrigado pela atenção.

4 respostas

Olá Gabriel, tudo bem? Estou sentido falta da função pede_movimento pode enviá-la também? E uma sugestão, em código, não escrevemos palavras utilizando acentuação como temos na nossa língua (PT-BR), ou seja, a boa prática é, ao invés de escrever variáveis como direção ou posição, escrevemos direcao ou posicao.

Abaixo está o código, e muito obrigado pela dica, é que estou tão acostumado que as vezes isso ocorre de forma indireta.

fogefoge.rb:

require_relative 'ui'

def le_mapa(numero)
    arquivo = "mapa#{numero}.txt"
    texto = File.read arquivo
    mapa = texto.split "\n"
end

def encontra_jogador(mapa)
    caractere_do_heroi = "H"
    mapa.each_with_index do |linha_atual, linha|
        coluna_do_heroi = linha_atual.index caractere_do_heroi
        if coluna_do_heroi
            return [linha, coluna_do_heroi]
        end    
    end    
    #não achei!    
end

def calcula_nova_posição(heroi, direção)
    case direção
        when "W"
            heroi[0] -= 1
        when "S"
            heroi[0] += 1
        when "A"
            heroi[1] -= 1
        when "D"
            heroi[1] += 1
    end    
    heroi
end

def joga(nome)
    mapa = le_mapa 1

    while true
        desenha mapa
        direção = pede_movimento
        heroi = encontra_jogador mapa
        nova_posição = calcula_nova_posição heroi, direção    

        if nova_posição[0] < 0
            next
        end

        if nova_posição[1] < 0
            next
        end

        if nova_posição[0] >= mapa.size
            next
        end

        if nova_posição[1] >= mapa[0].size
            next
        end

        if mapa[nova_posição[0]] [nova_posição[1]] == "X"
            next
        end

        mapa[heroi[0]][heroi[1]] = " "
        mapa[nova_posição[0]] [nova_posição[1]] = "H"
    end
end

def inicia_fogefoge
    nome = da_boas_vindas
    joga nome
end

ui.rb:

def da_boas_vindas
    puts "Bem vindo ao Foge-foge"
    puts "Qual é o seu nome?"
    nome = gets.strip
    puts "\n\n\n\n\n\n"
    puts "Começaremos o jogo para você, #{nome}."
    nome
end

def desenha(mapa)
    puts mapa
end

def pede_movimento
    puts "Para onde deseja ir?"
    movimento = gets.strip
end

main.rb

require_relative 'fogefoge'

inicia_fogefoge

Agradeço desde já pela ajuda, Alex.

solução!

Olá Gabriel, tudo bem? Verifiquei o seu código, o problema é que no calcucula_nova_posicao você está usando o próprio heroi, veja:

def calcula_nova_posicao(heroi, direcao)
    case direcao
        when "W"
            heroi[0] -= 1
        when "S"
            heroi[0] += 1
        when "A"
            heroi[1] -= 1
        when "D"
            heroi[1] += 1
    end    
    heroi
end

O correto é que você faça uma cópia do seu heroi para que ele não pegue a referência dele e sim a cópia. Para isso basta utilizar o dup. Então o calcula_nova_posicao fica assim:

def calcula_nova_posicao(heroi, direcao)
    heroi = heroi.dup
    case direcao
        when "W"
            heroi[0] -= 1
        when "S"
            heroi[0] += 1
        when "A"
            heroi[1] -= 1
        when "D"
            heroi[1] += 1
    end    
    heroi
end

Veja que agora, ao invés usar referência do heroi ele faz uma cópia. Mas porque precisamos fazer isso? É justamente para que a posição antiga não seja alterada na função joga, ou seja, quando ele tentar apagar o heroi na posição antiga, mapa[heroi[0]][heroi[1]] = " " precisa manter as informações da posição anterior. Basicamente é por isso que não podemos usar a referência original, só para que não perca a posição anterior do heroi. Estou enviando o fogefoge.rb completo já com as variáveis direcao e posicao modificadas ;)

fogefoge.rb completo

require_relative 'ui'

def le_mapa(numero)
    arquivo = "mapa#{numero}.txt"
    texto = File.read arquivo
    mapa = texto.split "\n"
end

def encontra_jogador(mapa)
    caractere_do_heroi = "H"
    mapa.each_with_index do |linha_atual, linha|
        coluna_do_heroi = linha_atual.index caractere_do_heroi
        if coluna_do_heroi
            return [linha, coluna_do_heroi]
        end    
    end    
    #não achei!    
end

def calcula_nova_posicao(heroi, direcao)
    heroi = heroi.dup
    case direcao
        when "W"
            heroi[0] -= 1
        when "S"
            heroi[0] += 1
        when "A"
            heroi[1] -= 1
        when "D"
            heroi[1] += 1
    end    
    heroi
end

def joga(nome)
    mapa = le_mapa 1

    while true
        desenha mapa
        direcao = pede_movimento
        heroi = encontra_jogador mapa

        nova_posicao = calcula_nova_posicao heroi, direcao  

        if nova_posicao[0] < 0
            next
        end

        if nova_posicao[1] < 0
            next
        end

        if nova_posicao[0] >= mapa.size
            next
        end

        if nova_posicao[1] >= mapa[0].size
            next
        end

        if mapa[nova_posicao[0]] [nova_posicao[1]] == "X"
            next
        end
        mapa[heroi[0]][heroi[1]] = " "
        mapa[nova_posicao[0]] [nova_posicao[1]] = "H"
    end
end

def inicia_fogefoge
    nome = da_boas_vindas
    joga nome
end

Muito obrigado mesmo Alex, o problema foi resolvido. Agradeço muito mesmo, pois estou a tempos tentando resolver isso por conta própria mas sem hesito algum.