Ruby - problems with nilClass [closed] - ruby

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am having trouble getting this to work. The error I get is:
114 in 'numberstash' : undefined method 'cards' for nil:Nilclass (No Method Error).
It is for a Blackjack game. I spent several hours trying to fix this code, including making a bunch of test scripts to figure it out. However, I have had no luck. This works on my test script, however it doesn't work on the current script:
class Card
attr_accessor :suit, :value
def initialize(suit, value)
#suit = suit
#value = value
end
def to_s
"#{value} of #{suit}"
end
end
class Deck
attr_accessor :cards
def initialize(number_of_decks)
#cards = []
num = number_of_decks
counter = 0
while counter < num
['H','C', 'S', 'D'].product(['2','3','4','5','6','7','8','9','10','J','K','Q','A']).each do |arr|
#cards << Card.new(arr[0], arr[1])
end
counter += 1
end
end
end
class Player
attr_accessor :cards, :testvalue
def initialize
#cards = []
end
end
class Dealer
attr_accessor :cards
#cards = []
end
class Blackjack
attr_accessor :deck, :player, :dealer
def calculate arr
new = arr.map { |e| e[1] }
sum = 0
ace = 0
new.each { |value|
if value == 'A'
sum += 1
ace = 1
elsif value.to_i == 0
sum += 10
else
sum += value.to_i
end
}
if ace = 1 && sum + 10 <= 21
ace = 0
sum = sum + 10
end
end
def initialize
deck = Deck.new(4)
##deck = #deck.shuffle
player = Player.new()
dealer = Dealer.new()
end
def dealcards
#puts 'dealcards'
#player.cards << deck.cards.pop
#dealer.cards << deck.cards.pop
end
def start
#dealcards
#player_turn
#dealer_turn
#compare?
#play again?
numberstash
end
def numberstash
#player.cards << deck.cards.pop
puts player.cards
#dealer.cards << deck.cards.pop
end
end
game = Blackjack.new()
game.start
My question is, why am I getting the above mentioned error?

Everywhere in Blackjack that you use player, you mean #player, for example in Blackjack#initialize:
#player = Player.new()
and Blackjack#numberstash:
puts #player.cards
# identifies instance variables, the kinds of thing accessed by attr_accessor.

Related

Undefined function make_card Ruby

