Undefined method in ruby - ruby

I'm a beginner in Ruby and I'm doing a really easy "game".
My problem is that I want to test if the user press 1 then roll some dices but I can't use my method. Please refer to the code below for more details:
class Player
#i have some methods but it work
end
class Game
tot = 0
def rollDice
tot = 0
puts "You roll the dices"
d1 = rand(1..6)
puts "Dice 1: #{d1}"
d2 = rand(1..6)
puts "Dice 2: #{d2}"
d3 = rand(1..6)
puts "Dice #{d3}"
tot = d1 + d2 + d3
puts "Your score is #{tot}"
return tot
end
#some puts but not important for the coding
puts "Press 1 to play or 2 to leave"
value = gets.chomp
if value == "1"
s1 = rollDice
puts "Why it doesnt work :C #{s1}"
#[i have a player class but its not important for the moment]
#player1 = Joueur.new(j1)
#player2 = Joueur.new(j2)
#player1.score
#player2.score
elsif value== "2"
exit
end
end
But i have the undefined method error for my method rollDice
thank you really

Your code does work. However, your rollDice definition is indented (and you have a second tot=0 call), so I guess you actually defined it in something else (a class?), which is at the time of writing not included in your posted code sample.
Btw, following conventions/style guides I would suggest you to rename rollDice into roll_dice.
The code I tested successfully is this one:
def rollDice
tot = 0
puts "You roll the dices"
d1 = rand(1..6)
puts "Dice 1: #{d1}"
d2 = rand(1..6)
puts "Dice 2: #{d2}"
d3 = rand(1..6)
puts "Dice #{d3}"
tot = d1 + d2 + d3
puts "Your score is #{tot}"
return tot
end☠
puts "Press 1 to play or 2 to leave"
value = gets.chomp
if value == "1"
s1 = rollDice
puts "Why it doesnt work :C #{s1}"
elsif value== "2"
exit
end
example session:
$ Press 1 to play or 2 to leave
> 1
You roll the dices
Dice 1: 5
Dice 2: 5
Dice 2
Your score is 12
Why it doesnt work :C 12

Related

Tic Tac Toe Help fixing method that checks if square has already been chosen. Game board is structured as empty array

I'm creating a tic tac toe game in the command line using Ruby. I have a method display_board that displays my array as a game board in the command line and when I play the game players can choose between 1-9 and populate the square with their "symbol". I created a method check_square to verify if one of the squares in the grid has already been taken but it's not working properly for me. I start up the game and everything works, up until it asks me to choose my first number on the grid. It immediately responds and tells me the number is already taken even though it's the first move of the game. It asks me to choose another number and on the second try it populates the grid. It does this on every player move. The logic seems to make sense to me and I've been trying to figure it out for an hour but I'm clearly overlooking something. Any pushes in the right direction would be helpful!
class Players
attr_accessor :name, :symbol
def initialize(name, symbol)
#name = name
#symbol = symbol
end
end
class Game
##board = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
##count = 0
def initialize
puts "Tic Tac Toe!"
end
def display_board
puts " #{##board[0]} | #{##board[1]} | #{##board[2]}"
puts seperator = "-----+-----+-----"
puts " #{##board[3]} | #{##board[4]} | #{##board[5]}"
puts seperator
puts " #{##board[6]} | #{##board[7]} | #{##board[8]}"
puts "\n"
end
def game_start
puts "Time for some Tic Tac Toe! Enter your name player 1: \n"
player1 = gets.chomp
puts "Would you like to be X or O #{player1}?"
symbol1 = gets.chomp.upcase
player_one = Players.new(player1, symbol1)
puts "And a name for player 2: \n"
player2 = gets.chomp
symbol2 = player_one.symbol == "X" ? "O" : "X"
player_two = Players.new(player2, symbol2)
puts "\n"
puts "Okay #{player_one.name}, you're up. Make a move."
display_board
make_moves(player_one, player_two)
end
def make_moves(player_one, player_two)
until ##count == 9
puts "Pick a number from the grid above #{player_one.name}"
move = gets.chomp.to_i - 1
check_square(move, player_one, player_two)
##board[move] = player_one.symbol
##count += 1
display_board
puts "Pick a number from the grid above #{player_two.name}"
move = gets.chomp.to_i - 1
check_square(move, player_one, player_two)
##board[move] = player_two.symbol
##count += 1
display_board
end
end
def check_square(move, player_one, player_two)
if ##board[move] == "#{player_one.symbol}" || "#{player_two.symbol}"
puts "That number is taken, pick another!"
move = gets.chomp.to_i - 1
else
return
end
end
end
game = Game.new
game.game_start
The problem you're running into is the conditional logic in your check_square method.
##board[move] == "#{player_one.symbol}" || "#{player_two.symbol}"
This logic is suppose to check if either of the players' symbols is stored on the board at the selected position. However, what it is really doing is checking if player one's symbol is stored on the board at that position and if it's not then the string literal for player two's symbol is being evaluated as truthy. This results in check_square always returning true
Try this instead:
##board[move] == "#{player_one.symbol}" || ##board[move] == "#{player_two.symbol}"
For more idiomatic ruby you can remove the interpolation which isn't necessary since symbol is already a string.
##board[move] == player_one.symbol || ##board[move] == player_two.symbol

