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
Related
I can play the game. Switch the player all working fine but not getting result who won the game.
def initialize_board
#count = 9
#player = PLAYER_ONE #current_player
#board = Array.new(3){ Array.new(3, " ") }
end
def play
inputs = get_inputs
return false if !inputs
update_board(inputs)
print_board
end
def switch_player
if(#player == PLAYER_ONE)
#player = PLAYER_TWO
else
#player = PLAYER_ONE
end
end
def game_over?
# #count = #count - 1
# #count <= 0
if check_winner
puts "#{#player} won "
end
end
def check_winner
WIN_COMBINATIONS.find do |indices|
binding.pry
values = #board.values_at(*indices)
values.all?('X') || values.all?('O')
end
end
Here I am getting indices [0,1,2] in all cases while debugging.
The main reason why you're not getting the winner is because your 'values = #board.values_at(*indices)' statement returns an array of arrays. And values.all?('X') || values.all?('O') checks not an 'X' or 'O' pattern but an array object. So you need to flatten an array first.
values.flatten!
Stefan already answered similar question , but his board was one-dimensional because of %w expression, you can read about it here
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Created this connect 4 game following a guide online but the guide didn't explain how to make it computer vs player it only explained how to make it player vs player. I've tried adding a computer variable that generated a random number 1..8 for the columns but it wasn't working was just sitting there asking player two to pick a location.
Here's the player code below how do i implement player vs computer ?
class Board
attr_accessor :board
attr_reader :turn, :identifier
def initialize
#board = [
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0]
]
#turn = 0
#identifier = 1
end
def choose_column(col)
7.downto(0) do |i|
if board[i][col-1] == 0
board[i][col-1] = identifier
break
end
end
false
end
def win?
return true if check_rows?
return true if check_columns?
return true if check_diagonal?
end
def check_validity(sum,num)
if num == 1
sum = 0 if sum < 0
sum += 1
elsif num == -1
sum = 0 if sum > 0
sum -= 1
else
sum = 0
end
end
def check_rows?
8.times do |i|
board[i].inject(0) do |sum, num|
sum = check_validity(sum,num)
return true if sum.abs == 4
sum
end
end
false
end
def check_columns?
8.times do |i|
column = []
board.each { |row| column.push(row[i]) }
column.inject(0) do |sum, num|
sum = check_validity(sum,num)
return true if sum.abs == 4
sum
end
end
false
end
def check_diagonal?
board[0..2].each_with_index do |row, row_i|
row.each_with_index do |column, col_i|
if col_i <=3
sum = board[row_i][col_i]
1.upto(3) { |i| sum += board[row_i+i][col_i+i] }
return true if sum.abs == 4
end
if col_i >= 3
sum = board[row_i][col_i]
1.upto(3) { |i| sum += board[row_i+i][col_i-i] }
return true if sum.abs == 4
end
end
end
false
end
def new_game
#turn = 1
end
def game_flow
new_game
while turn < 43
assign_player
player = #identifier == 1 ? 1 : 2
puts draw_board
print "Round #{#turn}. Player #{player}'s turn. Choose column (1-8): "
input = gets.chomp
while !validate_input(input) || check_full?(input)
print "Invalid Pick. Try again: "
input = gets.chomp
end
input = validate_input(input)
choose_column(input)
if win?
puts draw_board
puts "Congratulations. Player #{player} won"
break
end
#turn += 1
end
puts "Draw!" unless win?
return true
end
def assign_player
#identifier = #turn.odd? ? 1 : -1
end
def validate_input(input)
return input !~ /^[1-8]$/ ? false : input.to_i
end
def check_full?(column)
column = column.to_i
column -= 1
return board[0][column] != 0
end
def draw_board
print "1 2 3 4 5 6 7 8\n"
rep = { 0 => ".", 1 => "O", -1 => "X" }
board.each do |row|
print "#{rep[row[0]]} #{rep[row[1]]} #{rep[row[2]]} #{rep[row[3]]} #{rep[row[4]]} #{rep[row[5]]} #{rep[row[6]]} #{rep[row[7]]}\n"
end
print " "
end
end
board = Board.new
board.game_flow
Like Ken White says, if you want the computer to select a choice, you need to detect when it is the computer's turn. It looks like in your example this is encoded in the #player variable. You can have a simple if branch which only prompts for input when it is the human player's turn. Everything else could remain the same, but you would update your game_flow method to consider this other case:
if player == 1
print "Round #{#turn}. Player #{player}'s turn. Choose column (1-8): "
input = gets.chomp
while !validate_input(input) || check_full?(input)
print "Invalid Pick. Try again: "
input = gets.chomp
end
input = validate_input(input)
else
input = rand(1..8)
end
Hope this helps.
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"}
Sample input:
"I was 09809 home -- Yes! yes! You was"
and output:
{ 'yes' => 2, 'was' => 2, 'i' => 1, 'home' => 1, 'you' => 1 }
My code that does not work:
def get_words_f(myStr)
myStr=myStr.downcase.scan(/\w/).to_s;
h = Hash.new(0)
myStr.split.each do |w|
h[w] += 1
end
return h.to_a;
end
print get_words_f('I was 09809 home -- Yes! yes! You was');
This works but I am kinda new to Ruby too. There might be a better solution.
def count_words(string)
words = string.split(' ')
frequency = Hash.new(0)
words.each { |word| frequency[word.downcase] += 1 }
return frequency
end
Instead of .split(' '), you could also do .scan(/\w+/); however, .scan(/\w+/) would separate aren and t in "aren't", while .split(' ') won't.
Output of your example code:
print count_words('I was 09809 home -- Yes! yes! You was');
#{"i"=>1, "was"=>2, "09809"=>1, "home"=>1, "yes"=>2, "you"=>1}
def count_words(string)
string.scan(/\w+/).reduce(Hash.new(0)){|res,w| res[w.downcase]+=1;res}
end
Second variant:
def count_words(string)
string.scan(/\w+/).each_with_object(Hash.new(0)){|w,h| h[w.downcase]+=1}
end
def count_words(string)
Hash[
string.scan(/[a-zA-Z]+/)
.group_by{|word| word.downcase}
.map{|word, words|[word, words.size]}
]
end
puts count_words 'I was 09809 home -- Yes! yes! You was'
This code will ask you for input and then find the word frequency for you:
puts "enter some text man"
text = gets.chomp
words = text.split(" ")
frequencies = Hash.new(0)
words.each { |word| frequencies[word.downcase] += 1 }
frequencies = frequencies.sort_by {|a, b| b}
frequencies.reverse!
frequencies.each do |word, frequency|
puts word + " " + frequency.to_s
end
This works, and ignores the numbers:
def get_words(my_str)
my_str = my_str.scan(/\w+/)
h = Hash.new(0)
my_str.each do |s|
s = s.downcase
if s !~ /^[0-9]*\.?[0-9]+$/
h[s] += 1
end
end
return h
end
print get_words('I was there 1000 !')
puts '\n'
You can look at my code that splits the text into words. The basic code would look as follows:
sentence = "Ala ma kota za 5zł i 10$."
splitter = SRX::Polish::WordSplitter.new(sentence)
histogram = Hash.new(0)
splitter.each do |word,type|
histogram[word.downcase] += 1 if type == :word
end
p histogram
You should be careful if you wish to work with languages other than English, since in Ruby 1.9 the downcase won't work as you expected for letters such as 'Ł'.
class String
def frequency
self.scan(/[a-zA-Z]+/).each.with_object(Hash.new(0)) do |word, hash|
hash[word.downcase] += 1
end
end
end
puts "I was 09809 home -- Yes! yes! You was".frequency
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.