Simple Ruby Classes and Objects program - ruby

I am writing a script where I have to create an Orange Tree and every time I run through the specified method the tree's height goes up, tree's age goes up, and number of oranges on the tree also increases. But after a certain time (it's up to me) the tree is supposed to die. So in my program I decided that if the tree is 15 feet or more it should be dead. Now every time I run through the method the height, age, and number of oranges go up and once the height goes past 15 feet I get a message saying "Tree is dead" but the height keeps increasing. I want it to stop once the tree is dead. Also how can I add something different every time the user runs the method to go into the next year? For example right now every year the height goes up by 3, number of oranges goes up by 4 and age goes up by 1 as it should. How do I make the height and number of oranges go up by a random number every year? (not too large) here is my code.
class OrangeTree
def initialize
#tree_height = 0
#no_oranges = 0
#tree_age = 0
end
def firstYear
if #tree_height >= 15 then
puts "Tree is dead"
end
#tree_height = #tree_height + 3
puts "Your orange tree is " + #tree_height.to_s + " feet tall!"
#tree_age = #tree_age + 1
puts "Your orange tree is " + #tree_age.to_s + " year old!"
#no_oranges = #no_oranges + 4
puts "Your orange tree has " + #no_oranges.to_s + " oranges!"
end
def pickOrange
if #no_oranges == 0 then
puts "You can't pick any oranges yet, you have to wait at least a year!" else
puts "How many oranges do you want to taste?" + " Remember you only have " + #no_oranges.to_s + " oranges on your tree!"
pick2 = gets.chomp.to_i
puts "The oranges taste delicious and very refreshing!"
#no_oranges = #no_oranges - pick2
end
end
def isDead
if #tree_height >= 15 then
return true else
return false
end
end
def countOranges
puts "Current number of oranges: " + #no_oranges.to_s
end
end

You have to modify your firstYear method in OrangeTree class to get the height and number of orange to be incremented as a parametre and return from the method when tree height reached a certain value.
class OrangeTree
def initialize
#tree_height = 0
#no_oranges = 0
#tree_age = 0
end
def firstYear(tree_height_increment, fruit_increment)
if #tree_height >= 15 then
puts "Tree is dead"
return
end
#tree_height = #tree_height + tree_height_increment
puts "Your orange tree is " + #tree_height.to_s + " feet tall!"
#tree_age = #tree_age + 1
puts "Your orange tree is " + #tree_age.to_s + " year old!"
#no_oranges = #no_oranges + fruit_increment
puts "Your orange tree has " + #no_oranges.to_s + " oranges!"
end
end
Now, Everytime you make a call to firstYear method, you can specify the value with which you want to increase tree's height and fruit's values.

Related

Ruby Number Guessing Game

I have tried to make a number guessing game using ruby but it seems to be looping all over again after the user gets the correct answer, here's my code and thanks in advance!
require './input_functions'
def check (rno,input)
x = 1
while (x == 1)
y = 0
if (rno > input)
puts("Try a bigger number")
input = gets.chomp.to_i
y = y + 1
x = 1
else
if (rno < input)
puts("Try a smaller number")
input = gets.chomp.to_i
y = y + 1
x = 1
else
if(rno == input)
puts("Bingo!")
x = 0
end
end
end
end
return
end
def main
rno = rand(100)
input = read_integer("Enter an integer between 0 and 100: ")
check(rno,input,y)
times = check(rno,input,y)
puts ("You have tried " + times.to_s + " times.")
end
main
The main problems are:
You call check method two times within main method, you need to remove the first one.
You need to move y = 0 out of while loop to be able to return it.
Tried to simplify your code a bit, and you could try to improve it even more.
def check(rno, input)
x = 1
y = 0
while x == 1
if rno == input
puts "Bingo!"
x = 0
else
if rno > input
puts "Try a bigger number"
else
puts "Try a smaller number"
end
input = gets.chomp.to_i
y = y + 1
end
end
return y
end
def main
rno = rand(100)
input = read_integer("Enter an integer between 0 and 100: ")
times = check(rno, input)
puts ("You have tried " + times.to_s + " times.")
end

Can you someone support me to use ordinal in while loop in Ruby?

I am having a difficult time figuring ordinal in the program below. I need to use the ordinal in the loop statement. When I print statement, It print out backward like 3rd, 2nd, 1st, and so on.
I tried changing my loop statment from (number -= 1) to (number += 1) but that would make infinite while loop. Can someone give me feedback on what I can do here? Thank you.
class Integer
def ordinal
case self % 10
when 1
return "#{self}st"
when 2
return "#{self}nd"
when 3
return "#{self}rd"
else
return "#{self}th"
end
end
end
puts "Let's play a numbers game."
print "How many numbers would you like to enter? >"
number = gets.chomp.to_i
while number >= 1
print "\n\nEnter the #{number.ordinal} positive integer:"
user_int = gets.chomp.to_i
number -= 1
if user_int % 3 == 0
print "#{user_int} is divisible by 3."
else
print "#{user_int} is not divisible by 3."
end
end
puts "\n\nEnd of the Game"
First I'd suggest you to patch Integer class in this way:
module MyIntegerPatch # <------ a custom module
def to_ordinal # <------ to_ordinal is better
case self % 10
when 1
return "#{self}st"
when 2
return "#{self}nd"
when 3
return "#{self}rd"
else
return "#{self}th"
end
end
end
Integer.include MyIntegerPatch # <------ "patch" the class
Then for your loop just use a Range:
(1..number).each do |n| # <---- a range here
puts "\n\nEnter the #{n.to_ordinal} positive integer:"
user_int = gets.chomp.to_i
if user_int % 3 == 0
puts "#{user_int} is divisible by 3."
else
puts "#{user_int} is not divisible by 3."
end
end
Maybe you can try below, use the ruby style times to control
class Integer
def ordinal
case self % 10
when 1
"#{self}st"
when 2
"#{self}nd"
when 3
"#{self}rd"
else
"#{self}th"
end
end
end
puts "Let's play a numbers game."
print 'How many numbers would you like to enter? >'
number = gets.chomp.to_i
number.times do |time|
print "\n\nEnter the #{(time + 1).ordinal} positive integer:"
user_int = gets.chomp.to_i
if user_int % 3 == 0
print "#{user_int} is divisible by 3."
else
print "#{user_int} is not divisible by 3."
end
end
puts "\n\nEnd of the Game"

How do I update one element in an array and show new version of my array in the tictactoe grid?

This is a tictactoe game. When a player chooses a grid via a number, it is supposed to update the picked number with X or O, and then show the updated grid. Unfortunately, it continues to output the same default grid of numbers. I used map! but it does not work. If I switch #player1 : x to x: #player1, it changes the entire array to X or O.
Once I figure this out, the win method will be the next task to check. Will win work to determine the winning combinations?
#a = [1,2,3,4,5,6,7,8,9]
def game
#game_board = "#{#a[0]}|#{#a[1]}|#{#a[2]}\n" "------\n" "#{#a[3]}|#{#a[4]}|#{#a[5]}\n" "------\n" "#{#a[6]}|#{#a[7]}|#{#a[8]}\n"
#game_board
end
def secondchoice
if #player1 == "X"
#player2 = "O"
elsif #player1 == "O"
#player2 = "X"
else puts "please pick a valid number"
end
end
def start
puts " Player One, Pick Your Tic or Toe , X or O"
#player1 = gets.chomp.upcase
#player2 = secondchoice
puts "Player one is #{#player1}"
puts "Now Player Two is #{#player2}"
end
def player_turns
# player 1 gets then player 2 gets until game over == true
# nine total moves using a loop with a counter will work
moves = 1
while moves < 10
if moves.odd?
puts #game_board
puts "its player One's turn! place #{#player1} on the board by picking a number: "
cell = gets.chomp
#a.map! {|x|x == cell ? #player1 : x}
moves += 1
unless check_win == true
end
else
puts #game_board
puts "its player Two's turn! place #{#player2} on the board by picking a number: "
kell = gets.chomp
#a.map! {|x|x == kell ? #player2 : x}
moves += 1
unless check_win == true
end
end
end
end
def win
# 10 turns(count) with no combination is a draw
return [[#a[0]+ #a[1] + #a[2]],[#a[3] + #a[4] + #a[5]],[#a[6] + #a[7] + #a[8]],[#a[0]+ #a[3] + #a[6]],[#a[1] + #a[4] + #a[7]],[#a[2] + #a[5]+ #a[8]],[#a[0]+ #a[4] + #a[8]],[#a[2] + #a[4] + #a[6]]]
#game_over check if player has 3 in a row
end
# Create a loop that gives player turns. Player one then player two until a draw or three in row
def check_win
win.each do |arr|
str = arr.join
if str == "xxx"
puts "X Wins!"
return true
elsif str == "ooo"
puts "O Wins!"
return true
end
end
return false
end
while check_win != true
start
game
player_turns
end
It's not clear why map! would factor in here. A simple array manipulation is all that's required:
#a[cell.to_i - 1] = #player2
Specifying the cells as zero indexed would make this easier.
There's a lot of evidence of going against the grain here that's made for a ton more code than necessary. For example, variables like #player1 and #player2 are usually a sign of bad design. Why not #players = %w[ X O ]? That alone solves a lot of problems if you apply that array throughout your code instead of having per-player variables. Each turn: #players.unshift(#players.pop)

How to Use Hashes to Store methods in Ruby?

I was wondering if anyone could explain to me why I can't use my Hash($player_x_command_list) to access my player_x_move(position) method? What's the correct way of doing this?
What I am trying to do is, create a Hash that lets the user enter input and it reflecting back to my methods in my class.
I have tried various ways of altering so that the code could work correctly but nothing works.
I'm getting the error:
undefined method `player_x_move' for Game:Class (NoMethodError)
Does that mean hashes can't store methods?
Here's my code:
#Tic Tac Toe Game
#The format is the below: where index 0 represents top left and index 8 represents bottom right
#goes 0,1,2
# 3,4,5
# 6,7,8
#"e" is for empty. "x" is for Player X moves and "o" is for Player O moves
class Game
##player_x_win_count = 0
##player_o_win_count = 0
def initialize
#board = Array.new(9, "e")
#move_number = 0
end
def get_names
puts "Hi Welcome to my Tic Tac Toe Game. The board looks like this:
|TL|TM|TR|
|ML|MM|MR|
|BL|BM|BR|
Each position of the Tic Tac Toe board is represented by two letters. To \"X\" or \"O\" a position, just input the two letters in CAPS like \"MM\"
The command list is as follows:
TL = top left
TM = top mid
TR = top right
ML = mid left
MM = mid mid
MR = mid right
BL = bottom left
BM = bottom mid
BR = bottom right
board = to view the board
new game = to clean the board and create a new game (note that this command should only be used when you don't want to continue on the current game. The game automatically creates a new game if a winner, loser, or draw is declared)
"
puts "Please Enter PlayerX's name. He/she will be using X's to mark the board."
#player_x = gets.chomp
puts "Please Enter PlayerO's name. He/she will be using O's to mark the board."
#player_o = gets.chomp
self.new_round
end
$player_x_command_list = {"TL" => self.player_x_move(0), "TM" => self.player_x_move(1), "TR" => self.player_x_move(2), "ML" => self.player_x_move(3), "MM" => self.player_x_move(4),
"MR" => self.player_x_move(5), "BL" => self.player_x_move(6), "BM" => self.player_x_move(7), "BR" => self.player_x_move(8), "board" => self.board, "new game" => self.clean_board,
"win count" => self.win_count}
$player_o_command_list = {"TL" => self.player_o_move(0), "TM" => self.player_o_move(1), "TR" => self.player_o_move(2), "ML" => self.player_o_move(3), "MM" => self.player_o_move(4),
"MR" => self.player_o_move(5), "BL" => self.player_o_move(6), "BM" => self.player_o_move(7), "BR" => self.player_o_move(8), "board" => self.board, "new game" => self.clean_board,
"win count" => self.win_count}
def enter_command_player_x
puts "Please input your command, #{#player_x} aka PlayerX"
command = gets.chomp
$player_x_command_list[command]
end
def enter_command_player_o
puts "Please input your command, #{#player_o} aka PlayerY. Type \"help\" to see a full list of commands"
command = gets.chomp
$player_o_command_list[command]
end
def new_round
puts "So who wants to go first this round"
went_first_this_round = gets.chomp
if went_first_this_round == #player_x
self.enter_command_player_x
elsif went_first_this_round == #player_o
self.enter_command_player_o
else
puts "Not a valid name. Please enter one of the player's names"
end
end
def board
print "|#{#board[0]}|#{#board[1]}|#{#board[2]}|\n|#{#board[3]}|#{#board[4]}|#{#board[5]}|\n|#{#board[6]}|#{#board[7]}|#{#board[8]}|"
end
def player_x_move(position)
if #board[position] == "x" || #board[position] == "o"
return "That move was invalid as someone has already moved there. Please enter a valid move"
end
#board[position] = "x"
#move_number += 1
puts "That was move number #{#move_number} and the current board looks like: "
self.board
self.check_game
puts "Now it is #{player_o}'s turn. #{player_o} please input your next command."
self.enter_command_player_o
end
def player_o_move(position)
if #board[position] == "x" || #board[position] == "o"
return "That move was invalid as someone has already moved there. Please enter a valid move"
end
#board[position] = "o"
#move_number += 1
puts "That was move number #{#move_number} and the current board looks like: "
self.board
self.check_game
puts "Now it is #{player_x}'s turn. #{player_x} please input your next command"
self.enter_command_player_x
end
def check_game
triple_x = "xxx"
triple_o = "ooo"
if #move_number == 9
#move_number = 0
self.clean_board
return "The board is completely filled up. Looks like this is a draw. This is Game Over. Make a new game by setting any variable = to new.Game and using that variable to play"
elsif #board[0] + #board[1] + #board[2] == triple_x
##player_x_win_count += 1
#move_number = 0
self.clean_board
return "Player X Wins"
elsif #board[3] + #board[4] + #board[5] == triple_x
##player_x_win_count += 1
#move_number = 0
self.clean_board
return "Player X Wins"
elsif #board[6] + #board[7] + #board[8] == triple_x
##player_x_win_count += 1
#move_number = 0
self.clean_board
return "Player X Wins"
elsif #board[0] + #board[3] + #board[6] == triple_x
##player_x_win_count += 1
#move_number = 0
self.clean_board
return "Player X Wins"
elsif #board[1] + #board[4] + #board[7] == triple_x
##player_x_win_count += 1
#move_number = 0
self.clean_board
return "Player X Wins"
elsif #board[2] + #board[5] + #board[8] == triple_x
##player_x_win_count += 1
#move_number = 0
self.clean_board
return "Player X Wins"
elsif #board[0] + #board[4] + #board[8] == triple_x
##player_x_win_count += 1
#move_number = 0
self.clean_board
return "Player X Wins"
elsif #board[2] + #board[4] + #board[6] == triple_x
##player_x_win_count += 1
#move_number = 0
self.clean_board
return "Player X Wins"
#now check if Player O Wins
elsif #board[0] + #board[1] + #board[2] == triple_o
##player_y_win_count += 1
#move_number = 0
self.clean_board
return "Player O Wins"
elsif #board[3] + #board[4] + #board[5] == triple_o
##player_y_win_count += 1
#move_number = 0
self.clean_board
return "Player O Wins"
elsif #board[6] + #board[7] + #board[8] == triple_o
##player_y_win_count += 1
#move_number = 0
self.clean_board
return "Player O Wins"
elsif #board[0] + #board[3] + #board[6] == triple_o
##player_y_win_count += 1
#move_number = 0
self.clean_board
return "Player O Wins"
elsif #board[1] + #board[4] + #board[7] == triple_o
##player_y_win_count += 1
#move_number = 0
self.clean_board
return "Player O Wins"
elsif #board[2] + #board[5] + #board[8] == triple_o
##player_y_win_count += 1
#move_number = 0
self.clean_board
return "Player O Wins"
elsif #board[0] + #board[4] + #board[8] == triple_o
##player_y_win_count += 1
#move_number = 0
self.clean_board
return "Player O Wins"
elsif #board[2] + #board[4] + #board[6] == triple_o
##player_y_win_count += 1
#move_number = 0
self.clean_board
return "Player O Wins"
else
return "no one has WON YET! Continue your GAME!!"
end
end
def clean_board
#board = Array.new(9, "e")
end
def win_count
puts "So far Player X has won #{##player_x_win_count} times and Player O has won #{##player_o_win_count} times."
end
end
a = Game.new
a.get_names
You have a few things wrong here:
Your scope is wrong. When defining the hash, self is the class, not the instance of the class that you want to operate on.
When you create the hash, the value of the hash is going to be return value of the player_x_move etc method at the time it was defined.
You can simplify this a lot by using case.
def enter_command
puts "Please input your command, #{#player_x} aka PlayerX"
command = gets.chomp
case command
when "TL"
player_x_move(0)
when "TM"
player_x_move(1)
# etc
else
puts "#{command} is not a valid command."
end
end
You can also simplify your code further by creating methods that accept parameters like enter_command, player_move, and then passing the player to operate on to them. This prevents you from having to duplicate each of your methods for each player.
Something else you could consider is just looking up the index of the move based on the command given:
COMMAND_POSITIONS = %w(TL TM TR ML MM MR BL BM BR)
def enter_command(player)
puts "Please input your command, #{player}"
command = gets.chomp
case command
when *COMMAND_POSITIONS
player_move player, COMMAND_POSITIONS.index(command)
when "board"
board
when "new game"
clean_board
when "win count"
win_count
else
puts "#{command}" is not a valid command
end
end
Hashes can not store methods. Methods aren't objects, but can be converted to Procs. Method definitions return nilchanged since this writing. However, you can store a Proc or a lambda. You can also store the return (evaluation) of a method.
Here is an example of how you can store a Proc to a Hash that was derived from a method.
>> def hello(name)
>> "Hello #{name}!"
>> end
=> nil
>> my_stored_methods = {:hello => method(:hello).to_proc}
=> {:hello=>#<Proc:0x816f604 (lambda)>}
>> my_stored_methods[:hello].call("World")
=> "Hello World!"
Do not let the stroop effect of me calling the hash "my_stored_methods" lead you to believe that there is actually a real method stored there. It is lambda (a specialized Proc) stored in the hash, and used as appropriate. Indeed, had I not used .to_proc there, it would hold a Method instance.
Also, this solution does not grow with the development of the open method, if the method were to change, the Proc stored in the hash would continue to work as the method did at the point when the method was stored as a Proc.
As #AndrewMarshall reminds me, I could have left it as a Method instance. This still will not "store" the method itself, as when the method changes, the result will still be the historical behavior of the source method as it was when stored. It also provides for a stronger "Stroop effect" in that you may mistakenly think that an actual method is stored there. It simply is not.

Public key encryption demo in Ruby

I wrote up the ruby script below to help my students understand public key encryption. I followed the "pencil and paper" method shown here: http://sergematovic.tripod.com/rsa1.html
This works fine as long as 29 isn't chosen as either p or q. If 29 is picked, it hangs on calculating the secret key. Can anyone tell me why that is?
#!/usr/bin/env ruby -wKU
#initialize
primes, p, q, n, z, k, j, m,e,d = nil
def prime
primes = [2,3,5,7,11,13,17,19,23,29,31]
primes.sample
end
#pick p
p= prime
puts "p: " + p.to_s
#pick q
q=p
while p==q
q = prime
end
puts "q: " + q.to_s
#find n
n=p*q
puts "n: " + n.to_s
#find z
z=(p-1)*(q-1)
puts "z: " + z.to_s
#pick a relative prime of the totient
k=7
puts "k: " + k.to_s
#calculate secret key
j=0
while j*k % z != 1
j+=1
end
puts "j: " + j.to_s
#message
m=16
puts "Message: " + m.to_s
#encrypt
e = m**k % n
puts "Encrypted: " + e.to_s
#decrypt
d = e**j % n
puts "Decrypted: " + d.to_s
When 29 is chosen as p or q, z has 28 as a factor, and thus k = 7 is not a relative prime of the totient as your comment claims!
(This means j*k % z is always a multiple of 7, so your loop never terminates.)

Resources