Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Não entendo o porque da aparição do undefined method

/fogefoge2.rb:38:in `posicao_valida?': undefined method `[]' for nil:NilClass (NoMethodError)
    from /home/oteti/Alura/3Ruby /fogefoge2.rb:71:in `posicoes_validas_a_partir_de'

Eu resolvi meu problema colocando "X" no final do mapa, assim fechando a borda final do mapa. Mas estou sem entender do porque desse erro ter ocorrido!

require_relative 'ui2'

def le_mapa(mapa)
  arquivo = "mapa2.txt"
  texto = File.read(arquivo)
  mapa = texto.split("\n")
end

def movimento_do_heroi(mapa)
  caracter_do_heroi = "H"
  mapa.each_with_index do |linha_atual, linha|
    coluna_do_heroi = linha_atual.index caracter_do_heroi
    if coluna_do_heroi
      return [linha, coluna_do_heroi]
    end
  end
end

def calculando_nova_posicao(direcao, heroi)
heroi = heroi.dup
movimentos = {
  "W" => [-1,0],
  "S" => [1,0],
  "A" => [0,-1],
  "D" => [0,1]
}
  movimento = movimentos[direcao]
  heroi[0] += movimento[0]
  heroi[1] += movimento[1]
  heroi
end

def posicao_valida?(mapa, nova_posicao)
linha = mapa.size
coluna = mapa[0].size
estourou_linhas = nova_posicao[0] < 0 || nova_posicao[0] >= linha
estourou_colunas = nova_posicao[1] < 0 || nova_posicao[1] >= coluna
valor_local = mapa[nova_posicao[0]][nova_posicao[1]]
  if valor_local == "X" || valor_local == "F"
      return false
  end
  if estourou_linhas || estourou_colunas
    return false
  end
  true
end

def move_fantasmas(mapa)
  caracter_do_fantasma = "F"
  mapa.each_with_index do |linha_atual, linha_do_fantasma|
    linha_atual.chars.each_with_index do |caracter_encontrado, coluna_do_fantasma|
      eh_fantasma = caracter_encontrado == caracter_do_fantasma
      if eh_fantasma
        move_fantasma mapa, linha_do_fantasma, coluna_do_fantasma
      end
    end
  end
end

def move_fantasma (mapa,linha_do_fantasma,coluna_do_fantasma)
  posicoes = posicoes_validas_a_partir_de mapa, [linha_do_fantasma, coluna_do_fantasma]
  return if posicoes.empty?
  nova_posicao = posicoes[0]
  mapa[linha_do_fantasma][coluna_do_fantasma] = " "
  mapa[nova_posicao[0]][nova_posicao[1]] = "F"
end

def posicoes_validas_a_partir_de(mapa, nova_posicao)
  posicoes = []
  baixo = [nova_posicao[0] + 1,nova_posicao[1]]
  if posicao_valida? mapa, baixo
    posicoes << baixo
  end
  direita = [nova_posicao[0],nova_posicao[1] + 1]
  if posicao_valida? mapa, direita
    posicoes << direita
  end
  cima = [nova_posicao[0] - 1,nova_posicao[1]]
  if posicao_valida? mapa, cima
    posicoes << cima
  end
  esquerda = [nova_posicao[0],nova_posicao[1] - 1 ]
  if posicao_valida? mapa, esquerda
    posicoes << esquerda
  end
  posicoes
end

def jogo(nome)
mapa = le_mapa mapa
  while true
    desenha_mapa mapa
    direcao = pede_movimento
    heroi = movimento_do_heroi mapa
    nova_posicao = calculando_nova_posicao direcao, heroi
    if !posicao_valida? mapa, nova_posicao
      next
    end
    mapa[heroi[0]][heroi[1]] = " "
    mapa[nova_posicao[0]][nova_posicao[1]] = "H"
    move_fantasmas mapa
  end
end

def inicia_fogefoge2
  nome = da_boas_vindas
  jogo nome
end

desde já, agradeço!

1 resposta
solução!

Olá Otávio,

a mensagem de erro indica que não há o método [] para o objeto nil, ou seja, provavelmente o elemento mapa[nova_posicao[0]] do mapa[nova_posicao[0]][nova_posicao[1]] é nil. Assim, quando vamos acessar sua posição, seria como estivéssemos fazendo nil[nova_posicao[1]].

O motivo disso provavelmente é que você está checando se estourou as linhas e as colunas apenas depois de ter buscado a posição no seu mapa.

Para resolver isso, você pode colocar a checagem do estouro antes, assim:

def posicao_valida?(mapa, nova_posicao)
    linha = mapa.size
    coluna = mapa[0].size
    estourou_linhas = nova_posicao[0] < 0 || nova_posicao[0] >= linha
    estourou_colunas = nova_posicao[1] < 0 || nova_posicao[1] >= coluna
    if estourou_linhas || estourou_colunas
        return false
    end
    valor_local = mapa[nova_posicao[0]][nova_posicao[1]]
    if valor_local == "X" || valor_local == "F"
      return false
    end

    true
end

Eu não consegui executar o programa aqui, porque tem outros arquivos, ui.rb, mapa2.txt, etc.. Testa aí e me diz se deu tudo certo!

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software