How to update hashmap value based on a conditional statement - ruby

I need help updating the value of my HashMap. The idea is that the user will input the Rover Direction as N. The user then inputs the behaviour as L (for left). The move_left method then updates the Hashmap key "D" to equal "W" instead of the "N" which the user inputs. However, this piece of code is not updating it to "W". Any help would be great. I am an absolute beginner, so any recommendations would be great!
def rover_direction
puts " \n Please input the direction which the rover is facing
(N,E,S,W): "
user_input = gets.chomp.upcase
#direction = {"D" => user_input}
end
def rover_behaviour
puts " \n Please input the behaviour of the rover(L,R & M): "
input = gets.chomp.upcase
#behaviour = input.scan /\w/
if #behaviour[0] == "L"
move_left
elsif #behaviour[0] == "R"
move_right
elsif #behaviour[0] == "M"
move_forward
end
end
#move rover left as per behaviour input
def move_left
if #direction[0] == "N"
#direction.update("D") { |key, user_input| user_input == W }
elsif #direction[0] == "W"
#direction.update("D") { |key, user_input| user_input == "S" }
elsif #direction[0] == "S"
#direction.update("D") { |key, user_input| user_input == "E" }
elsif #direction[0] == "E"
#direction.update("D") { |key, user_input| user_input == "N" }
end
end

Related

transfer functions into classes and arrays

This is the code that I wanted to make use of the repeated code by placing it at another function and storing the variables to that other function. I am not really new at this function type so I really need Some help, thank you so much for helping me.
def main
marks = 0
puts "1. What does the == operator do?"
puts "(a) calculates an arithmetic solution."
puts "(c) checks for e"
puts "Your answer: "
begin
answer = gets.chomp
end while (answer != 'a' && answer != 'b' && answer != 'c' && answer != 'd')
if answer == 'c'
score += 1
puts "Correct "
else
puts "Wrong "
end
puts "2. Which is NOT a C keyword?"
puts "(a) when"
puts "(b) const"
puts "(c) unsigned"
puts "Your answer: "
begin
answer = gets.chomp
end while (answer != 'a' && answer != 'b' && answer != 'c' && answer != 'd')
if answer == 'a'
score += 1
puts "Correct "
else
puts "Wrong "
end
puts "3. In function call, the actual parameters are separated by"
puts "(a) semicolons"
puts "(b) colons"
puts "(c) commas"
puts "Your answer: "
note
answer = gets.chomp
if answer != 'a' && answer != 'b' && answer != 'c' && answer != 'd'
if answer == 'c'
score += 1
puts "Correct "
else
puts "Wrong "
end
end
main
this isn't an easy step but, as per #BroiSatse's comments, creating the different aspects of the object as classes:
Defining an object to hold possible answers
class Answer
attr_accessor :text, :correct
def initialize text, correct
#text = text
#correct = correct
end
end
Defining an object to hold questions, which will contain an array of possible answers
class Question
attr_accessor :text, :answers
def initialize text
#text = text
#answers = []
end
end
Defining the "Quiz" class, which contains the score, and an array of questions. it also includes a routine to loop through the questions and answers stored in the quiz
class Quiz
attr_accessor :questions, :score
def initialize
#questions = []
#score = 0
end
def ask_questions
#questions.each_with_index do |question, i|
puts "#{i+1}. #{question.text}"
question.answers.each_with_index do |answer,i|
a_letter = (i + 'a'.ord).chr
puts "(#{a_letter}) #{answer.text}"
end
while true
puts "Your answer: "
user_answer = gets.chomp
break if (user_answer&.ord - 'a'.ord)&.between?(0, question.answers.count-1)
end
if (question.answers[(user_answer.ord - 'a'.ord)]&.correct)
#score += 1
puts "Correct \tYour score is now " + #score.to_s
else
puts "Wrong \tYour score is still " + #score.to_s
end
end
end
end
Use the new classes/objects
Now that the classes are set up, we can create our "Quiz":
quiz=Quiz.new
question = Question.new("What does the == operator do?")
question.answers << Answer.new('calculates an arithmetic solution.', false)
question.answers << Answer.new('assigns a value to a variable.', false)
question.answers << Answer.new("checks for equality", true)
question.answers << Answer.new("draws the '=' character", false)
quiz.questions << question
question = Question.new("Which is NOT a C keyword?")
question.answers << Answer.new('when', true)
question.answers << Answer.new('const', false)
question.answers << Answer.new('unsigned', false)
question.answers << Answer.new('do', false)
quiz.questions << question
question = Question.new("In function call, the actual parameters are separated by")
question.answers << Answer.new('semicolons', false)
question.answers << Answer.new('colons', false)
question.answers << Answer.new('commas', true)
question.answers << Answer.new('space', false)
quiz.questions << question
and finally run the "ask_questions" routine
quiz.ask_questions
demo output
2.7.2 :124 > quiz.ask_questions
1. What does the == operator do?
(a) calculates an arithmetic solution.
(b) assigns a value to a variable.
(c) checks for equality
(d) draws the '=' character
Your answer:
c
Correct Your score is now 1
2. Which is NOT a C keyword?
(a) when
(b) const
(c) unsigned
(d) do
Your answer:
c
Wrong Your score is still 1
3. In function call, the actual parameters are separated by
(a) semicolons
(b) colons
(c) commas
(d) space
Your answer:
c
Correct Your score is now 2
this is my code is it alright or too sloppy
class Question
attr_accessor :prompt, :answer
def initialize(prompt, answer)
#prompt = prompt
#answer = answer
end
end
p1 =
"1. What does the == operator do?\n
(c) checks for equality\n
(d) draws the '=' character\n
Your answer: \n"
p2 =
"1. What does the == operator do?\n
(b) assigns a value to a variable.\n
(c) checks for equality\n
(d) draws the '=' character\n
Your answer: "
p3 =
"3. the actual parameters are separated by\n
(b) colons\n
(c) commas\n
Your answer: "
questions = [
Question.new(p1, "c"),
Question.new(p2, "a"),
Question.new(p3, "c"),
]
def run_test(questions)
answer = ""
score = 0
for question in questions
puts question.prompt
answer = gets.chomp
(answer != 'a' && answer != 'b' && answer != 'c' && answer != 'd')
if answer == question.answer
score += 1
puts "Correct " =
else
puts "Wrong "
end
end
end
run(questions)

