How i can solve this issue ? undefined method for class - ruby

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

Related

Random number generator doesn't seem to save number

My RNG guessing game seems to generate a new number constantly, and not save the number for the current session of the game for the player to guess.
def initialize
##answer = rand(1..100).to_s
end
def answer
##answer
end
def guessing
puts "What's your guess?"
##guess = gets.chomp.downcase
while ##guess != answer
wrong_answer
end
right_answer
end
I don't see any problem with your code, but it could be the way are initializing the class (if you are calling guessing explicitly everytime you want to make a guess).
You need to store the initialized class in a variable:
guess = Guess.new
guess.guessing
guess.guessing
Also you don't want to use class instance variables unless necessary i.e, use #guess, #answer instead of ##guess and ##answer.
Another way
def guessing
puts "What's your guess?"
#guess = gets.chomp.downcase
while #guess != answer
puts "wrong_answer"
#guess = gets.chomp.downcase
end
puts "right_answer"
end
I think if you store the random number in an attr_reader, you can then reference it and compare it to the guess. If you store the guess in an attr_accessor, you can compare the guess to the stored random number and have the User continue the game by updating their guess until it matches the random number. I can include an example that you can copy and paste right into IRB. To start the game just call PlayGame.new and you are off and running. Enter cheat for the random number and hint for a hint.
class RandomNumber
attr_reader :number
def initialize
#number = rand(1..100).to_s
end
def hint
random_number = number.to_i
puts case
when random_number >= 75
"Your number is in the range of 75 to 100"
when random_number >= 50
"Your number is in the range of 50 to 74."
when random_number >= 25
"Your number is in the range of 25 to 49"
else random_number > 0
"Your number is 24 or less."
end
end
end
class PlayGame
attr_accessor :input
attr_reader :number
def initialize
#generate_number = RandomNumber.new
#number = #generate_number.number
puts "What's your guess?"
#input = gets.chomp.downcase
validate
end
def validate
case
when input == number
puts "You win!"
when input == "cheat"
puts "The number is #{number}"
get_guess
when input == "hint"
#generate_number.hint
get_guess
else
get_guess
end
end
def get_guess
puts "Try again, what's your guess?"
#input = gets.chomp.downcase
validate
end
end

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.

Test file and testing file talking through each other

I'm learning Ruby and RSpec, and I've hit a snag wherein most learning materials available have become deprecated and I lack the vocabulary to sift through the wreckage.
class Session
def initialize(winning_score = 0)
#winning_score = winning_score
play
end
def play
get_players
max_score
while #game is in play
print_score
#play game
end
winner
end
def get_players
puts "\nPlayer X name:"
p1 = gets.chomp.upcase
#player1 = Player.new(p1, "X", 0)
puts "\nPlayer O name:"
p2 = gets.chomp.upcase
#player2 = Player.new(p2, "O", 0)
end
def max_score
puts "\nBest out of how many?"
max = gets.chomp
#winning_score = (max.to_f/2).ceil
end
def print_score
puts "\n#{#player1.name}: #{#player1.score} \n#{#player2.name}: #{#player2.score}"
end
def winner
if #player1.score == #winning_score
puts "\n#{#player1.name} WINS!!!"
elsif #player2.score == #winning_score
puts "\n#{#player2.name} WINS!!!"
end
end
end
class Player
attr_accessor :name, :mark, :score
def initialize(name, mark, score)
#name = name
#mark = mark
#score = score
end
end
Rpec:
describe "Play" do
before(:each) do
allow(x).to receive(:puts)
allow(x).to receive(:print)
end
let(:x) { Session.new }
it "displays game score" do
#player1 = Player.new("p1", "X", 0)
#player2 = Player.new("p2", "O", 2)
expect(x).to receive(:puts).with("\np1: 0 \np2: 2")
x.print_score
x.play
end
end
... I think that's all the applicable bits of code... The problem is that the file being tested and the RSpec file keep talking through each other, and I keep getting this sort of thing:
1) play displays game score
Failure/Error: expect(x).to receive(:puts).with("\np1: 0 \np2: 2")
#<Session:0x007fc16b9f5d38> received :puts with unexpected arguments
expected: ("\np1: 0 \np2: 2")
got: ("\n\t\t: 0 \n\tEND: 0"), ("\nPlayer X name:"), ("\nPlayer O name:"), ("\nBest out of how many?"), ("\n\tIT \"GETS AND CREATES PLAYERS\" DO WINS!!!")
# ./tictactoe_spec.rb:36:in `block (2 levels) in <top (required)>'
...where the noise is other methods gets.chomping the running RSpec code and storing it as the player names... I can't figure out how to prevent this from happening, clear/reset it, or what the correct course of action even is... Please advise.
Well, you are setting the #player1 and #player2 instance variables in the test context. While you need them inside your session object.
I think a good approach here would be to stub the get_players method, but we will have to change it a bit.
class Session
#...
def get_players
#player1 = get_player("X")
#player2 = get_player("O")
end
def get_player(mark)
puts "\nPlayer #{mark} name:"
name = gets.chomp.upcase
Player.new(name, mark, 0)
end
#...
end
Now you can stub those get_player calls
# ...
it "displays game score" do
allow(x).to recive(:get_player).with("X") { Player.new("p1", "X", 0) }
allow(x).to recive(:get_player).with("O") { Player.new("p2", "O", 2) }
expect(x).to receive(:puts).with("\np1: 0 \np2: 2")
x.print_score
x.play
end
The solution was to implement an optional output source at initialization that defaults to stdout, then create a double of that output source for the methods to puts to. After talking to a few more experienced devs, it seems to be a fairly common thing to do. Simplifying the code a bit would probably also be pretty thoroughly helpful... It's pretty bad looking back at it.

