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
Related
I'm trying to access a class variable from a method outside of the class.
This is my class:
class Book
##bookCount = 0
##allBooks = []
def self.allBooks
##allBooks
end
def self.bookCount
##bookCount
end
attr_accessor :name,:author,:date,:genre,:rating
def initialize(name, author, date, genre, rating)
#name = name
#author = author
#date = date
#genre = genre
#rating = rating
##bookCount += 1
##allBooks << self
end
end
This is the method trying to access the class variable ##bookCount
def seeBookShelf
if ##bookCount == 0
puts "Your bookshelf is empty."
else
puts "You have " + #bookCount + " books in your bookshelf:"
puts allBooks
end
end
When I try to execute the method I get this:
undefined local variable or method `bookCount' for main:Object (NameError)
How can I access bookCount from the outside?
Use class_variable_get to access a class variable outside of a class:
class Foo
##a = 1
end
Foo.class_variable_get(:##a)
=> 1
For most cases, class instance variables are preferred to class variables. The latter are prone to all manner of strange behaviour when used with inheritance.
Consider:
class Book
#book_count = 0
#all_books = []
class << self
attr_reader :book_count
attr_reader :all_books
end
# further code omitted.
end
With this code Book.book_count and Book.all_books get the expected data.
You can use class_eval to evaluate a block of code within the scope of a specific class:
class Book
##bookCount = 1
end
Book.class_eval '##bookCount'
# => 1
And just for fun... you can actually do all kinds of trickery with class_eval such as define a new method in the class without monkey patching:
Book.class_eval { ##bookCount = 5 }
Book.class_eval '##bookCount'
# => 5
Book.class_eval do
def self.hey_look_a_new_method
return "wow"
end
end
Book.hey_look_a_new_method
# => "wow"
You need a getter to access the class variable, try this code.
See http://www.railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby/ for an explanation.
You are also better to use string interpolation otherwise you get a Type error, also it is more Rubyesque.
class Book
##bookCount = 0
def self.bookCount
##bookCount
end
end
def seeBookShelf
if Book.bookCount == 0
puts "Your bookshelf is empty."
else
puts "You have #{Book.bookCount} books in your bookshelf:"
end
end
seeBookShelf # Your bookshelf is empty.
You have to specify the Class of the variable :
def seeBookShelf
if Book.bookCount == 0
puts "Your bookshelf is empty."
else
puts "You have " + Book.bookCount + " books in your bookshelf:"
puts Book.allBooks
end
end
I have this class:
class Player
attr_accessor :card_pile, :name
def initialize
#name = name
#bust = false
#card_pile = []
end
def bust?
return #cards.inject(:+) > 21
end
end
I also have this as the beginning of another class
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
#players.each do |each_player|
#name = Player.new
while true
while #name.card_pile.length < 2 do
new_card = Card.new
#name.card_pile.push(new_card.value)
end
puts(#name.card_pile)
print #name, "'s turn" "\n"
At the moment this will print out #<Player:0x007fc14984a4b0>'s turn instead of Rich's turn
Why is this happening? I thought I had made an instance variable in the Player class and then instantiated this class #name = Player.new and then could reference it from here on out??
This will help
def playing_game
puts 'How many players are playing?'
players_amount = gets.chomp.to_i
players_names = (0...players_amount).map do
puts ("What is the players name? ")
gets.chomp
end
players_names.each do |player_name|
player = Player.new(player_name)
while player.card_pile.length < 2 do
new_card = Card.new
player.card_pile.push(new_card.value)
end
puts player.card_pile
puts "#{player.name}'s turn"
end
end
UPD:
You don't need instance variables (like #name and #players inside single method).
In this code you iterate over players names
#players.each do |each_player|
=>
players_names.each do |player_name|
In context of
#name = Player.new
name is a Player instance
to create player with given name pass it to initializer:
player = Player.new(player_name)
then call name on Player instance, that you create earlier
puts "#{player.name}'s turn"
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
...
I'm trying to make a game but I am having problems settinga default value for an attribute and having a different default value for each subclass.
Here is the problem:
class Player
attr_accessor :hp
#hp = 2
end
class Harper < Player
#hp = 5
end
bill = Harper.new.hp #=>nil
I'm expecting Harper.new.hp to be 5 but it's showing nil instead, and I don't understand why.
The problem with your initialization is that it exists at the class level. That is, you are creating a class instance variable (confusing?) not an object-instance variable as you expect.
In order to create an instance variable you need to do it in a method run at the instance level, like the initialize method which runs when you create an object with the "new" method.
Example:
class Hello
#world = "World!"
def initialize
#to_be_or_not_to_be = "be!"
end
end
=> :initialize
inst = Hello.new
inst.instance_variables
=> [:#to_be_or_not_to_be]
Hello.instance_variables
=> [:#world]
inst.class.instance_variables
=> [:#world]
You need to place your assignments on an initialize function:
class Player
attr_accessor :hp
def initialize
#hp = 2
end
end
class Harper < Player
def initialize
super ## May not be necessary for now.
#hp = 5
end
end
bill = Harper.new.hp
# => 5
new class method runs instance method initialize, so your code should look like:
class Harper < Player
def initialize
#hp = 5
end
end
I'm creating a card game with multiple classes. Currently, I'm using global variables to hold the $shuffled_deck, $players_hand, and $dealers_hand variables, but I worry when using global variables (perhaps, needlessly) and would prefer to use instance variables.
I've been reading around, but nothing is really clicking. Can anyone help point me in the right direction with this?
Using instance variables I haven't been able to save the #players_hand and #dealers_hand to be able to use them in other classes. For instance, I have #players_hand from the Player class. I have the Dealer class draw a card, but I can't pull that #players_hand into the Dealer class to add the two together.
My current code is:
class Blackjack
def initialize
#player = Player.new
#dealer = Dealer.new
end
end
class Dealer
def initialize
#deck = Deck.new
$dealers_hand = 0
end
def hit_dealer
#deck.hit_dealer
end
def hit_player
#deck.hit_player
end
def draw_card
#hit = $shuffled_deck
end
def shuffle
#deck.suits
end
end
class Player
def initialize
$players_hand = 0
end
end
class Deck
def suits
#code that shuffled the deck..
$shuffled_deck = #shuffled_deck
end
def hit_player
#hit = $shuffled_deck.pop
end
def hit_dealer
#hit = $shuffled_deck.pop
end
end
using your example you can do it like this
class Blackjack
attr_reader :player, :dealer
def initialize
#player = Player.new
#dealer = Dealer.new
end
end
class Dealer
def dealers_hand #the long java way of a getter
#dealers_hand
end
#and now the short ruby way
attr_reader :dealers_hand #if you only need to read the attribute
attr_writer :dealers_hand #if you only need to write the attribute
attr_accessor: dealers_hand #if you need both
def initialize
#deck = Deck.new
#dealers_hand = 5
end
def hit_dealer
#deck.hit_dealer
end
def hit_player
#deck.hit_player
end
def draw_card
#hit = $shuffled_deck
end
def shuffle
#deck.suits
end
end
class Player
attr_reader :players_hand
def initialize
#players_hand = 0
end
end
class Deck
def suits
attr_reader :shuffled_deck
#shuffled_deck = #shuffled_deck
end
def hit_player
#hit = $shuffled_deck.pop
end
def hit_dealer
#hit = $shuffled_deck.pop
end
end
game = Blackjack.new
p game.dealer.dealers_hand
game.dealer.dealers_hand = 4
p game.dealer.dealers_hand
You want to use attr_reader, attr_writer, or attr_accessor. Here's how they work:
attr_reader :players_hand: Allows you to write some_player.players_hand to get the value of that player's players_hand instance variable
attr_writer :players_hand: Allows you to write some_player.players_hand = 0 to set the variable to 0
attr_accessor :players_hand: Allows you to both read and write, as though you'd used both attr_reader and attr_writer.
Incidentally, all these do is write methods for you. If you wanted, you could do it manually like this:
class Player
def initialize
#players_hand = 0
end
def players_hand
#players_hand
end
def players_hand=(new_value)
#players_hand = new_value
end
end