This short code is working when I'm using class variable ##points instead of #points. I wonder why it's happening like this? Someone can explain me? It looks like #points is always nil.
class Game
#points = 0
def start
until #points == 10
puts "Guess number between 0 and 10:"
num = gets.chomp.to_i
break if #points == 0
guess_number(num)
puts "Your score is: #{#points}"
end
end
def guess_number(num)
#points += 1 if num == rand(0..10)
end
end
game = Game.new
game.start
Because #points is a class instance variable, and to access it from within the instance method's scope you'd have to either do
self.class.instance_variable_get(:#points)
or define an attr_accessor in Game's singleton_class
class Game; class << self; attr_accessor :points; end; end
and then you'd be able to do
self.class.points
But neither of these is what you really want.
code is working when I'm using class variable ##points instead of
#points
It is working, because you do have access to class variable from within a scope of an instance methods.
It looks like #points is always nil
It is always nil, because you never defined an instance variable #points, but, as said, class instance variable.
So these three things are different (you could read up something about Ruby scoping - do not mix with AR scopes):
class variable
class instance variable
instance variable
To solve it there are many ways, but if you want to keep it on the instance level, wrap #points into a method:
def points
#points ||= 0
end
And then use it as points - now it'll work as you are expecting.
Thanks to answer by Andrey Deineko. I came up with such solution to use instance variable here.
class Game
def initialize
#points = 0
end
def start
until points == 10
puts "Guess number between 0 and 10:"
num = gets.chomp.to_i
break if points == 10
guess_number(num)
puts "Your score is: #{points}"
end
end
private
def guess_number(num)
if num == rand(0..10)
increment_points
end
end
def points
#points
end
def increment_points
#points += 1
end
end
game = Game.new
game.start
Related
why is the instance variable #my_instance return nil even thought it's been set to 0 in the my_method ?
attr_accessor should let me write and read the instance, right ?
what would be the right way to do something like this ?
thank You.
class Myclass
attr_accessor :my_instance
def initialize
#my_instance
end
def called_method
puts "this is my instance value #{my_instance} "
end
def my_method
my_instance = 0
puts "i set my instance to be #{my_instance}"
called_method
end
end
a = Myclass.new
a.my_method
called_method return nil when i expect 0
what would be the right way to do something like this ?
my_instance = 0
This creates a local variable instead of calling your setter. Give ruby a hint that you want to call the method:
self.my_instance = 0
Or you can set the instance variable directly:
#my_instance = 0
I am currently making a game, and I have some problems. I used define to make some special cases. This is my define script.
def answerCorrect()
puts "Correct! Let's proceed to the next question."
points = points + 1
end
def answerWrong()
puts "Oh no! That's wrong! Try again!"
points = points - 2
input = gets.chomp
end
And the special case is:
if input == "x"
answerCorrect()
else
answerWrong()
end
However, I get this error:
`answerCorrect': undefined method `+' for nil:NilClass (NoMethodError)
How can I solve this?
The problem is that your points variable is not shared across the two methods.
Consider using an instance variable to manage the point system, ie.
class AnswerEvaluator
def initialize
#points = 0
end
def answerCorrect()
puts "Correct! Let's proceed to the next question."
#points = #points + 1
end
def answerWrong()
puts "Oh no! That's wrong! Try again!"
#points = #points - 2
input = gets.chomp
end
end
You could expand on this by using an attr_accessor if you don't want to access the #points directly.
The problem is that the method does not know what "points" is. you probably need to make this an instance variable #points
Example:
class myGame
def initialize
#points = 0
end
def answerCorrect()
puts "Correct! Let's proceed to the next question."
#points = #points + 1
end
def answerWrong()
puts "Oh no! That's wrong! Try again!"
#points = #points - 2
input = gets.chomp
end
end
class Player
attr_accessor :card_pile
def initialize
#bust = false
#card_pile = []
end
def bust?
return #cards.inject(:+) > 21
end
end
I have this Player class and have initazlied card_pile variable
class Game
def initialize
#players = []
end
def playing_game
puts "How many players are playing? "
players_amount = gets.chomp.to_i
(0...players_amount).each do
puts ("What is the players name? ")
name = gets.chomp
#players.push(name)
end
puts #players
player = Player.new
player.initialize
while #card_pile.length < 2 do
new_card = Card.new
#card_pile.push(new_card.value)
end
end
I wish to use this variable in the while loop below. Why cannot this be accessed in the way I am hoping it will be?
The error message is: ``playing_game': private method initialize' called for #<Player:0x007fda53073f48 #bust=false, #card_pile=[]> (NoMethodError)
initialize is called automatically when you make a new instance of a class using Player.new. You don't currently have any arguments being passed in to your initialize method, but you have set the instance variable card_pile with attr_accessor, so you can do this:
player = Player.new
while player.card_pile.length < 2 do
new_card = Card.new
player.card_pile.push(new_card.value)
end
I am building a Tic-Tac-Toe game to be played on the command line.
module TicTacToe
class Player
attr_accessor :symbol
def initialize(symbol)
#symbol = symbol
end
end
class Board
attr_reader :spaces
def initialize
#spaces = Array.new(9)
end
def to_s
output = ""
0.upto(8) do |position|
output << "#{#spaces[position] || position}"
case position % 3
when 0, 1 then output << " | "
when 2 then output << "\n-----------\n" unless position == 8
end
end
output
end
def space_available(cell, sym)
if spaces[cell].nil?
spaces[cell] = sym
else
puts "Space unavailable"
end
end
end
class Game < Board
attr_reader :player1, :player2
def initialize
play_game
end
def play_game
#player1 = Player.new("X")
#player2 = Player.new("O")
puts Board.new
#current_turn = 1
turn
end
def move(player)
while victory != true
puts "Where would you like to move?"
choice = gets.chomp.to_i
space_available(choice, player.symbol)
puts Board
#current_turn += 1
turn
end
end
def turn
#current_turn.even? ? move(#player2) : move(#player1)
end
def victory
#still working on this
end
end
end
puts TicTacToe::Game.new
The method that is to take a user's cell choice (space_available) and alter the array with their piece ('X' or 'O') is giving me an error. I can't find why my code is throwing this particular error.
The problem is that you don't call the parent constructor in your Game class, therefore #spaces is not initialized.
Your hierarchy decision is questionable, but to make it work, you can simply change the Game constructor to:
def initialize
super
play_game
end
You are calling spaces[cell]. The error is telling you that you are calling [] on nil, which means that spaces must be nil.
Perhaps you mean #spaces? Otherwise - you need to tell the program how spaces is defined and how it is initialized. A simple spaces = {} unless spaces would work
Another way of initialising your spaces variable would be to call super when you initialize the Game:
class Game < Board
attr_reader :player1, :player2
def initialize
super
play_game
end
...
Working in Ruby, I'm getting an error saying
'add': undefined local variable or method 'food' for #<FoodDB:...
This is the code I'm trying to run
require_relative 'FoodDB.rb'
class Manager
def initialize
food = FoodDB.new
self.create_foodDB(food)
end
def create_foodDB(food)
counter = 1
word = []
file = File.new("FoodDB.txt","r")
while (line = file.gets)
food.addFood(line)
counter = counter + 1
end
file.close
end
end
manager = Manager.new
input_stream = $stdin
input_stream.each_line do |line|
line = line.chomp
if line == "quit"
input_stream.close
end
end
This is FoodDB.rb's code
class FoodDB
def initialize
food = []
end
def addFood(str)
food.push(str)
end
end
I'm not sure what's the problem since it seems like I'm definitely calling the correct method from the FoodDB class. All help is appreciated, thank you!
You need to change food in the FoodDB class to an instance variable:
class FoodDB
def initialize
#food = []
end
def addFood(str)
#food.push(str)
end
end
An instance variable will be available throughout all methods of an instance, while the food variable you used was local to its lexical scope, i.e. only available within the initialize method.