Rock, Paper, Scissor Ruby

Error:
syntax error, unexpected tIDENTIFIER, expecting end-of-input end whlie
continue == "N"
I checked all the code, but I still don't get it.
Should I add the end code after while continue == "N"?
begin
puts "|===============================================|"
puts "|Welcome to Rock Paper Scissors!!! |"
puts "|===============================================|"
begin
puts "please choose one of the following: R / P / S"
user_input = gets.chomp.upcase
end while !["R", "P", "S"].include?(user_input)
com_input = ["R", "P", "S"].sample
puts "You:#{user_input} Com:#{com_input}"
if user_input = "R" && com_input = "S" || user_input = "S" && com_input = "P" || user_input = "P" && com_input = "R"
puts "Result:You win"
elsif com_input = "R" && user_input = "S" || com_input = "S" && user_input = "P" || com_input = "P" && user_input = "R"
puts "Result:You lose"
else
puts "Result:Draw"
end
begin
puts "Play Again?: Y / N"
continue = gets.chomp.upcase
end while !["Y", "N"].include?(continue)
end whlie continue == "N"
puts "Good Bye! Thanks for playing!"
Change whlie for while.
Also that while is checking for N to continue, what I suppose it must be Y.
begin
...
end while continue == 'Y'
puts "Good Bye! Thanks for playing!"
If you want you could reduce a bit the user and com input validation, and apply a bit of DRY:
begin
puts "|===============================================|"
puts "|Welcome to Rock Paper Scissors!!! |"
puts "|===============================================|"
choices = ['R', 'P', 'S']
begin
puts 'please choose one of the following: R / P / S'
user_input = gets.chomp.upcase
end while !choices.include?(user_input)
com_input = choices.sample
puts "You: #{user_input} Com: #{com_input}"
regex = /rs|sp|pr/i
choice = "#{user_input}#{com_input}"
if choice =~ regex
puts 'Result:You win'
elsif choice.reverse =~ regex
puts 'Result:You lose'
else
puts 'Result:Draw'
end
puts 'Play Again?: Y / N'
continue = gets.chomp.upcase
end while continue == 'Y'
puts 'Good Bye! Thanks for playing!'

Where am I missing an "end" in this Ruby script?