I am doing a practice problem black jack card game in ruby, references I am using are
https://medium.com/quick-code/using-ruby-classes-to-implement-a-game-of-blackjack-535a786c417
I am getting error that says undefined method "make_card"
Code for my Deck Class
class Deck
def initialize
#faces = [*(2..10),'Jack','Queen','King','Ace']
#suits = ['clubs','spades','hearts','diamonds']
#cards = []
#faces.each do |face|
if face.class == "Integer"
value = face
elsif face == 'Ace'
value = 11
else
value = 10
end
#suits.each do |suit|
#cards << Card.new(face,suit,value)
end
end
#cards.shuffle!
end
def make_card(participant)
fresh_card = Card.new(face,suit,value)
participant.turn << fresh_card
participant.total = participant.total + fresh_card.value
end
def deal(number,participant)
number.times{#cards.shift.make_card(participant)}
end
end
As both methods are in same class I am still getting that error
Solved it by placing method in Card class and accessing it via its instance variable
class Card
attr_accessor :face, :suit, :value
def initialize(face,suit,value)
#face = face
#suit = suit
#value = value
end
def make_card(participant)
fresh_card = Card.new(face,suit,value)
participant.turn << fresh_card
participant.total = participant.total + fresh_card.value
end
end
class Deck
def initialize
#faces = [*(2..10),'Jack','Queen','King','Ace']
#suits = ['clubs','spades','hearts','diamonds']
#cards = []
#faces.each do |face|
if face.class == Integer
value = face
elsif face == 'Ace'
value = 11
else
value = 10
end
#suits.each do |suit|
#cards << Card.new(face,suit,value)
end
end
#cards.shuffle!
end
def deal(number,participant)
number.times{#cards.shift.make_card(participant)}
end
end

Can we add items and quantity to a list through shovel approach and call that list outside a class?

Write a simple DSL for creating a shopping list. We should be able to specify the item name and quantity..
Something like.
sl = ShoppingList.new
sl.items do
add("Toothpaste",2)
add("Computer",1)
I am trying to add items and quantity both to a list, but facing trouble using shovel operation and also faced error to call this list outside the class. Can I list these items without using hash ?
class Array
def initialize
#list = []
#total = 0
end
def add(items, quantity)
if #list.include?(items) == false
#list << items
else #list.include?(items) == true
#list
end
#total.each {|x| quantity += x }
end
def items(&block)
#list.each(&block)
end
def total
#total
end
def display
#list
end
end
sl = Array.new
sl.items do
add('Toothpaste', 2)
add('Computer', 1)
add('Toothpaste', 3)
end
puts sl.list
puts sl.total
Expected Result :
s.list # => Should display list of items with quantity.
s.total # => Should display total of all quantities.
There was an attr_reader and attr_accessor missing in your code and the loop was not working (at least for me). With those attr_reader and attr_accessor you can get rid of at least two methods.
I wonder why you don't want to use a hash ..
Here's some working code, no hashes but an array of arrays, in my implementation counting the total numbers of items must be done at the end when all items are added.
class ShoppingList
attr_reader :list
attr_accessor :total
def initialize
#list = []
#total = 0
end
def add(items, quantity)
if #list.include?(items) == false
#list << [items, quantity]
else
#list
end
end
def total_number_of_items
quantities = list.map { |item| item[1] }
total = quantities.inject(0){|sum,x| sum + x }
end
end
sl = ShoppingList.new
sl.add('Toothpaste', 2)
sl.add('Computer', 1)
sl.add('Toothpaste', 3)
puts sl.list
puts sl.total_number_of_items
P.S. I renamed the method from Array to ShoppingList.
I know, this was not the question, but isn't that super-easy with a hash?
class ShoppingList
attr_reader :list
def initialize
#list = {}
end
def add(product_type, quantity)
if list[product_type].nil?
list[product_type] = quantity
else
list[product_type] += quantity
end
end
end
sl = ShoppingList.new
sl.add('Toothpaste', 2)
sl.add('Computer', 1)
sl.add('Toothpaste', 3)
pp sl.list.inspect
pp sl.list.keys.inspect
pp sl.list.values.inspect
Result:
"{\"Toothpaste\"=>5, \"Computer\"=>1}"
"[\"Toothpaste\", \"Computer\"]"
"[5, 1]"

Possible moves on a chess board, using instance from one class in another.

I'm working on making a chess game. I want to keep everything that has to do with possible moves inside each type of pieces class. In order to do this I need to refer back to #board[][]. The commented section of code in the possible_moves method is what I would like to do, except it does not work and throws an error.
class Board
attr_accessor :board, :choice
def initialize
#board = Array.new(8){Array.new(8," ")}
#choice = choice
end
def set_board
#board[0][2] = Bishop.new([0,2],false)
end
end
class Bishop
attr_accessor :x_position, :y_position, :piece, :color, :moves
def initialize(position,is_white)
#x_position = position[0]
#y_position = position[1]
#piece = is_white ? "♝" : "♗"
#color = is_white ? "white" : "black"
#moves = [[+1,-1],
[+1,+1],
[-1,+1],
[-1,-1]]
end
def possible_moves
move_list = Array.new
#moves.each do |moves|
x = #x_position
y = #y_position
loop do
x += moves[0]
y += moves[1]
break if x.between?(0,7) == false
break if y.between?(0,7) == false
# This is where I want to refer back to #board from the Board class.
# if #board[x][y].color.....
move_list << [x,y]
#end
end
end
p move_list
end
end
You can pass the board into the Bishop constructor:
class Bishop
attr_reader :board
# etc.
def initialize(position,is_white,board)
#board = board.board # or just #board = board and you can fetch the matrix later
# etc.
end
end
class Board
# etc.
def set_board
#board[0][2] = Bishop.new([0,2],false, self)
end
end

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

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