Ruby Blackjack and loops - ruby

I am building a command line ruby blackjack game using methods. I have gotten to the point where the player can hit or stick (after having being dealt 2 cards). Right now I can't seem to make the jump to thinking logically about how to limit my player to only four hits. make
This tells me that my problem is looping - that is I am approaching the loop part of the program the wrong way.
Here is my code so far:
def blackjack
promt
end
def promt
puts "Welcome! Would you like to play a game of blackjack? Enter Yes or No"
play = gets.chomp.downcase
if play == "yes"
game_plan
elsif play =="no"
puts "That's too bad. Come back when you feel like playing"
else
puts "Sorry but I don't understand your respones. Please type and enter yes to play Or no to to quit"
blackjack
end
end
def game_plan
wants_to_play = true
hand = []
total = first_move(hand)
wants_to_play = hit_me(hand)
if wants_to_play == true
hit_me(hand)
end
end
def first_move(hand)
deal(hand)
deal(hand)
total(hand)
end
def deal(hand)
card = rand(12)
puts "You have been dealt a card with a value of #{card}"
hand << card
end
def total(hand)
total = 0
hand.each do |count|
total += count
end
puts "The sum of the cards you have been dealt is #{total}"
total
end
def hit_me(hand)
puts "Would you like to hit or stick?"
yay_or_nah = gets.chomp.downcase
if yay_or_nah == "stick" && total(hand) < 21
puts "Sorry! The sum of the cards you have been dealt is less than 21. You lost this round!"
else
deal(hand)
total(hand)
playing = true
end
end
blackjack
What I want to do is limit my player to 2 hits (after the initial first hit, which deals 2 cards). I know this is a totally annoying newbie question but I really would appreciate any feedback that would help me think of the solution in the proper manner.
PS: while I understand how loops work I am STRUGGLING with knowing how and when to implement them … so any feedback would be very much appreciated. Thank you!

Are you looking for something like that?
MAX_HITS = 2
hits = 0
loop do
break if hits > MAX_HITS
puts "Would you like to hit or stick?"
…
else
hits += 1
…
end
end

Related

Undefined Method "attack" for Player::Class

