Using a variable across classes in Ruby - ruby

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"

Related

How to make 2 entities of the same class interact?

I am trying to get 2 "people" of the same class to interact with each other, and change each other's "stats." However, I get the error, "formal argument cannot be a constant."
class Hands
attr_reader :name, :element, :skill, :mana, :health, :attack, :fire, :water, :lyfe
def initialize(name, element, skill)
#mana = 100
#health = 200
#name = name
#element = element
#skill = skill
end
def mana
sleep 1
puts "#{#name} has #{#mana} mana."
end
def health
sleep 1
puts "#{#name} has #{#health} HP."
end
def restore(Hands)
if #element == "Lyfe"
#mana = 100
puts "#{#name} has been restored!"
else
puts "#{#name} cannot use this ability!"
end
end
end
player1 = Hands.new('Silk', 'Lyfe', 'Summon')
player2 = Hands.new('Nubz', 'Lyfe', 'Manipulate Wildlife')
player3 = Hands.new('Lisk', 'Water', 'Invisible')
player4 = Hands.new('Azzi', 'Water', 'Manipulate Water')
player5 = Hands.new('Zeph', 'Fire', 'Lightning')
player6 = Hands.new('Ford', 'Fire', 'Manipulate Fire')
player7 = Hands.new('Boyd', 'Fire', 'Craft')
player1.restore("Nubz")
Here I am trying to get player1 to "restore" player2 back to full mana.
I know the code isn't perfect, but I'm not sure how else to do this.
Focussing on the restore command, the others work fine.
You should be able to pass the instance of the player you want affected to the restore method rather than the name string. You can then update that player's attributes as needed. A quick example:
Update class to make mana writeable:
class Hands
attr_reader :name, :element, :skill, :mana, :health, :attack, :fire, :water, :lyfe
attr_writer :mana
# ...
end
Update restore method to accept player instance:
def restore(hands)
if element == "Lyfe"
hands.mana = 100
puts "#{hands.name} has been restored!"
else
puts "#{name} cannot use this ability!"
end
end
Pass instance to method:
player1 = Hands.new('Silk', 'Lyfe', 'Summon')
player2 = Hands.new('Nubz', 'Lyfe', 'Manipulate Wildlife')
player1.restore(player2)
#=> Nubz has been restored!

How do I pull a name from a class in an Array?

Okay, this is a little hard to explain but I will try (For starters I am only just learning to code so it may be something super simple I'm missing..)
I created a few classes, I put a name in those classes, I put them in an array, I then chose one at random and try to puts the name, and it outputs blank.
Am I doing this all completely wrong? I've been learning ruby for about 3 months now so I'm sure there is a lot I don't know.
class A
attr :name
def set_name
#name = "Aaa"
end
def get_name
return #name
end
end
class B
attr :name
def set_name
#name = "Bbb"
end
def get_name
return #name
end
end
class C
attr :name
def set_name
#name = "Ccc"
end
def get_name
return #name
end
end
name_a = A.new
name_b = B.new
name_c = C.new
which_name = Array.new
which_name[0] = name_a
which_name[1] = name_b
which_name[2] = name_c
roll = rand(max 3)
puts which_name[roll].get_name
I then chose one at random and try to puts the name, and it outputs
blank.
You never called the #set_name method in your code. You can add this:
name_a.set_name
name_b.set_name
name_c.set_name
Also, you probably want to look into #attr_accessor.

How to access an instance variable in another Ruby class?

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

obj.method(argument)

I am looking at this code:
class Student
attr_accessor :first_name, :last_name, :age
def initialize(first, last, age)
#first_name = first
#last_name = last
#age = age
end
def birthday
#age += 1
end
end
class ViewStudent
def initialize(student)
#student = student
end
def do_something
puts "Student name: #{#student.first_name} #{#student.last_name}"
end
end
class UpdateStudent
def initialize(student)
#student = student
end
def do_something
puts "What is the student's first name?"
#student.first_name = gets.chomp
puts "What is the student's last name?"
#student.last_name = gets.chomp
puts "Updated student: #{#student.first_name} #{#student.last_name}"
end
end
choices = [ViewStudent, UpdateStudent]
student = Student.new("John", "Doe", 18)
puts "Select 1 to view student or 2 to update student."
selection = gets.chomp.to_i
obj = choices[selection - 1]
obj = obj.new(student)
obj.do_something
In the last five lines, I understand that selection = gets.chomp.to_i converts the selection options to integers, but how does that work in tandem with obj = choices[selection - 1]?
I'm also not sure what obj = obj.new(student) and obj.do_something do. It looks like a local variable is being set to create a new object with student as the argument. However, obj isn't a class or method to call on?
I can also gather that obj.do_something calls the methods defined for both ViewStudent and UpdateStudent given the selection.
I saw this, but it doesn't answer my question.
obj = choices[selection - 1] just select ViewStudent if 1 and UpdateStudent if 2 from your array by index (choices[0] or choices[1]).
Then you creating an instance of selected class (ViewStudent.new or UpdateStudent.new) and call do_something method on this instance, because this methos difined in both classes:
obj = choices[selection - 1] # obj is ViewStudent or UpdateStudent class
obj = obj.new(student) # obj is ViewStudent or UpdateStudent instance
obj.do_something # call `do something` method on instance

How can I combine two blocks to simplify my code?

Hi I am a student learning Ruby. I am using the quick start guide at ruby-lang.org, which has some examples of Ruby basics.
I studied the MegaGreeter class, and I am trying to figure out how to puts two arguments (name and age) in the same each block in order to simplify my code.
I think there would be another way. (Using regular loops instead of each.)
Calculate the array's size.
Use a loop like in C.
But I want to use the each loop. Below is my code:
class MegaGreeter
attr_accessor :name
attr_accessor :age
#Creat the object
def initialize(name=nil, age=0)
#name = name
#age = age
#tmp = Array.new()
#i = 0
end
#Say hi to everybody
def say_hi
if #name.nil?
puts "please give me the input !!"
elsif #name.respond_to?("each")
#list responding
#name.each do |name|
#tmp[#i] = "hi ~! #{name}"
#i += 1
end
#i=0
#age.each do |age|
#tmp[#i] += " and you are #{age} years old"
puts #tmp[#i]
#i += 1
end
else
puts "give me array ~"
end
end
end
a = MegaGreeter.new()
a.name = ["juno","yoonhe"]
a.age = [1,2]
a.say_hi
You can use the Array method zip to first combine your two arrays. It groups the elements by their position in the array, so the first element of the #name array will be grouped with the first element of the #age array and so on.
#name = ['Foo', 'Bar']
#age = [23, 41]
name_and_age = #name.zip(#age)
# [['Foo', 23], ['Bar' 41]]
Now the names and ages are grouped together, and you can iterate over them using each.
name_and_age.each do |name, age|
puts name, age
end
# Foo 23
# Bar 41
Putting it back into your original code:
class MegaGreeter
attr_accessor :name, :age
#Creat the object
def initialize(name = nil, age = 0)
#name = name
#age = age
end
#Say hi to everybody
def say_hi
if #name.nil?
puts "please give me the input !!"
elsif #name.respond_to?("each")
#list responding
#name.zip(#age).each do |name, age|
puts "hi ~! #{name} and you are #{age} years old"
end
else
puts "give me array ~"
end
end
end

Resources