制作 Yahtzee 游戏时,数组不会显示在屏幕上

Making a Yhatzee game, array won't show up on screen

好的,所以我刚开始学习 ruby 并且我正在制作 Yhatzee 游戏,现在这是我目前所在的位置:

class  Yhatzee

 def dices
    @dices.to_a= [
    dice1=rand(1..6),
    dice2=rand(1..6),
    dice3=rand(1..6),
    dice4=rand(1..6),
    dice5=rand(1..6)
    ]
  end

  def roll_dice
    @dices.to_a.each do |dice|
      puts dice
    end
  end
end

x = Yhatzee.new
puts x.roll_dice

现在我在数组后输入 .to_a 的原因是我一直收到 "uninitialized variable @dices" 错误,这似乎解决了它,我不知道为什么。

关于我的问题,我目前没有收到任何错误,但我的程序仍然不会在屏幕上打印任何内容。我希望它能打印出数组中每个骰子的值……知道我做错了什么吗?当我在不使用 类 或方法的情况下以程序方式执行时,它似乎可以工作,所以我认为如果我使用 'dices' 方法 public 它可能会工作。但是运气不好。

这里有一些问题。首先 @dicesnil 因为它没有在任何地方设置。因此,当您调用 @dices.to_a 时,您将得到 []。此外, dices 方法也不起作用,因为 nil 没有 to_a= 方法,并且您在数组中分配的局部变量将被忽略。

似乎需要阅读一些内容,但我会执行以下操作:(不是整个游戏只是重构您的代码)

class  Yhatzee
  def dice
    @dice = Array.new(5){rand(1..6)}
  end
  def roll_dice
    puts dice
  end
end

x = Yhatzee.new
puts x.roll_dice

这里需要考虑很多额外的注意事项,但这至少应该让您入门。我建议如何扩展你的逻辑的小例子:(我没有在这里处理很多场景所以不要复制粘贴。只是想让你更深入地了解)

require 'forwardable'
module Yahtzee
  module Display
    def show_with_index(arr)
      print arr.each_index.to_a
      print "\n"
      print arr
    end
  end
  class Roll
    include Display
    extend Forwardable 
    def_delegator :@dice, :values_at
    attr_reader :dice
        def initialize(dice=5)
            @dice = Array.new(dice){rand(1..6)}
        end
        def show
      show_with_index(@dice)
        end
    end
  class Turn
    class << self
      def start
        t = Turn.new
        t.show
        t
      end
    end
    attr_reader :rolls
    include Display
    def initialize
      @roll = Roll.new
      @rolls = 1
      @kept = []
    end
    def show
      @roll.show
    end
    def roll_again
      if available_rolls_and_dice
        @rolls += 1
        @roll = Roll.new(5-@kept.count)
        puts "Hand => #{@kept.inspect}"
        show
      else
        puts "No Rolls left" if @rolls == 3
        puts "Remove a Die to keep rolling" if @kept.count == 5
        show_hand
      end 
    end
    def keep(*indices)
      @kept += @roll.values_at(*indices)
    end
    def show_hand
      show_with_index(@kept)
    end
    def remove(*indices)
      indices.each do |idx| 
        @kept.delete_at(idx)
      end
      show_hand
    end
    private 
      def available_rolls_and_dice
        @rolls < 3 && @kept.count < 5
      end
  end
end   

此代码的主要问题是您试图在 roll_dice 方法内部使用 @dices 实例变量,但是您没有在任何地方(正在使用的任何地方)定义实例变量。您已经创建了 dices 方法,但实际上并没有在任何地方实例化它。我在下面概述了一个修复方法:

class  Yhatzee

  def initialize
    create_dices
  end

  def roll_dice
    @dices.each do |dice|
      puts dice
    end
  end

  private

  def create_dices
    @dices = Array.new(5){rand(1..6)}
  end

end

x = Yhatzee.new
x.roll_dice

我做了一些简单的重构:

  1. 创建了一个初始化方法,它在 class 初始化时创建了 @dice 实例变量。
  2. 使 'dices' 方法更具描述性,并将方法可见性更改为私有,因此只有 class 本身能够创建 @dice。
  3. 清除了在@dice 实例变量中创建的骰子
  4. 我已经从 roll_dice 方法中省略了 .to_a ,现在我们从 class 中创建变量并且我们知道它是一个数组并且它将是除非我们明确地重新定义它。

更新

尽管我清理了 class 的实现,但@engineersmnky 友善地指出,我监督每次调用 [=34] 时滚动都会 return 相同的结果=] 函数,因此我编写了两个函数来实现这一点,一个定义了一个实例变量供以后使用,另一个实际上只是 return 的结果。

class  Yhatzee

  def roll_dice
   @dice = Array.new(5){rand(1..6)} # You will have access to this in other methods defined on the class
   @dice.each {|dice| puts dice }
  end

  def roll_dice_two
    Array.new(5){rand(1..6)}.each {|dice| puts dice } # This will return the results but will not be stored for later use
  end

end

x = Yhatzee.new
x.roll_dice
x.roll_dice # Will now return a new result