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
Related
I'm writing this script to build a tic-tac-toe game. This is only the beginning (no turns yet). I want to let the user input again if the previous input is invalid.
def display_board(board)
first_row = " #{board[0]} | #{board[1]} | #{board[2]} "
second_row = " #{board[3]} | #{board[4]} | #{board[5]} "
third_row = " #{board[6]} | #{board[7]} | #{board[8]} "
row_divider = "-----------"
puts first_row
puts row_divider
puts second_row
puts row_divider
puts third_row
end
def valid_move?(board,index)
if (index >= 0) && (index <= board.length - 1) && (position_taken?(board,index) != FALSE)
return TRUE
else
return FALSE
end
end
def input_to_index(user_input)
index = user_input.to_i - 1
return index
end
def move(board, index, character = "X")
board[index] = character
end
def position_taken?(board,index)
if (board[index] == "X") || (board[index]=="O")
return FALSE
end
end
def turn(board)
puts "Please enter 1-9:"
user_input = gets.strip
index = input_to_index(user_input)
while valid_move?(board,index) == FALSE
puts "invalid"
turn(board)
end
move(board, index, character = "X")
display_board(board)
end
I am stuck on the while loop. If I input an invalid input and then a valid input, it runs through the while loop instead of ending the program. It should be true. The problem is fixed if I use an if statement instead of a while loop, but I want to learn to use while loops better.
Because you call "turn" (internal) from "turn" (external) and then the internal "turn" called is valid but the board and index on the external
"turn" didn't change.
try this:
def turn(board)
loop do
puts "Please enter 1-9:"
user_input = gets.strip
index = input_to_index(user_input)
if valid_move?(board,index) == TRUE
break
end
puts "invalid"
end
move(board, index, character = "X")
display_board(board)
end
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
Hey the code I created only repeats 2 times.
After I type the second time "y" for the "continue_question"-method the code only stops.
def greeting
puts "Hello! Please type your name: "
name = gets.chomp.capitalize
puts "It is nice to meet you #{name}. I am a simple calculator application."
puts "I can add, subtract, multiply, and divide."
end
greeting
def calculator
puts "First number: "
#n1 = gets.chomp.to_i
puts "Secons number: "
#n2 = gets.chomp.to_i
def calculation
puts "Type 1 to add, 2 to subtract, 3 to multiply, or 4 to divide two numbers: "
operation_selection = gets.chomp.to_i
if operation_selection == 1
#result = #n1 + #n2
elsif operation_selection == 2
#result = #n1 - #n2
elsif operation_selection == 3
#result = #n1 * #n2
elsif operation_selection == 4
#result = #n1 / #n2
else
puts "Something went wrong!"
calculation
end
end
calculation
puts "Your Result is #{#result}"
end
calculator
def continue_question
puts "Do you want to continue? (y/n)"
continue = gets.chomp.to_s
if continue == "y"
calculator
elsif continue == "n"
puts "Bye!"
else
puts "What?"
continue_question
end
end
continue_question
Your code does not repeat 2 times, it repeats once.
The reason is because in your continue_question method, you do not tell it to repeat again:
def continue_question
puts "Do you want to continue? (y/n)"
continue = gets.chomp.to_s
if continue == "y"
calculator # <-- This causes it it repeat ONCE!
elsif continue == "n"
puts "Bye!"
else
puts "What?"
continue_question
end
end
A quick fix is to re-call the continue_question method below that line, to recursively repeat itself:
def continue_question
puts "Do you want to continue? (y/n)"
continue = gets.chomp.to_s
if continue == "y"
calculator
continue_question # <-- Add this to repeat indefinitely
elsif continue == "n"
puts "Bye!"
else
puts "What?"
continue_question
end
end
The problem is that continue_question only executes once, at the end of your code, but you need to loop until user exits (i.e types n).
So simply add a loop inside continue_question, for example:
def continue_question
continue = "y"
until continue == "n" do
puts "Do you want to continue? (y/n)"
continue = gets.chomp.to_s
if continue == "y"
calculator
elsif continue == "n"
puts "Bye!"
else
puts "What?"
end
end
end
Hey the code I created only repeats 2 times.
I think you misunderstand the following:
if continue == "y"
calculator
elsif continue == "n"
puts "Bye!"
When you call the above function calculator, you are still executing the continue_question function. So when the calculator finishes executing, continue_question will finish as well and the program will stop. For the wanted result you can try using a loop.
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!'
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.