why do I get undefined method `+' for nil:NilClass (NoMethodError) - ruby

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

Related

How i can solve this issue ? undefined method for class

Have a problem, when run a code allways have error.
Expect: for the user add win or reduce his balance.
undefined method `balance=' for #<Dice:0x0000563d4d4dfd88 #name="foo", #balance=600, #bet=300>
Did you mean? balance
(repl):22:in `increase_decrease_cash'
(repl):62:in `<class:Game>'
(repl):29:in `<main>'
This error always comes out, retried everything I could guess, but nothing came of it and I don’t understand how it can be googled
class Dice
attr_accessor :name, :bet
attr_reader :balance
def initialize(name, balance, bet)
#name = name
#balance = balance
#bet = bet
end
def self.roll
#roll_dice = rand(1..2)
end
def self.check_bet
if #player.bet > #player.balance
puts "Enter number from 1 to #{#player.balance}"
end
end
def self.increase_decrease_cash
if #roll == #my_number
#player.balance += #player.bet
else
#player.balance -= #player.bet
end
end
end
class Game < Dice
#player = Dice.new("foo", 600, 0)
puts "Hello #{#player.name} your balance is: #{#player.balance}"
puts "Bones throwing count times"
a = 2 #gets.chomp.to_i
while a > 0 do
puts ""
puts "Enter your bet !!!"
# PLAYER BET
#player.bet = 300 #gets.chomp.to_i
check_bet
puts "Respected #{#player.name} your bet is: #{#player.bet}"
puts "Now select number 1-2"
# BONES ROLL
#my_number = roll # gets.chomp.to_i
puts "###################"
puts "Now we throw bones"
#roll = roll
puts "Nuber is #{roll}"
if #roll == #my_number
puts "Your win, you get #{#player.bet}"
else
puts "You lose #{#player.bet}"
end
p "$$$$"
p #player.balance
p "$$$$"
a -= 1
increase_decrease_cash
end
end
This error always comes out, retried everything I could guess, but nothing came of it and I don’t understand how it can be googled
attr_reader creates only the get method for balance. You need both get and set method for balance. Because you set balance in the initialize method. So, you should use attr_accessor instead of attr_reader.
attr_accessor :balance

Why this instance variable is not incrementing?

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

Ruby beginner: class, instance variable, accessor, rspec

So I'm in the process of trying to recreate a board game called Ciao Ciao. I'm not anywhere near done but I keep getting stuck and would really appreciate some help. So far I've made the following 3 classes and rspec file:
The Player class
require_relative 'die'
class Player
attr_reader :name
attr_accessor :token, :position, :point
def initialize(name, token, position, point)
#name = name
#token = token
#position = position
#point = point
end
def advance
#position += #number #basically I want the player to advance when he rolls between 1-4 but not sure how to connect it to the Die class here.
end
def lie
#token -= 1 #here I want the player to lose a token if he rolls between 5-6
#position == 0 #and have to start again from position 0
end
def score
#token -= 1
#position == 0
#point += 1
end
end
The Game Class
require_relative 'player'
require_relative 'die'
class Game
def initialize(title)
#title = title
#players = []
end
def join(player)
#players << player
end
def play
puts "There are #{#players.size} players in the current round of #{#title}."
#players.each do |player|
die = Die.new
case die.roll
when 1..4
puts "#{player.name} just rolled #{die.roll}!"
player.advance
puts "#{player.name} advances to #{player.position}!"
when 5..6
puts "#{player.name} just rolled #{die.roll}!"
player.lie
puts "#{player.name} is down to #{player.token} and starts at #{player.name}!"
end
puts "#{player.name} has #{player.point} points and is at #{player.position}. He has #{player.token} token(s) left."
if player.position >= 10
player.score
puts "#{player.name} scores a point for reaching the endzone!"
end
if player.token == 0
#players.delete(player)
puts "#{player.name} has been eliminated."
end
end
end
end
The Die Class
class Die
attr_reader :number
def initialize
end
def roll
#number = rand(1..6)
end
end
The rspec file
require_relative 'game'
describe Game do
before do
#game = Game.new("chaochao")
#initial_token == 4
#initial_position == 0
#initial_point == 0
#player = Player.new("iswg", #initial_token, #initial_position, #initial_point)
#game.join(#player)
end
it "advances the player if a number between 1 and 4 is rolled" do
#game.stub(:roll).and_return(3)
#game.play
#player.position.should == #initial_position + 3
end
it "makes the player lie if a number between 5 and 6 is rolled" do
#game.stub(:roll).and_return(5)
#game.play
#player.token.should == #initial_token - 1
end
end
I keep getting the following error message when I run the rspec file:
Failures:
1) Game advances the player if a number between 1 and 4 is rolled
Failure/Error: #game.play
NoMethodError:
undefined method -' for nil:NilClass
# ./player.rb:19:inlie'
# ./game.rb:24:in block in play'
# ./game.rb:16:ineach'
# ./game.rb:16:in play'
# ./game_spec.rb:17:inblock (2 levels) in '
2) Game makes the player lie if a number between 5 and 6 is rolled
Failure/Error: #game.play
NoMethodError:
undefined method +' for nil:NilClass
# ./player.rb:15:inadvance'
# ./game.rb:21:in block in play'
# ./game.rb:16:ineach'
# ./game.rb:16:in play'
# ./game_spec.rb:23:inblock (2 levels) in '
So the error message points to the advance/lie methods under Player class but I have no idea what I've done wrong. Also please feel free to point out other blunders. Thanks so much in advance.
This isn't the whole problem, but it's a problem.
Your first error stood out to me a bit. player.lie is only supposed to be called when the roll is a 5 or 6, but you stubbed the roll method to return a 3. Or did you?
roll is a method of the Die class, but you stubbed #game, which is an instance of the Game class.

undefined method `[]' for nil:NilClass (NoMethodError) in tic-tac-toe game

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
...

uninitialized constant Die (NameError)

I'm receiving an Uninitialized constant error from my code. I have searched around with no luck. Any help would be highly appreciated.
Class Die
def initialize
roll
end
def roll
#num_showing = 1 + rand(6)
end
def showing
#num_showing
end
def cheat
puts "Enter the die # (1-6)"
#num_showing = gets.chomp
while #numshowing > 6 and #numshowing < 0
puts "Enter the die # (1-6)"
#num_showing = gets.chomp
end
end
puts Die.new.cheat
Change Class to class
Add an extra end at the end of the class definition. Looks like you're not closing the while loop.

Resources