Find 方法从数组中返回错误 object?

Find method is returning wrong object from array?

我正在为基于文本的冒险游戏开发 Ruby 项目,在尝试使用 Ruby 中的 'find' 方法时遇到了问题。

我有一个位置 class,所有位置均从中实例化。每个位置都有一组两个坐标,([x, y] = [1, 1]),玩家也有自己的一组坐标来存储他们实际所在的位置。

class方法&初始化方法

def self.findLocation(coord, attributeToPrint)
    puts coord.inspect
    puts @@finder.find { coord }.inspect
  end

def initialize(newTitle, newDescription, newCoord)
    @title = newTitle
    @description = newDescription
    @coordinate = newCoord

    @@finder << self
  end

我想做的是将所有位置存储在一个数组中,并有一个 class 方法通过使用 [=54= 的 find 方法打印出位置的标题和描述] 与玩家匹配坐标的位置。我目前使用的方法是在 coord 参数中传递玩家的坐标,并使用 find 方法检查数组(其中包含所有位置 object)的坐标。

我发现了很多与此方法相关的问题,但在这些问题上找到的任何解决方案都没有成功,我自己的任何解决方案也没有成功。如果我尝试使用诸如 @coordinate == coord 之类的比较语句,该方法将简单地 return nil 和我当前的版本 returns 和 object,但只有 object 是数组中的第一个,而不是 return 具有匹配 @coordinate 属性的位置。

对于此问题的任何帮助,我将不胜感激,因为这是在文本冒险游戏上取得一些进展并允许一些交互的主要障碍。我确定我错误地使用了这个方法并且不明白它是如何工作的但是枚举器文档在查看它之后并没有帮助我很多并且可能有更好的方法来实现这个 class 方法。

重现问题

位置class(必要部分)

class Location
  @@finder = Array.new

  def self.findLocation(coord, attributeToPrint)
    puts coord.inspect
    puts @@finder.find { coord }.inspect
  end

  #Initialise locations here
  def initialize(newTitle, newDescription, newCoord)
    @title = newTitle
    @description = newDescription
    @coordinate = newCoord

    @@finder << self
  end

播放器class(必要部件)

class Player
  def initialize(playerHealth, playerLocation, playerInventory)
    @health = playerHealth
    @location = playerLocation
    @inventory = playerInventory
  end

主脚本(必要部分)

require_relative '../lib/player'
require_relative '../lib/location'

start = Location.new('Test 1', 'This is test 1.', [0, 0])
start2 = Location.new('Test 2', 'This is test 2.', [1,1])
start3= Location.new('Test 3', 'This is test 3.', [2, 2])
player = Player.new(100, [1,1], ['sword'])

#Input loop
loop do

  Location.findLocation(player.getLocation, 'example')
end

您必须指定 find 如何将存储的记录与提供的值进行匹配。具体来说,您需要将 coord 与记录的坐标进行比较。要访问记录的坐标,您需要一个 getter 方法。

class Location

  def self.findLocation(coord, attributeToPrint)
    puts coord.inspect
    puts @@finder.find { |location| location.coord == coord }.inspect
  end

  def coord
    @coord
  end

end  

find 的工作方式是它为数组中的每个实例执行块,返回结果为 'truthy' 的第一个数组元素(即不是 nil 也不是 false)。当您执行 { coord } 时,块 returns 立即 coord 值。 coord 不是 nil 也不是 false,因此选择了第一条记录。当您执行 @coord == coord 时,@coord 在 class 级别未定义(它为零),因此对于所有记录,比较都是错误的,因此没有选择任何记录,因此您的结果为零。

要打印特定属性(例如,title),您还可以使用 getter 方法访问该属性。然后将该方法发送给对象。

class Location

  def self.findLocation(coord, attributeToPrint)
    puts coord.inspect
    found_location =  @@finder.find { |location| location.coord == coord }
    puts found_location.send(attributeToPrint) if found_location
  end

  def coord
    @coord
  end

  def title
    @title
  end

end 

所以现在你可以做...

Location.findLocation([1,1], 'title')

然而...

让findLocation只负责返回对象然后在方法外输出属性就灵活多了...单一职责原则...

class Location

  def self.findLocation(coord)
    @@finder.find { |location| location.coord == coord }
  end

  def coord
    @coord
  end

  def title
    @title
  end

end 

所以现在你可以做...

player_location = Location.findLocation([1,1])
puts player_location.title if player_location