I am banging my head against the error message I keep getting, reading that "syntax error, unexpected keyword_end, expecting end-of-input." I cannot find my mistake for the life of me. It's probably sloppy-looking, I am a newbie. And any tips on preventing this specific issue in the future would also be greatly appreciated!
$move_direction_hash = {"N" => [0,1], "E" => [1,0], "S" => [0,-1], "W" => [-1,0]}
$cardinal_directions = ["N", "E", "S", "W"]
class Martian
attr_accessor :coordinate_x, :coordinate_y, :bearing, :direction_string
def initialize (coordinate_x, coordinate_y, bearing, direction_string)
#coordinate_x = coordinate_x
#coordinate_y = coordinate_y
#bearing = bearing
#direction_string = direction_string
end
def check_valid
#coordinate_x.between?(0, $boundaries[0]) && coordinate_y.between?(0, $boundaries[1])
return true
end
end
#will be second and last called in source code
def get_final
return "#{coordinate_x} #{coordinate_y} #{bearing}"
end
def move_forward
# find where in the hash the bearing is
position_array = $move_direction_hash[#bearing]
# returns a temporary variable
# that is the
test_x = #coordinate_x + position_array[0]
test_y = #coordinate_y + position_array[1]
if $rovers_on_grid.include?([test_x.to_s, test_y.to_s])
puts "Stopping Martian. You're about to crash!"
get_final
break
else
#coordinate_x = test_x
#coordinate_y = test_y
if check_valid == false
puts "Stopping Martian. About to run off the plateau."
get_final
break
else
return #coordinate_x, #coordinate_y
end
end
end
def add_to_grid
$rovers_on_grid << [#x_coordinate, #y_coordinate]
end
def read_instructions
#direction_string.each_char do |direction|
if direction == "L" || direction == "R"
position = $cardinal_directions.index(#bearing)
if direction == "L"
position = (position - 1)%4
$cardinal_directions[position]
elsif direction == "R"
position = (position + 1)%4
$cardinal_directions[position]
else
puts "Error!"
end
#bearing = $cardinal_directions[position]
elsif direction == "M"
move_forward
end
end
end
end
This error is located in the check_valid method. You missed the if.
def check_valid
if #coordinate_x.between?(0, $boundaries[0]) && coordinate_y.between?(0, $boundaries[1])
return true
end
end
Like steenslag mentioned the if statement is not required. You can write:
def check_valid
return #coordinate_x.between?(0, $boundaries[0]) && coordinate_y.between?(0, $boundaries[1])
end

How do I make my tic-tac-toe program not skip a players turn?

I wrote a tic-tac-toe program. The problem is that when a user enters an invalid coordinate, the user is notified however, it skips his turn. For example: if player "x" enters valid coordinates, and player "o" enters valid coordinates, player "o" is notified but his/her turn gets skipped and player "x" goes again. How do I fix this so that player "o" gets another chance to enter in valid coordinates?
Here is my code:
class Game
def initialize
#board=Array.new
#board[1]="1 __|"
#board[2]="__"
#board[3]="|__"
#board[4]="\n2 __|"
#board[5]="__"
#board[6]="|__"
#board[7]="\n3 |"
#board[8]=" "
#board[9]="| "
#turn="o"
#win_status = false
end
def turn
#turn
end
def show_board
puts " 1 2 3"
#board.each do |i|
print i
end
puts ""
end
def set_turn #switches turns
if #turn == "x"
#turn = "o"
else #turn == "o"
#turn = "x"
end
end
def make_move
puts "Enter x coordinate"
x=gets.to_i
puts "Enter y coordinate"
y=gets.to_i
if y==1 && x==1
#board[1]="1 _"+#turn+"|"
elsif y==2 && x==1
#board[2]="_"+#turn
elsif y==3 && x==1
#board[3]="|_"+#turn
elsif y==1 && x==2
#board[4]="\n2 _"+#turn+"|"
elsif y==2 && x==2
#board[5]="_"+#turn
elsif y==3 && x==2
#board[6]="|_"+#turn
elsif y==1 && x==3
#board[7]="\n3 "+#turn+"|"
elsif y==2 && x==3
#board[8]=" "+#turn
elsif y==3 && x==3
#board[9]="| "+#turn+" \n"
else
puts "you entered an invalid coordinate"
end
end
def win_combo
return [[#board[1][4] + #board[2][1] + #board[3][2]], [#board[4][5] + #board[5][1] + #board[6][2]], [#board[7][5] + #board[8][1] + #board[9][2]],[#board[1][4] + #board[4][5] + #board[7][5]], [#board[2][1] + #board[5][1] + #board[8][1]], [#board[3][2] + #board[6][2] + #board[9][2]], [#board[1][4] + #board[5][1] + #board[9][2]], [#board[3][2] + #board[5][1] + #board[7][5]]]
end
def check_win
#if some row or column or diagonal is "xxx" or "ooo" then set #win_status = true
self.win_combo.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
g = Game.new
while g.check_win != true
g.show_board
g.set_turn
g.make_move
end
end
You could call make_move again to prompt for the user to enter new coordinates.
puts "you entered an invalid coordinate"
make_move
You could call make_move from within your else clause once you know that a player
has entered an invalid move.
else
puts "you entered an invalid coordinate"
make_move
end
Look at the condition in make_move that is triggered when the user enters an invalid coordinate. After that code is triggered, make_move's execution is over, so it steps out into your g.check_win loop.
Think about your functions as pieces that can be reused. make_move is called whenever you want the current user to make a move. How can you execute this functionality again, after make_move tells the user their input was invalid?
I'll give you a hint: functions can call themselves.

Why does the else condition of my if-statement not work?

I wrote a tic-tac-toe program. The problem I am experiencing is that in my if statement, which allows the user enter his/her desired coordinate, my else condition is not working. The else condition is in place in case the user enters a coordinate not on the board.
This is my code:
class Game
def initialize
#board=Array.new
#board[1]="1 __|"
#board[2]="__"
#board[3]="|__"
#board[4]="\n2 __|"
#board[5]="__"
#board[6]="|__"
#board[7]="\n3 |"
#board[8]=" "
#board[9]="| "
#turn="o"
#win_status = false
end
def turn
#turn
end
def show_board
puts " 1 2 3"
#board.each do |i|
print i
end
puts ""
end
def set_turn #switches turns
if #turn == "x"
#turn = "o"
else #turn == "o"
#turn = "x"
end
end
def make_move
puts "Enter x coordinate"
x=gets.to_i
puts "Enter y coordinate"
y=gets.to_i
if y==1 && x==1
#board[1]="1 _"+#turn+"|"
elsif y==2 && x==1
#board[2]="_"+#turn
elsif y==3 && x==1
#board[3]="|_"+#turn
elsif y==1 && x==2
#board[4]="\n2 _"+#turn+"|"
elsif y==2 && x==2
#board[5]="_"+#turn
elsif y==3 && x==2
#board[6]="|_"+#turn
elsif y==1 && x==3
#board[7]="\n3 "+#turn+"|"
elsif y==2 && x==3
#board[8]=" "+#turn
elsif y==3 && x==3
#board[9]="| "+#turn+" \n"
else
"You entered an invalid coordinate"
end
end
def win_combo
return [[#board[1][4] + #board[2][1] + #board[3][2]], [#board[4][5] + #board[5][1] + #board[6][2]], [#board[7][5] + #board[8][1] + #board[9][2]],[#board[1][4] + #board[4][5] + #board[7][5]], [#board[2][1] + #board[5][1] + #board[8][1]], [#board[3][2] + #board[6][2] + #board[9][2]], [#board[1][4] + #board[5][1] + #board[9][2]], [#board[3][2] + #board[5][1] + #board[7][5]]]
end
def check_win
#if some row or column or diagonal is "xxx" or "ooo" then set #win_status = true
self.win_combo.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
g = Game.new
while g.check_win != true
g.show_board
g.set_turn
g.make_move
end
end
You are just returning the string: "You entered an invalid coordinate".
I suspect that you want to display it using:
puts "You entered an invalid coordinate"
Otherwise it is passed as the result of g.make_move and then ignored.
I'm assuming you would like to print: "You entered an invalid coordinate" to the console in the event of an invalid x, y coordinate. You need to add a method to that statement like:
else
puts "You entered an invalid coordinate"
end
Or:
else
abort "You entered an invalid coordinate"
end
It looks you you forgot to use puts or print in front of your "You entered an invalid coordinate" string. As it is currently written it is returned from the method.
In Ruby, the return value of a method is the value returned by the last statement evaluated. For example, both of these methods will return the same value if x=3:
def square_example(x)
if x ==3
x_squared = 9
end
end
def square_example2(x)
if x == 3
x_squared = 9
end
return x_squared
end
For simplicity of testing you might try using explicit returns so that you can easily tell what it is you are returning from the method. Or (as a beginner with Ruby myself) you could add in a puts statement with each if/else result so that you can easily monitor the results of each move and then remove those puts lines when you know everything is working properly.
Looks like this is a misinterpretation of the site below, but if you're interested in the difference between 'and' and '&&' you should check out the comments below.
From: http://www.tutorialspoint.com/ruby/ruby_operators.htm
You will want to use "and" instead of "&&", an example:
if y==1 and x==1
# do move
elsif y==2 and x==1
# do move
.
.
.
else
"invalid coordinate"
end
The "&&" operator will check that the values on either side of it are nonzero. If they are both nonzero then it will return true. In your case it is doing the operation
false && false
Where false != 0, so it returns true.
Here is another discussion of this: http://archive.railsforum.com/viewtopic.php?id=27353

Resources