我有六名球员。这意味着我有十五个独特的游戏:
players = [1, 2, 3, 4, 5, 6]
games = players.combination(2).to_a
# => [[1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [2, 3], [2, 4], [2, 5],
# [2, 6], [3, 4], [3, 5], [3, 6], [4, 5], [4, 6], [5, 6]]
我想将这些游戏随机分为5轮3.每个玩家每轮应该玩1场比赛,并且任何一对都不应该重复上一轮比赛。
在每一轮中,我尝试使用player1
循环与player2
随机选择while
和each
,但我总是以无限循环结束。有什么建议吗?
所以这是代码(抱歉没有把它放在预告片中)。问题是,有时它确实有效并且给了我想要的结果,但有时它只是分解并且它被捕获在循环中。
def pick_pair(players)
player1 = players[rand(players.length)]
players.delete(player1)
player2 = players[rand(players.length)]
players.delete(player2)
pair = [player1, player2]
return pair.sort!
end
def check_round(all_rounds, current_round)
repeat = false
if all_rounds == []
repeat = false
else
repeat = catch :repeat do
k = 0
all_rounds.each do |round|
a_r_l = all_rounds.length
round.each do |pair|
r_l = round.length
k += 1
z = 0
current_round.each do |new_pair|
#p "Comparing: #{pair} to #{new_pair}"
z += 1
if pair == new_pair
repeat = true
throw :repeat, repeat
elsif (k == a_r_l*r_l and z == current_round.length and pair != new_pair)
repeat = false
throw :repeat, repeat
end
end
end
end
end
end
return repeat
end
players = [1,2,3,4,5,6]
all_rounds = []
for i in 1..(players.length-1)
#p "Round: #{i}"
players_d = players.dup
current_round = catch :round do
check = true
while check
current_round = []
for j in 1..(players.length/2)
#p "Game: #{j}"
pair = pick_pair(players_d)
current_round << pair
end
p "Previous rounds: #{all_rounds}"
p "Current round: #{current_round}"
repeat = check_round(all_rounds, current_round)
if repeat == false
throw :round, current_round
else
players_d = players.dup
end
end
end
all_rounds << current_round
end
嗨,
感谢您的帮助。我重写了代码,它似乎工作。它也更简单:
players = [1,2,3,4,5,6]
possible_games = players.combination(2).to_a
all_games = []
for i in 1..(players.length - 1)
round = catch :round do
check = true
while check
round = []
for i in 1..(players.length/2)
pair = possible_games[rand(possible_games.length)]
round << pair
end
if round.flatten.uniq == round.flatten
round.each do |game|
possible_games.delete(game)
end
throw :round, round
else
end
end
end
all_games << round.sort!
end
p all_games
答案 0 :(得分:3)
基本上,您正在尝试随机组合并重试,直到该方案有效。它会偶尔成功,但有时会陷入僵局:
Round 1 2 3 4 5
12 14 16 13
34 36 32 5??
56 52 54
在第4轮中,玩家5必须玩1或3玩家,但这不会发生因为3已经在玩1.您的脚本会一直重试直到时间结束。
这样的锦标赛被称为循环锦标赛;维基百科有an algorithm。
答案 1 :(得分:1)
虽然严格来说,这里最好(最有效)的解决方案是使用steenslang建议的“循环”算法。
我建议采用一种更简单的方法,这种方法很有效且很直接。
基本上,该程序试图让每一轮每个玩家每轮玩一次。它遍历一个混合的组合数组并尝试将它们配对。如果无法进行组合,则会对阵列进行重新洗牌并再次尝试。
这很简单,效果很好。
另外,如果你需要的话,你可以改变玩家的数量而且它只是有效。
希望这会有所帮助:
players = [1, 2, 3, 4, 5, 6]
initial_games = players.combination(2).to_a.shuffle
players_sum = players.inject{|sum,x| sum + x }
all_rounds = []
games = initial_games
until games.empty?
current_round = []
games.each do |game|
if (current_round.flatten & game).empty?
current_round << game
end
end
current_round_sum = current_round.flatten.inject{|sum,x| sum + x }
if current_round_sum == players_sum
all_rounds << current_round
games = games - current_round
else
all_rounds = []
games = initial_games.shuffle
end
end
puts all_rounds.inspect # this outputs 5 rounds of 3 games