100 Doors with Ruby

I am working on the "Rosetta Code 100 Doors" problem and have hit a wall.
I found "100 doors help using Ruby" which was of some help, but I still can't get my code to work.
My toggle method doesn't work within my array iteration method.
def toggle(state)
if state == 'closed'
state.replace('open')
elsif state == 'open'
state.replace('closed')
end
end
def one_hundred_doors(array)
i = 0
100.times do
i += 1
array.each_with_index.map do |state, index|
if (index + 1) % i == 0
toggle(state)
end
end
end
array.each_with_index { |state, door| puts "Door #{door + 1} is #{state}." }
end
doors = Array.new(100, "closed")
one_hundred_doors(doors)
Can someone please explain what I am doing wrong?
Your problem is in your array creation method. You create it to contain 100 references to the same string:
doors = Array.new(100, "closed")
doors.first.replace("lala")
doors # => ["lala", "lala", ...]
but you need different strings.
Create it this way:
doors = 100.times.map{"closed"}

TicTacToe invalid move method issue

Below is my take for the TicTacToe game. So far it works, but it's not perfect. I'm having an issue with one of the methods - Game#invalid_move_check? after the game asked you "where to:"once choose the new destination , the game change the symbol like if it was a new turn .in fact not , suppose to keep the same player symbol until next turn.
P.S the code probably need some refactoring. I'm in a learning phase.
class Game
def initialize(symbol)
#board = Array.new(3){Array.new(3)}
# [0,1,2]
# [3,4,5]
# [6,7,8]
#symbol = ["X", "O"]
end
WINNING_COMBO = [
# Horizontal wins:
[0, 1, 2], [3, 4, 5], [6, 7, 8],
# Vertical wins:
[0, 3, 6], [1, 4, 7], [2, 5, 8],
# Diagonal wins:
[0, 4, 8], [2, 4, 6]
]
def create_players
# create both players
#names = []
print "Please enter the name of the first player: "
#player_1 =gets.chomp
#names << #player_1
print "Please enter the name of the second player: "
#player_2 = gets.chomp
#names << #player_2
puts "\n"
puts"welcome #{#player_1.upcase} and #{#player_2.upcase}"
puts"------------------------------------------------"
puts"\n"
puts "Randomizing who'll start..."
puts"\n"
# assign player by calling the player_assigment function that will determine who will start first
player_assigment
puts"\n"
end
def player_assigment
# merge the names array and symbol array
# with the zip method and return a nested array with player and symbol.
#choice = #names.zip(#symbol)
# iterate over the choice nested array and
# print out each player and their assigned symbol
#choice.each do |player, symbol|
puts "#{player.upcase} will use #{symbol}"
end
end
def current
#current = #names.first
#current
end
def switch_turn
#current = #names.last
#current
end
def first_turn
current
puts "#{#current.upcase} turn"
#marker = #symbol.first
make_move(#marker)
end
def next_turn
switch_turn
puts "#{#current.upcase} turn"
#marker = #symbol.last
make_move(#marker)
end
def check_win?(first_arr, second_arr)
WINNING_COMBO.select do |item|
if
item == first_arr
puts"#{#player_1} won!!"
elsif
item == second_arr
puts "#{#player_2} won!!"
end
end
end
def mapping(move, marker)
case move
when 0
arr_index = 0
index = 0
invalid_move_check?(arr_index,index)
#board[0][0] = marker
when 1
arr_index = 0
index = 1
invalid_move_check?(arr_index,index)
#board[0][1] = marker
when 2
arr_index = 0
index = 2
invalid_move_check?(arr_index,index)
#board[0][2] = marker
when 3
arr_index = 1
index = 0
invalid_move_check?(arr_index,index)
#board[1][0] = marker
when 4
arr_index = 1
index = 1
invalid_move_check?(arr_index,index)
#board[1][1] = marker
when 5
arr_index = 1
index = 2
invalid_move_check?(arr_index,index)
#board[1][2] = marker
when 6
arr_index = 2
index = 0
invalid_move_check?(arr_index,index)
#board[2][0] = marker
when 7
arr_index = 2
index = 1
invalid_move_check?(arr_index,index)
#board[2][1] = marker
when 8
arr_index = 2
index = 2
invalid_move_check?(arr_index,index)
#board[2][2] = marker
end
end
def invalid
puts"move invalid"
end
def invalid_move_check?(arr_index, index)
array = #board
if array[arr_index][index] == "X" ||
array[arr_index][index] == "O"
invalid
puts "Where to :"
#move = gets.chomp.to_i
mapping(#move,#marker)
end
end
def make_move(marker)
# after each turn the make_move method will called to place move on the board
puts "Where to :"
#move = gets.chomp.to_i
mapping(#move,#marker)
print_board
end
# display board in a matrix format
def print_board
#board.each_slice(1) { |a| p a }
puts"\n"
end
def instructions
puts "Instructions :Enter your first move by entering a number 1-9"
puts "corresponding to the grid on the bottom and press enter"
puts"\n"
puts "0 | 1 | 2 ",
"----------",
"3 | 4 | 5 ",
"----------",
"6 | 7 | 8 "
print"\n"
end
def self.start(symbol)
# start a new game
new_game =Game.new(symbol)
# create players
new_game.create_players
new_game.instructions
new_game.print_board
# Checking wining combo for matching patter if none
while new_game.check_win?(#move_first, #move_second) do
new_game.first_turn
# the player switch turn
new_game.next_turn
end
end
loop do
puts"------------------------------------------------"
puts" Welcome to tictactoe ".upcase
puts"------------------------------------------------"
print"\n"
Game.start(#symbol)
end
end
This should do the trick:
#will return true or false to check validity of move
def invalid_move_check?(arr_index, index)
array = #board
if array[arr_index][index] == "X" ||
array[arr_index][index] == "O"
invalid
puts "Where to :"
#move = gets.chomp.to_i
mapping(#move,#marker)
return true
end
return false
end
def mapping(move, marker)
case move
...
when 0
arr_index = 0
index = 0
unless invalid_move_check?(arr_index,index) #change all cases
#board[0][0] = marker #to have the assignment of board
#only if the move is valid
end
...
end
end
The reason of your bug is that the assignment happens even if the move is invalid.
This is just a band-aid solution to your current problem, as for refactoring ,there are things that can be done to optimize your code and make it better :) But you still have to fix first your 'ending'. Refactoring your own code would be a very good practice. I wish you a joyful ruby journey
!
After scratching the previous code and rethink the code i 've come up with this solution , not elegant as i will want it to be but it works .i move the symbol assignment in the if/else block code and therefore when a move is invalid next move will use the symbol of the current player
def mapping(move, symbol)
case move
when 0
if #board[0][0]=="X" || #board[0][0] == "O"
invalid
make_move
else
#board[0][0] = symbol
track_move(#move)
print_board
end
...
end
end

Why does counter keep getting reset?

I've created a simple game where the user has to alphabetize the order of a word to score. For some odd reason score is returning 1 even though the user gets 2 questions correct. What am I doing wrong?
def alphabetize(word)
word.chars.sort_by(&:downcase).join
end
def words
%w(hello yes)
end
#correct = 0
#incorrect = 0
def score
(#correct / #correct + #incorrect)
end
words.each do |word|
puts "Alphabetize '#{word}'"
answer = gets.chomp
if answer == alphabetize(word)
#correct += 1
p 'Nice!'
else
#incorrect += 1
p 'You suck!'
end
end
p "Your score: #{score}"
because:
#correct / #correct
will always be 1

Passing arguments to functions in ruby using variables

Following the tutorial Zed A. Shaw, I'm writing a soccer game. My code so far is as follows:
$team_a_players = ["Basar", "Mehmet", "Abdullah", "Alpaslan", "Salih", "Recep", "Ibrahim", "Orhan", "Hakki", "Yakup", "Serdar"]
$team_a_substitutes = ["Hasan", "Turgay", "Umit"]
$team_b_players = ["Habib", "Erkan", "Sahin", "Cemal", "Ahmet", "Fikret", "Yucel", "Pergel", "Ali", "Sabri", "Yilmaz"]
$team_b_substitutes = ["Abdulkadir", "Gokhan", "Mustafa"]
$yellow = []
$red = []
$reasons = ["corner", "direct attack", "free kick", "side attack", "speed kick"]
$team_a_attack = 90.0
$team_a_defense = 80.0
$team_b_attack = 70.0
$team_b_defense = 60.0
$team_a_goals = 0
$team_b_goals = 0
def prompt()
print "> "
end
def dice()
if rand(2) == 0
round_team_a()
else
round_team_b()
end
end
def fauls()
if rand(0) > 0.95 and rand(10) % 2 == 0
faul_player = $team_a_players[rand(11)]
if $yellow.include?(faul_player)
$red.push(faul_player)
$team_a_players.delete("faulplayer")
puts "#{faul_player} of Team A gets a red card in #{$i}. minute!"
puts "Who would you like to substitute in place of #{faul_player}?"
list_subs_a()
prompt()
substitute = STDIN.gets.chomp()
$team_a_players.push("substitute")
$yellow.delete(faul_player)
else
$yellow.push(faul_player)
puts "#{faul_player} of Team A gets a yellow card in #{$i}. minute!"
end
elsif rand(0) > 0.95 and rand(10) % 2 == 1
faul_player = $team_b_players[rand(11)]
if $yellow.include?(faul_player)
$red.push(faul_player)
$team_b_players.delete("faulplayer")
puts "#{faul_player} of Team B gets a red card in #{$i}. minute!"
puts "Who would you like to substitute in place of #{faul_player}?"
list_subs_b()
prompt()
substitute = STDIN.gets.chomp()
$team_b_players.push("substitute")
$yellow.delete(faul_player)
else
$yellow.push(faul_player)
puts "#{faul_player} of Team B gets a yellow card in #{$i}. minute!"
end
else
faul_player = nil
end
end
def list_subs_a()
$team_a_substitutes.each {|p| puts p}
end
def list_subs_b()
$team_b_substitutes.each {|p| puts p}
end
def list_yellow()
$yellow.each {|p| puts p}
end
def list_red()
$red.each {|p| puts p}
end
def round_team_a()
score = $team_a_attack / $team_b_defense * rand(0)
if score > 1
goal = 1
$team_a_goals += 1
reason = $reasons[rand(5)]
puts "Team A scored #{goal} goal through a #{reason} in #{$i}. minute!"
else
goal = 0
end
end
def round_team_b()
score = $team_b_attack / $team_a_defense * rand(0)
if score > 1
goal = 1
$team_b_goals += 1
reason = $reasons[rand(5)]
puts "Team B scored #{goal} goal through a #{reason} in #{$i}. minute!"
else
goal = 0
end
end
def match()
$i = 0
until $i > 59 do
dice()
fauls()
$i += 1
end
puts "Team A scored a total of #{$team_a_goals} goals and Team B scored a total of #{$team_b_goals} goals."
if $team_a_goals > $team_b_goals
puts "Team A won against Team B by #{$team_a_goals}:#{$team_b_goals}!"
elsif $team_b_goals > $team_a_goals
puts "Team B won against Team A by #{$team_b_goals}:#{$team_b_goals}!"
else
puts "It's a tie!"
end
if $yellow.length > 0
puts "Players shown a yellow card are:"
list_yellow()
else
puts "No yellow cards in the end of the game"
end
if $red.length > 0
puts "Players shown a red card are:"
list_red()
else
puts "No red cards in the end of the game"
end
end
match()
From here, I would like to do the following:
Replace the arrays $yellow and $red with hashes so that I can also report minutes and teams of yellow- and red-cards.
Replace the arrays starting with the name $team_ with hashes so that I can add individualized attack- and defense-powers to players so that substitutions mean sth. but before the code gets any more complex, I have to solve sth. This looks similar to this question concerning php.
Define the functions list, round and faul in a way that can be used common to a_players and b_players . I tried doing team_#{team}_players instead of team_a_players etc, but cannot achieve it.
What I seek is a guide to that problem, not a solution, so that I can fix this myself. A link or long explanation in clear words is very much more welcome than a fixed code. And please note that the tutorial has not mentioned classes yet, so this is not an option yet.
The basic idea you haven't seemed to grasp is passing arguments to functions.
Assume we have two global variables and we wish to perform identical operations on them - say multiply elements of arrays by 2.
You write:
$a = [1,2,3]
$b = [2,3,4]
def multiply_a
result = []
for element in $a do
result << element * 2
end
result
end
def multiply_b
result = []
for element in $b do
result << element * 2
end
result
end
But this code is very bad. First of all, you should note that in Ruby $a is a special variable - a global variable. You should never need to use them - writing code containing them means that there is something wrong with it. So how to fix it?
The basic idea is to pass an argument to a function, instead of hard coding the variable, the function operates on. So you can transform the code as follows:
a = [1, 2, 3]
b = [2, 3, 4]
def multiply(argument)
result = []
for element in argument do
result << element * 2
end
result
end
# and then call
multiply(a) # instead of multiply_a
multiply(b) # instead of multiply_b
This is the way you should fix your code.

Resources