So I am trying to make a text based game with classes for an assignment. I have worked for 2 hours and could not find what the problem is.
class Rankuun
attr_accessor :rankuun_damage, :rankuun_health
def initialize
rankuun_health = 200
rankuun_damage = 100
end
def monolouge
puts 'Rankuun: "So, I see that you have lived this long. I am suprised.'
puts "Not a single libing creature has lived for this long inside my dungeon."
puts "But it's time that your endless slaughter of my brethren are halted."
puts "Now face what true fear really is!"
puts "Hoc vanitas est, et non est fere ut serves!"
puts "You see a mystical aura rise around Rankuun, and hear the shouts of agony"
puts "Rankuun has grown twice in size, and has taken the form of some kind of lich"
puts 'Rankuun: WELCOME TO DIE!"'
end
end
class Player
attr_accessor :health, :gold
def initialize
health = 100
money = 200
puts "Health: #{health}"
puts "Gold: #{money}"
end
def attack
puts "You attack the monster!"
hitmiss = 1
if hitmiss == 1
dmg = rand(5..10)
puts "You hit the monster, and do #{dmg} damage!"
monster_health = monster_health - dmg
elsif hitmiss == 2
puts "You missed!"
end
end
def guard
puts "You attempt to defend yourself"
guard = rand(1..2)
if guard == 1
counter = rand(5..10)
puts "You block the damage, and counterstrike for #{counter} damage"
monster_health = monster_health - counter
elsif guard == 2
monster_counter = rand(1..5)
puts "You try to guard, but the enemy hits harder than you expected, and you get dealt #{monster_counter}"
health = health = monster_counter
end
end
def loot
puts "You search the room and find:"
loot_item = rand (2..3)
if loot_item == 2
puts "You find some gold!"
money = money + 50
puts "Health: #{health}"
puts "Gold: #{money}"
elsif loot_item == 3
puts "You find a curious potion that seems to heal you"
health = health + 50
puts "Health: #{health}"
puts "Gold: #{money}"
end
end
def encounter
encounter = rand(1..2)
if encounter == 1
puts "A monster confronts you!"
monster = Monster.new
elsif encounter == 2
puts "There appears to be no monsters in this room"
end
end
end
class Monster
attr_accessor :monster_health, :monster_damage
def initialize
monster_health = 50
monster_damage = 10
end
def monster_attack
puts "The monster attacks you!"
end
end
puts "There has been a saying in your town for as long as you can remember:"
puts "Ne pas entrer dans le Donjon De Rankuun"
puts 'It means: "Do not enter The Dungeon of Rankuun"'
puts "Many adventurers died inside, and the only living creature in there is the man named Rankuun"
puts "He has great power over the Dungeon, reviving the dead and casting black magic"
puts "You have been selected by the village to go into the Dungeon and exterminate Rankuun"
puts "You have been given a sword, a shield, and some gold. Now you must enter:"
puts "T H E D U N G E O N O F R A N K U U N!"
puts ""
puts ""
player = Player.new
player.encounter
room1 = gets.chomp
if room1 == "attack"
player.attack
elsif room1 == "loot"
player.loot
end
It would be great if this problem were solved. Thanks for responding and aiding me in my assignment.
Welcome to the exciting world of object-oriented design. Many adventurers died inside.
I think you may have a small misunderstanding about the difference between classes and instances. If so, I strongly advise you to read about it before continuing.
You created a new instance of Player when you called Player.new. Your first mistake was not putting it in a variable.
Try something like this:
my_player = Player.new
Secondly, you are trying to call encounter on the Player class, while you should call it on the new instance.
my_player.encounter
You do the same thing inside the Monster class with Player.attack.
I could tell you how to solve each of these problems individually, but I think you would benefit more from redesigning some parts of the project to be easier to change in the future. Hopefully, most of the problems will resolve themselves along the way.
Generally speaking, the shorter a method is, the better. When you tell the Player to attack, that is all it should do. Instead, it does all sorts of things, including getting the monster to attack!
It suddenly becomes apparent that the two classes have quite a lot in common: they both attack; they both take damage, and they both die. It's time to make a superclass. (If you are not familiar with how classical inheritance works, you should learn - this truly is the perfect use case for it.)
class Character
attr_accessor :health
def attack damageable, damage
damageable.take_damage damage
end
def take_damage damage
health -= damage # Equivenent to health = health - damage
potential_death
end
def potential_death
if dead?
die
end
end
def dead?
health <= 0 # With random damage, it could be less than 0.
end
def die # overruled by subclass
end
end
The greatest advantage to doing it like this is you only have to write the code in one place, and it will work for everything. If you change your mind about a design decision, you can change it in one place and know that everything will be adjusted.
You can make a subclass similar to this:
class Monster < Character
def die
super # Call the copy of die in Character, in case it contains something important
reward killer
puts "You kill the monster..."
end
def reward rewardable
rewardable.gain_money 30
end
end
class Player < Character
def die
super # Call the copy of die in Character, in case it contains something important
puts "You died..."
game.over
end
end
(These are only examples; they are not as complete as the code you already have.)
Do you see how each method only does one thing? If you apply that principle to everything you write, it will become much easier to reuse bits and pieces.
I hope this has been useful. If you decide to stick with what you have and just fix the errors, just say so in the comments, and I'll help you with that.
Good luck!

Ruby: How to exit a function and then return to it

