How to correctly write a ruby method - ruby

i'm trying ruby. I want to make a program which can continue the sequence.
1
11
21
1211
111221
(which next line is a calculated each number of previous line)
For example last line is(see previous) one of 1, one of 2, and two of 1.
I make a code and it works fine:
5.times do
result_seq = []
count = 1
puts initial_seq.join
initial_seq.size.times do
if (value = initial_seq.shift) == initial_seq.first
count += 1
else
result_seq << count << value
count = 1
end
end
initial_seq = result_seq
end
But now I want to write a simple method called Next
I want to make:
sec = Sequence.new(1)
sec.next -> will return 11
sec.next.next -> will return 21
sec.next.next.next -> will return 1211
How can i write it correctly using my code?
UPD
I wrote the tests for it:
require "spec_helper"
require "sequence"
describe Sequence do
let(:sequence) { Sequence.new("1") }
describe "to_s" do
it "return initial value" do
expect(sequence.to_s).to eql "1"
end
end
describe "next" do
it "generate next state" do
expect(sequence.next.to_s).to eql "11"
end
it "return Sequence instance" do
expect(sequence.next).to be_an_instance_of(Sequence)
end
it "generate next state 2 times" do
expect(sequence.next.next.to_s).to eql "21"
end
it "generate next state 3 times" do
expect(sequence.next.next.next.to_s).to eql "1211"
end
end
end

class Sequence
attr_reader :initial_seq
def initialize(initial_seq = [])
#initial_seq = initial_seq
print_next
end
def print_next
result_seq = []
count = 1
puts initial_seq.join
initial_seq.size.times do
if (value = initial_seq.shift) == initial_seq.first
count += 1
else
result_seq << count << value
count = 1
end
end
#initial_seq = result_seq
self #<===== The most important part for being able to chain `print_next`
end
end
Usage:
Sequence.new([1]).print_next.print_next.print_next.print_next
1
11
21
1211
111221
edit
If you want to initialize it with integer argument, not array:
def initialize(number)
#initial_seq = [number]
print_next
end
Sequence.new(1).print_next.print_next
1
11
21
Or, if you do not want initialize to accept an argument (assuming, it will always start with 1):
def initialize
#initial_seq = [1]
print_next
end
Sequence.new.print_next.print_next
1
11
21

Ruby provides Enumerators, which behave almost like in OP. Leaving the original code almost unaltered:
seq = Enumerator.new do |yielder|
initial_seq = [1]
loop do #endless loop, but don't worry, its lazy
result_seq = []
count = 1
yielder << initial_seq.join
initial_seq.size.times do
if (value = initial_seq.shift) == initial_seq.first
count += 1
else
result_seq << count << value
count = 1
end
end
initial_seq = result_seq
end
end
5.times{puts seq.next}
puts seq.next

Related

Is there a a function in Ruby to increment an objects variable inside an array in this example?

