**关闭。**此题需要debugging details。目前不接受答复。
编辑问题以包含desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将帮助其他人回答这个问题。
4天前关闭。
截至4天前,社区正在审查是否重新开放此问题。
Improve this question
我正在学习用Ruby创建一个小游戏的教程,突然遇到了一个我无法理解的bug。当我仔细查看时,我意识到错误发生在fogefoge.rb
的第51行,调用nova_posicao = calcula_nova_posicao heroi, direcao
。
在这一点上的教程,英雄“H”应该能够移动与关键“ASDW”。我注意到第49行heroi = encontra_jogador mapa
中的数组heroi
被更改了,这在应用程序中引入了bug。之后,我创建了另一个名为heroi2
的变量,代码工作正常。
为什么当我调用fogefoge.rb
的第51行时,数组正在改变?
从我在Rubydocs上阅读到的内容来看,我只是不明白为什么会发生这种情况。
File "main.rb"
require_relative "fogefoge"
inicia_fogefoge
File "mapa1.txt"
XXXXX
X H X
X X X
X X X
X X
X
XXX
X
X F X
XXXXX
File "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"
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
#File "fogefoge.rb"
require_relative "ui"
def le_mapa(numero)
arquivo = "mapa#{numero}.txt"
texto = File.read(arquivo)
mapa = texto.split "\n"
# p mapa
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
end
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
def posicao_valida?(mapa, posicao)
linhas = mapa.size
colunas = mapa[0].size
estourou_linhas = posicao[0] < 0 || posicao[0] >= linhas
estourou_colunas = posicao[1] < 0 || posicao[1] >= colunas
if estourou_linhas || estourou_colunas
return false
end
if mapa[posicao[0]][posicao[1]] == "X"
return false
end
true
end
def joga(nome)
mapa = le_mapa 1
while true
desenha mapa
direcao = pede_movimento
heroi = encontra_jogador mapa
#heroi2 = encontra_jogador mapa
nova_posicao = calcula_nova_posicao heroi, direcao #At this call
if !posicao_valida? mapa, nova_posicao
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
我原以为“H”会在空白处移动,但“H”却向几个方向重复
输出:
bem vindo ao Foge-foge
Qual é o seu nome?
marcos
Começaremos o jogo para você, marcos
XXXXX
X H X
X X X
X X X
X X
X
XXX
X
X F X
XXXXX
Para onde deseja ir?
d
XXXXX
X H X
X X X
X X X
X X
X
XXX
X
X F X
XXXXX
Para onde deseja ir?
D
XXXXX
X HHX
X X X
X X X
X X
X
XXX
X
X F X
XXXXX
Para onde deseja ir?
S
XXXXX
X HHX
X X X
X X X
X X
X
XXX
X
X F X
如果你取消注解第50行的第二个引用,然后将第51行改为nova_posicao = calcula_nova_posicao heroi2, direcao
,那么代码就可以工作了。
1条答案
按热度按时间ih99xse11#
您的
calcula_nova_posicao
实现更改了传递的heroi
数组,然后返回它。因此,nova_posicao
和heroi
在调用后将是相同的(不仅包含相同的值,而且都引用相同的对象)。这里有一个关于如何验证这一点的快速示例:(
equal?
检查两个对象是否是同一个对象)为什么当我调用一个函数传递一个引用到一个数组时,数组在ruby中发生了变化?
这是Ruby中非常基本的行为。有些对象是可变的,即您可以通过向这些对象发送某些消息(所谓的 * 破坏性方法 *)来更改它们。可变对象的例子有字符串、散列和数组。不管(破坏性)信息是如何或在哪里发送的,也不管是谁发送的。一旦接收到,对象将改变自身。
下面是两个变量
a
和b
引用同一个对象的例子,一个字符串。如果你向字符串发送upcase!
消息,它将大写字符,两个变量都将反映这种变化:(因为它们仍然引用现在已经改变的相同对象)这同样适用于方法参数。如果你将一个可变对象传入一个方法,该方法就可以改变它,就像你在该方法之外所做的一样:
回到你的问题。您可能希望
calcula_nova_posicao
1)返回一个 new 数组,2)保持传入的数组不变。后者对于从Map中清除当前H
非常重要。但一般来说,不更改方法中的参数也是一个好主意,因为这可能会导致意外的结果,并且很难找到错误。下面是一个实现:
下面是另一个使用数组分解的例子:
你可以考虑为你的方法编写测试。