I'm writing a text-adventure game for exercise 36 of Learn Ruby the hard Way: http://ruby.learncodethehardway.org/book/ex36.html
I want to include 'instructions' as an option players can use anytime, but once the player exits the Room() function and enters the intructions() function, I am unsure how to return them to the appropriate room. I can have the instructions() always return player to the start after, but is there a way to get them back to the same location?
Here is a quick example, sorry it's incomplete...I'm still in the middle of building it:
puts
puts <<INTRO
"Welcome to the Cave of Indifference.
It doesn't much care for you. Beware!
There are deadly areas of this cave, but if you seek
it you may find the secret treasure and escape with your life."
INTRO
puts
puts "Type \'Instructions\' at any time for direction"
puts
sword = false
monster = true
treasure = false
def Command()
puts ">>> "
end
def dead(how)
puts how.to_s
puts "PLAYER DEAD!"
Process.exit(0)
end
def instruction()
puts "Rooms will have individual instructions"
puts "but here are some general items."
puts "west, east, north, south: goes that direction"
puts "look: look around the room"
puts "take: to take item or object"
end
def Room1()
puts "You are now at the cave entrance."
puts "You may go west or east. OR exit with your life!"
Command(); choice = gets.chomp()
if choice.downcase == "exit" && treasure = true
puts "Congratulations! You win!"
Process.break
elsif choice.downcase == "exit" && treasure = false
puts "Seriously?! Giving up already?"
puts "Fine. Here is what happens:"
dead("You stumble on your exit from the cave and trip
on a rock. The fall cracks your skull and you bleed
to death. Bye bye!")
elsif choice.downcase.include? "right"
#INPUT
elsif choice.downcase.include? "left"
#INPUT
elsif choice.downcase.include? "instructions"
instructions()
else
"That command makes no sense, try again."
end
end
Room1()
I also assume there are many issues with the code and would be very appreciative of your help, but no worries I am going to keep working on this and make it really fun to play :)
You can give the instruction method the last location.
def instruction(last_room)
#do stuff
last_room.call()
end
You would call that function like so:
instructions(method(:Room1)), where Room1 is the name of the method you want to return to.
The problem you have isn't having instructions return to Room1 (or RoomX). It'll do that without you doing anything special. What you need is something like:
#room = :Room1
while true
send(#room)
end
and then set the variable #room to control which room you're in.
It's not the greatest way in the world to do that, but it'll get you started.

Ruby script need fix

I'm having a problem with my ruby script. If anyone could help, I'd really appreciate it. The problem is that the number is stuck between 1-2; where 2 is too high and 1 is too low. The guesses should be integers only.
#!/usr/bin/ruby
def highLow(max)
again = "yes"
while again == "yes"
puts "Welcome to the High Low game"
playGame(max)
print "Would you like to play again? (yes/no): "
again = STDIN.gets.chomp
if again == 'no'
puts "Have a nice day, Goodbye"
end
end
end
#This method contains the logic for a single game and call the feedback method.
def playGame(max)
puts "The game gets played now"
puts "I am thinking of a number between 1 and #{max}." #It show what chosen by user
randomNumber = rand(max)+ 1
print "Make your guess: "
guess = STDIN.gets.chomp
feedback(guess, randomNumber)
end
#Start while loop
#Logic for feedback method. It's ganna check the guess if it's high or low.
def feedback(guess, randomNumber)
count = 1
while guess.to_i != randomNumber
count = count + 1
if guess.to_i < randomNumber
print "That's too low. Guess again: "
else
print "That's too high. Guess again: "
end
guess = STDIN.gets.chomp
end
puts "Correct! You guessed the answer in #{count} tries!"
end
highLow(ARGV[0])
Change your last line to this:
highLow(ARGV[0].to_i)
The ARGV array contains all the passed in arguments as strings, so you have to cast it to integer.

Guessing Game Ruby

So i have been learning ruby as of late and i am working on this code for practice purposes but i cannot seems to be able to solve this problem any help would be appreciate it.
This is are the guidelines i am following:
clear the screen
greet the player
explain the rules of the game to the player
generate a random number between 0 and x (x being a variable that can be set to any integer)
allow the player n number of guesses (n being a variable)
keep track of the guess history
don't count repeated guesses against the player
congratulate the player when he/she guesses correctly
alert the player when there is only one guess remaining
print the guess history at the end of the game
count number of games won IN A ROW
count number of games won in total
congratulate the play on 3 games won IN A ROW
ask if the player wants to play again
thank the player for playing games if the number of games played is greater than 2
please keep in my that this is work in progress and i have not completed all the guideline, however my questions is with one particular part of it.
here is the code:
guess = Array.new
puts guess.class
def ask()
puts "Please answer in a 'y' or 'n' only!"
puts "Would like to play again?"
end
def guess_check_against()
g = guess.last
unless guess.include?(g) != guess
count+=1
else
puts "sorry you have guessed that number before, Guess Again: "
guess << gets.to_i
count+=1
end
end
puts "what is your name?"
user= gets.chomp
puts "Hello #{user}!!"
max_user_attempts = 4
#attempt_counter = 0
directions = "\nLets play a guessing game! You have
#{max_user_attempts.to_s} guesses before you lose."
print directions
g = guess.last
win = 0
count = 0
play = true
while play == true
puts "Please tell me the max value of the random number: "
max= gets.to_i
num= rand(max)
puts "Ok. The random number is generated between 1 and " + max.to_s + "."
puts "Make your guess: "
guess << gets.to_i
guess_check_against()
#attempt_counter+=1
while guess != num && play != false
if g > num && #attempt_counter < max_user_attempts
print "That's too high. Guess again: "
guess << gets.to_i
guess_check_against()
#attempt_counter+=1
elsif g < num && #attempt_counter < max_user_attempts
print "That's too low. Guess again: "
guess << gets.to_i
guess_check_against()
count+=1
#attempt_counter+=1
else
break
end
end
if #attempts_counter >= max_user_attemtps
puts "Sorry! you lost! Try Again"
break
else #attempts_counter <= max_user_attempts
puts "Correct! You guessed the answer in " + count.to_s + " tries!"
win+=1
end
if win >= 3
puts "Congratulation! you have #{win} number of games in a row"
ask()
answer = gets.chomp!
elsif win < 3
ask()
answer = gets.chomp!
else
break
end
if answer == 'n'
play = false
break
end
if answer == 'y'
play = true
count = 0
end
end
puts "Ok. Goodbye!!"
and here is the error i keep receiving when i try to run this program:
guessing_game.rb:12:in `guess_check_against': undefined local variable or method `guess' for main:Object (NameError)
from guessing_game.rb:45:in `<main>'
when i try to use irb to run the same scenario it works completely fine.
i can not figure out what i am doing wrong, please help!!
The method definition
def guess_check_against()
g = guess.last
...
end
has its own scope, and the local variable
guess = Array.new
that you defined outside of it, is not accessible inside the method definition. guess is not defined inside the method definition. You can change the code so that the method takes that as an argument, and it will become accessible.

Ruby Loops with Grandma

Okay, I'm trying to write a ruby simulation of my grandmother. I can't quite get the loop to work the way I'd like though. I want granny to respond with
"OH, THAT REMINDS ME OF BACK IN (random year) ..."
when you answer her in all caps but I also want her to respond with
"WHAT'D YOU SAY????"
when you don't use all caps. I can get each one to work separately but I can't seem to make a continuous loop of granny with her crazy responses. Here's the code:
puts 'HELLO SONNY! WHAT\'S NEW IN THE WHO\'S IT WHAT\'S IT?'
response = gets.chomp
while response == response.upcase
puts 'OH, THAT REMINDS ME OF BACK IN ' + (rand(50) + 1905).to_s + '...'
response = gets.chomp
end
while response != response.upcase
puts 'WHAT\'D YOU SAY????'
response = gets.chomp
end
Any ideas?
The issue is that once you exit the first while loop, you're never returning back to it. Try something like this:
while true
response = gets.strip
if response == response.upcase
puts msg1
else
puts msg2
end
end
That'll run forever, until you decide to kill virtual-granny with Ctrl-C.
This program works, though Im a noob so it may not be the best way. Also my math is more creative then practical, the other guys is way better. :)
puts 'Talk to your grandma!'
while true
say = gets.chomp
if say == say.downcase
puts 'WHAT DID YOU SAY? SPEAK UP!'
else say == say.upcase
puts "NO HONEY, NOT SINCE 19" + (rand(90) + 10).to_s
end
break if say == 'bye'.upcase
end

Resources