Ruby: issues with an undefined method error

I am working on a ruby banking problem and I keep coming across this error when trying to write the code for the deposit method. I would like the deposit method to put out a puts statement saying this person has enough cash to make this deposit and state amount, or it states they do not have enough cash to deposit. It says this error in my irb:
NoMethodError: undefined method `<' for nil:NilClass
from banking2.rb:30:in `deposit'
from banking2.rb:59:in `<top (required)>'
Can someone please help me find my error? I've tried several options but am not able to figure it out.
class Person
attr_accessor :name, :cash_amount
def initialize(name, cash_amount)
#name = name
#cash_amount = #cash_amount
puts "Hi, #{#name}. You have #{cash_amount}!"
end
end
class Bank
attr_accessor :balance, :bank_name
def initialize(bank_name)
#bank_name = bank_name
#balance = {} #creates a hash that will have the person's account balances
puts "#{bank_name} bank was just created."
end
def open_account(person)
#balance[person.name]=0 #adds the person to the balance hash and gives their balance 0 starting off.
puts "#{person.name}, thanks for opening an account at #{bank_name}."
end
def deposit(person, amount)
#deposit section I can't get to work
if person.cash_amount < amount
puts "You do not have enough funds to deposit this #{amount}."
else
puts "#{person.name} deposited #{amount} to #{bank_name}. #{person.name} has #{person.cash_amount}. #{person.name}'s account has #{#balance}."
end
end
def withdraw(person, amount)
#yet to write this code
# expected sentence puts "#{person.name} withdrew $#{amount} from #{bank_name}. #{person.name} has #{person.cash_amount} cash remaining. #{person.name}'s account has #{#balance}. "
end
def transfer(bank_name)
end
end
chase = Bank.new("JP Morgan Chase")
wells_fargo = Bank.new("Wells Fargo")
person1 = Person.new("Chris", 500)
chase.open_account(person1)
wells_fargo.open_account(person1)
chase.deposit(person1, 200)
chase.withdraw(person1, 1000)
Change this in your initialize method on Person:
#cash_amount = #cash_amount
To this:
#cash_amount = cash_amount
You added an extra # sign, so you set #cash_amount to #cash_amount. The default value for an uninitialized instance variable is nil in Ruby.
The only place you have a < is in person.cash_amount < amount, so the error is coming from there - person.cash_amount is nil.
Look at where cash_amount is being defined in your Person initializer - you are passing in def initialize(name, cash_amount) but then you are calling #cash_amount = #cash_amount!
Remove the second # so you are actually assigning #cash_amount with the value you are passing in in cash_amount.

Ruby: Using variables between classes

I am making a short, text-based game as an extra credit exercise based on the Ruby I have learned so far and I'm having trouble getting classes to read and write variables between each other. I have read extensively and searched for clarification on how to do this but I haven't had much luck. I have tried using # instance variables and attr_accessible but I can't figure it out. Here is my code so far:
class Game
attr_accessor :room_count
def initialize
#room_count = 0
end
def play
while true
puts "\n--------------------------------------------------"
if #room_count == 0
go_to = Entrance.new()
go_to.start
elsif #room_count == 1
go_to = FirstRoom.new()
go_to.start
elsif #room_count == 2
go_to = SecondRoom.new()
go_to.start
elsif #room_count == 3
go_to = ThirdRoom.new()
go_to.start
end
end
end
end
class Entrance
def start
puts "You are at the entrance."
#room_count += 1
end
end
class FirstRoom
def start
puts "You are at the first room."
#room_count += 1
end
end
class SecondRoom
def start
puts "You are at the second room."
#room_count += 1
end
end
class ThirdRoom
def start
puts "You are at the third room. You have reached the end of the game."
Process.exit()
end
end
game = Game.new()
game.play
I want to have the different Room classes change the #room_count variable so that Game class knows which room to go to next. I am also trying to do this without implementing class inheritance. Thanks!
class Room
def initialize(game)
#game = game
#game.room_count += 1
end
def close
#game.room_count -= 1
end
end
class Game
attr_accessor :room_count
def initialize
#room_count = 0
end
def new_room
Room.new self
end
end
game = Game.new
game.room_count # => 0
room = game.new_room
game.room_count # => 1
room.close
game.room_count # => 0

Resources