【问题标题】:Making a Yhatzee game, array won't show up on screen制作 Yahtzee 游戏,数组不会出现在屏幕上
【发布时间】:2015-05-05 13:58:48
【问题描述】:

好的,所以我刚开始学习 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 的原因是我不断收到“未初始化的变量 @dices”错误,这似乎解决了它,我不知道为什么。

关于我的问题,我目前没有收到任何错误,但我的程序仍然不会在屏幕上打印任何内容。我希望它能够打印出数组中每个骰子的值......知道我做错了什么吗?当我在不使用类或方法的情况下以程序样式执行此操作时,它似乎有效,因此我认为如果我将“骰子”方法公开,它可能会有效。但没有运气。

【问题讨论】:

    标签: ruby arrays class object methods


    【解决方案1】:

    这里有几个问题。首先@dicesnil,因为它没有在任何地方设置。因此,当您调用@dices.to_a 时,您将得到[]。此外,骰子方法也不起作用,因为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   
    

    【讨论】:

    • 嘿,谢谢你的修复,除非我卡住了,否则我会尽量不看你的扩展,我这样做主要是为了练习,这真的是我的第一个实际项目。我有一个棘手的问题。基本上,在我看来,您所做的实际上只是调用方法“dice”而不是调用实际变量“@dice”,我不太明白为什么在调用变量时它不起作用。此外,当您解决这样的问题时,是否有任何理由将“@dice”数组实际设为实例变量?
    • @MariusBelkhirMahiout 调用该变量不起作用的原因是因为它在您调用它时没有设置,所以它是nilnil.to_a 产生一个空数组。调用该方法会返回数组,因此它可以工作。从技术上讲,像这样调用时您不需要实例变量,但您可能希望握住骰子以便稍后与它进行交互。
    【解决方案2】:

    这段代码的主要问题是你试图在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. 创建了一个初始化方法,该方法在类初始化时创建@dice 实例变量。
    2. 使“骰子”方法更具描述性,并将方法可见性更改为私有,因此只有类本身才能创建 @dice。
    3. 清理了 @dice 实例变量中骰子的创建
    4. 我已经从 roll_dice 方法中省略了 .to_a,现在我们从类中创建了变量,并且我们知道它是一个数组,除非我们明确地重新定义它,否则它将是一个数组。

    更新

    虽然我清理了类的实现,但@engineersmnky 好心地指出,我监督每次调用 roll_dice 函数时 roll 会返回相同的结果,因此我编写了两个函数来实现这一点,一个定义一个实例变量供以后使用,另一个实际上只是返回结果。

    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 
    

    【讨论】:

    • 很好的解释,但从逻辑的角度来看,@dices 现在已固定为该集合。滚动不应该每次都返回不同的结果吗?还放在每个循环中的数组将与调用puts ARRAY_HERE 产生相同的影响
    • 是的,谢谢您指出这一点,我完全监督了这一点。我现在修改了我的答案。关于循环,我实际上并不知道是这种情况,但是在查看它之后,我认为我更喜欢使用循环只是为了便于阅读。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 1970-01-01
    • 2023-01-09
    • 2015-05-20
    • 1970-01-01
    • 2017-09-04
    相关资源
    最近更新 更多