The drop1.amount or drop2.amount of Drop object in this example will not increase after the first time theyre run through.
class Drop
attr_accessor :item, :price, :amount
end
drop1 = Drop.new()
drop1.item = "item1"
drop1.price = 2247
drop1.amount = 1
drop2 = Drop.new()
drop2.item = "item2"
drop2.price = 4401
drop2.amount = 60
x = 0
array = []
while x < 10
rand1 = rand(2)
if rand1 == 0
if array.include? drop1.item
drop1.amount = drop1.amount + 1
else
array << drop1.item
array << drop1.amount
end
elsif rand1 == 1
if array.include? drop2.item
drop2.amount = drop2.amount + 60
else
array << drop2.item
array << drop2.amount
end
end
x += 1
end
puts array.to_s.gsub('"', '').gsub('[', '').gsub(']', '')
puts ""
puts drop1.amount
puts drop2.amount
Example of expected output:
item2, 240, item1, 6
6
240
Example of actual result:
item2, 60, item1, 1
6
240
I am looking for a change to the else statements in lines 24 and 32. The purpose of the this program is to create an array of items that will display the "item" one time and an incremented "amount" when a drop is randomly chosen multiple times.
array << drop1.amount does not make an alias of drop1.amount, it makes a one-time copy of the number value contained in drop1.amount. When you update drop1.amount, the copy in array is unchanged. Instead, put a reference to the object onto the result array or update the result array value directly (depending on whether you want to modify the original or not).
For example we can stick to the existing design with something like:
# ...
if array.include? drop1.item
array[array.index(drop1.item)+1] += 1
drop1.amount += 1 # optionally update the original (less ideal than an alias)
else
array << drop1.item
array << drop1.amount
end
# ...
if array.include? drop2.item
array[array.index(drop2.item)+1] += 60
drop2.amount += 60
else
array << drop2.item
array << drop2.amount
end
# ...
While this emits the expected output, this sort of awkward searching and repeated code suggests that there are fundamental design flaws.
I'd write the program something like:
Drop = Struct.new(:item, :price, :amount)
drops = [
Drop.new("item1", 2247, 1),
Drop.new("item2", 4401, 60)
]
increment_amounts = drops.map {|e| e.amount}
result = [nil] * drops.size
10.times do
choice = rand(drops.size)
if result[choice]
result[choice].amount += increment_amounts[choice]
else
result[choice] = drops[choice]
end
end
puts result.compact
.shuffle
.flat_map {|e| [e.item, e.amount]}
.to_s
.gsub(/["\[\]]/, "")
puts "\n" + drops.map {|e| e.amount}.join("\n")
Suggestions which the above version illustrates:
Use a struct instead of a class for such a simple type and set its properties using the constructor rather than accessors.
Use arrays instead of thing1, thing2, etc. This makes it a lot easier to make random choices (among other things). Note that the above version is expandable if you later decide to add more drops. After adding a third or 100 drops (along with corresponding increment amounts), everything just works.
Prefer a clear name like result instead of a generic name like array.
x = 0 ... while x < 10 ... x += 1 is clearer as 10.times.
Pass a regex to gsub instead of a string to avoid chaining multiple calls.
I don't know if I undestand properly the logic, but consider using a Hash instead of an Array:
h = {}
10.times do |x|
rand1 = rand(2)
if rand1 == 0
if h.has_key? drop1.item
drop1.amount += 1
h[drop1.item] = drop1.amount
else
h[drop1.item] = drop1.amount
end
elsif rand1 == 1
if h.has_key? drop2.item
drop2.amount += 60
h[drop2.item] = drop2.amount
else
h[drop2.item] = drop2.amount
end
end
end
For checking the result:
p h
p drop1.amount
p drop2.amount
Other option, if it is viable for you, let the class do the job defining it like this:
class Drop
attr_accessor :item, :price, :amount
def initialize(item:'no_name', price: 0, amount: 0)
#item = item
#price = price
#amount = amount
#counts = 0
#increment = amount
end
def count!
#counts += 1
#amount += #increment if #counts > 1
end
end
Then store the instances in an array:
drops = []
drops << Drop.new(item: 'item1', price: 2247, amount: 1)
drops << Drop.new(item: 'item2', price: 4401, amount: 60)
Run the random picking sampling the drops array:
10.times do |x|
drops.sample.count!
end
Check the result:
drops.each do |drop|
puts "#{drop.item} - #{drop.amount} - #{drop.price}"
end
You can also define a reset method which restores the amount and the counts to the original value:
def reset
#amount = #increment
#count = 0
end

How to 'puts' a number list of items in the array using an 'until' loop

I am using loops and a counter to put out a numbered list of items. It lists them all at once under 1, and then 2 is another round of listing of all of the items.
The while loop doesn't work and I figured until was better. I also moved counter outside of the first iteriation but that doesn't work either.
require 'pry'
require 'rubygems'
require 'open-uri'
require 'nokogiri'
class KefotoScraper::CLI
def initialize
#product_names = []
#page_url = "https://kefotos.mx/"
end
def call
puts "These are the services that Kefoto offers:"
list_products
end
private
def home_html
Nokogiri::HTML(open(#page_url))
end
def service_names
#service_names = home_html.css(".nav-link").map do |link|
link['href'].to_s.gsub(/.php/, "")
end
#service_names.each do |pr|
#product_names << pr
end
#product_names
end
def list_products
i = 1
n = 0
until #product_names.length < n do
#product_names.each {|list_item| puts "#{i} #{list_item}"}
i += 1
n += 1
end
end
def service_links
#service_links ||= home_html.css(".nav-item").map { |link| link['href'] }
end
end
The list repeats itself over and over again.
[3] pry(#<KefotoScraper::CLI>)> #product_names
=> ["foto-enmarcada", "impresion-fotografica", "photobooks", "impresion-directa-canvas", "impresion-acrilico", "fotoregalos"]
[4] pry(#<KefotoScraper::CLI>)> list_products
1 foto-enmarcada
1 impresion-fotografica
1 photobooks
1 impresion-directa-canvas
1 impresion-acrilico
1 fotoregalos
2 foto-enmarcada
2 impresion-fotografica
2 photobooks
2 impresion-directa-canvas
2 impresion-acrilico
2 fotoregalos
def list_products
#product_names.each_with_index do |list_item, i|
puts "#{i} #{list_item}"
end
end
edit: thanks for the feedback, the Tin Man.
With your current code, you're looping through #product_names once with until and inside of that you're looping through #product_names with .each. For example if #product_names.length == 3, you'd print 3 * 3 == 9 times!
Since you only need to loop through #product_names once, pick either until or .each. My example above uses .each and here is an example using until:
i = 1
until #product_names.length < i do
puts "#{i} #{#product_names[i-1]}"
i += 1
end

Player vs computer [closed]

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.

A very specific Conway's Game of Life (Ruby beginner)

Looking for feedback on obvious logic errors on this, not optimizing. I keep getting weird tick counts on the end game message (ex: 1 tick turns into 11 ticks)
The largest error I can spot while running the code is on the 2nd tick, a very large amount of alive cells appear. I am too new to this to understand why, but it seems like the #alive_cells is not resetting back to 0 after each check.
Here is my entire code, its large but it should be child's play to anyone with experience.
class CellGame
def initialize
puts "How big do you want this game?"
#size = gets.chomp.to_i
#cell_grid = Array.new(#size) { Array.new(#size) }
#grid_storage = Array.new(#size) { Array.new(#size) }
#tick_count = 0
fill_grid_with_random_cells
end
def fill_grid_with_random_cells
#cell_grid.each do |row|
row.map! do |cell|
roll = rand(10)
if roll > 9
"•"
else
" "
end
end
end
check_cells_for_future_state
end
def check_for_any_alive_cells
#cell_grid.each do |row|
if row.include?("•")
check_cells_for_future_state
break
else
end_game_print_result
end
end
end
def check_cells_for_future_state
#cell_grid.each_with_index do |row, row_index|
row.each_with_index do |cell, cell_index|
#live_neighbors = 0
add_row_shift = (row_index + 1)
if add_row_shift == #size
add_row_shift = 0
end
add_cell_shift = (cell_index + 1)
if add_cell_shift == #size
add_cell_shift = 0
end
def does_this_include_alive(cell)
if cell.include?("•")
#live_neighbors +=1
end
end
top_left_cell = #cell_grid[(row_index - 1)][(cell_index - 1)]
does_this_include_alive(top_left_cell)
top_cell = #cell_grid[(row_index - 1)][(cell_index)]
does_this_include_alive(top_cell)
top_right_cell = #cell_grid[(row_index - 1)][(add_cell_shift)]
does_this_include_alive(top_right_cell)
right_cell = #cell_grid[(row_index)][(add_cell_shift)]
does_this_include_alive(right_cell)
bottom_right_cell = #cell_grid[(add_row_shift)][(add_cell_shift)]
does_this_include_alive(bottom_right_cell)
bottom_cell = #cell_grid[(add_row_shift)][(cell_index)]
does_this_include_alive(bottom_cell)
bottom_left_cell = #cell_grid[(add_row_shift)][(cell_index - 1)]
does_this_include_alive(bottom_left_cell)
left_cell = #cell_grid[(row_index)][(cell_index - 1)]
does_this_include_alive(left_cell)
if #live_neighbors == 2 || #live_neighbors == 3
#grid_storage[row_index][cell_index] = "•"
else
#grid_storage[row_index][cell_index] = " "
end
end
end
update_cell_grid
end
def update_cell_grid
#cell_grid = #grid_storage
print_cell_grid_and_counter
end
def print_cell_grid_and_counter
system"clear"
#cell_grid.each do |row|
row.each do |cell|
print cell + " "
end
print "\n"
end
#tick_count += 1
print "\n"
print "Days passed: #{#tick_count}"
sleep(0.25)
check_for_any_alive_cells
end
def end_game_print_result
print "#{#tick_count} ticks were played, end of game."
exit
end
end
I couldn't see where your code went wrong. It does have a recursive call which can easily cause strange behavior. Here is what I came up with:
class CellGame
def initialize(size)
#size = size; #archive = []
#grid = Array.new(size) { Array.new(size) { rand(3).zero? } }
end
def lives_on?(row, col)
neighborhood = (-1..1).map { |r| (-1..1).map { |c| #grid[row + r] && #grid[row + r][col + c] } }
its_alive = neighborhood[1].delete_at(1)
neighbors = neighborhood.flatten.count(true)
neighbors == 3 || neighbors == 2 && its_alive
end
def next_gen
(0...#size).map { |row| (0...#size).map { |col| lives_on?(row, col) } }
end
def play
tick = 0; incr = 1
loop do
#archive.include?(#grid) ? incr = 0 : #archive << #grid
sleep(0.5); system "clear"; #grid = next_gen
puts "tick - #{tick += incr}"
puts #grid.map { |row| row.map { |cell| cell ? '*' : ' ' }.inspect }
end
end
end
cg = CellGame.new 10
cg.play
The tick count stops but the program keeps running through the oscillator at the end.
I wanted to revisit this and confidently say I have figured it out! Here is my new solution - still super beginner focused. Hope it helps someone out.
class Game
# Uses constants for values that won't change
LIVE = "🦄"
DEAD = " "
WIDTH = 68
HEIGHT = 34
def initialize
# Sets our grid to a new empty grid (set by method below)
#grid = empty_grid
# Randomly fills our grid with live cells
#grid.each do |row|
# Map will construct our new array, we use map! to edit the #grid
row.map! do |cell|
if rand(10) == 1
LIVE # Place a live cell
else
DEAD # Place a dead cell
end
end
end
# Single line implimentation
# #grid.each {|row|row.map! {|cell|rand(10) == 1 ? LIVE : DEAD}}
loop_cells #start the cycle
end
def empty_grid
Array.new(HEIGHT) do
# Creates an array with HEIGHT number of empty arrays
Array.new(WIDTH) do
# Fills each array with a dead cell WIDTH number of times
DEAD
end
end
# Single line implimentation
# Array.new(HEIGHT){ Array.new(WIDTH) { DEAD } }
end
def print_grid # Prints our grid to the terminal
system "clear" # Clears the terminal window
# Joins cells in each row with an empty space
rows = #grid.map do |row|
row.join(" ")
end
# Print rows joined by a new line
print rows.join("\n")
# Single line implimentation
# print #grid.map{|row| row.join(" ")}.join("\n")
end
def loop_cells
print_grid # Start by printing the current grid
new_grid = empty_grid # Set an empty grid (this will be the next life cycle)
# Loop through every cell in every row
#grid.each_with_index do |row, row_index|
row.each_with_index do |cell, cell_index|
# Find the cells friends
friends = find_friends(row_index, cell_index)
# Apply life or death rules
if cell == LIVE
state = friends.size.between?(2,3)
else
state = friends.size == 3
end
# Set cell in new_grid for the next cycle
new_grid[row_index][cell_index] = state ? LIVE : DEAD
end
end
# Replace grid and start over
#grid = new_grid
start_over
end
def find_friends(row_index, cell_index)
# Ruby can reach backwards through arrays and start over at the end - but it cannot reach forwards. If we're going off the grid, start over at 0
row_fix = true if (row_index + 1) == HEIGHT
cell_fix = true if (cell_index + 1) == WIDTH
# You'll see below I will use 0 if one of these values is truthy when checking cells to the upper right, right, lower right, lower, and lower left.
# Check each neighbor, use 0 if we're reaching too far
friends = [
#grid[(row_index - 1)][(cell_index - 1)],
#grid[(row_index - 1)][(cell_index)],
#grid[(row_index - 1)][(cell_fix ? 0 : cell_index + 1)],
#grid[(row_index)][(cell_fix ? 0 : cell_index + 1)],
#grid[(row_fix ? 0 : row_index + 1)][(cell_fix ? 0 : cell_index + 1)],
#grid[(row_fix ? 0 : row_index + 1)][(cell_index)],
#grid[(row_fix ? 0 : row_index + 1)][(cell_index - 1)],
#grid[(row_index)][(cell_index - 1)]
]
# Maps live neighbors into an array, removes nil values
friends.map{|x| x if x == LIVE}.compact
end
def start_over
sleep 0.1
loop_cells
end
end
# Start game when file is run
Game.new

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