2012-02-29 6 views
2

Je suis censé créer une méthode en Ruby qui prendra dans un cadre structuré, tableau à plusieurs dimensions, telles que:rubis: Luttant avec récursion

my_arr = [ 
[ [['Armando', 'P'], ['Dave', 'S']], [['Richard', 'R'], ['Michael', 'S']] ], 
[ [['Allen', 'S'], ['Omer', 'P']], [['David E.', 'R'], ['Richard X.', 'P']] ] 
] 

Ce tableau est censé représenter un tournoi de Rock , papier & ciseaux, le nombre de joueurs sera toujours de 2^n et aucune répétition (de joueurs) n'est faite.

Le code que j'ai écrit comme suit:

class WrongNumberOfPlayersError < StandardError ; end 
class NoSuchStrategyError < StandardError ; end 

def rps_game_winner(game) 
    raise WrongNumberOfPlayersError unless game.length == 2 
    valid = ["r","p","s"] 
    a1=[(game[0][1]).downcase] 
    a2=[(game[1][1]).downcase] 
    raise NoSuchStrategyError unless (valid & a1) && (valid & a2) 

    return (game[0]) if a1 === a2 
    case (a1[0]) 
    when "r" 
    case (a2[0]) 
    when "p" 
     return (game[1]) 
    else 
     return (game[0]) 
    end 
    when "p" 
    case (a2[0]) 
    when "s" 
     return (game[1]) 
    else 
     return (game[0]) 
    end 
    when "s" 
    case (a2[0]) 
    when "r" 
     return (game[1]) 
    else 
     return (game[0]) 
    end 
    end 
end 

def rps_tournament_winner(tournament) 
    if tournament[0][0].is_a?(Array) 
    rps_tournament_winner(tournament[0]) 
    elsif tournament[1][0].is_a?(Array) 
    rps_tournament_winner(tournament[1]) 
    else 
    rps_game_winner(tournament) 
    end 
end 

Donc mon problème est que compte tenu de l'utilisation du tableau je l'ai mentionné plus tôt étant passé à rps_tournament_winnerDave gagne toujours au lieu de Richard et je ne l'ai pas été en mesure pour savoir où je me suis trompé.

Ty pour la lecture de la paroi du texte/code :)

+1

Je vous recommande d'utiliser le ': papier,: rock ,: Il est plus facile de lire le code et plus vite pour l'interprète – farnoy

+0

le tableau que je suis fourni utilise les chaînes comme "R" "p", etc Je suppose que je pourrais avoir utilisé des symboles en interne? devez-vous le reconvertir en une chaîne de caractères pour le format de résultat requis (qui est comme ['Richard', 'R']? –

+0

Où initialisez-vous le tableau de jeu? –

Répondre

3

Une chose que j'ai remarquée est que votre utilisation de 'valide' ne fait rien pour vérifier si votre entrée est réellement valide. Si vous essayez de vérifier que a1 et a2 sont soit « r » « p » ou « s », vous devez utiliser une expression régulière:

valid = /[rps]/ # matches either "r" "p" or "s" 
raise NoSuchStrategyError unless (a1 =~ valid) && (a2 =~ valid) 

Votre tableau de joueurs est niché très profond.Vous vous simplifieront la vie en fluidifiant it out:

my_arr = [['Armando', 'P'], ['Dave', 'S'], ['Richard', 'R'], ['Michael', 'S'], 
     ['Allen', 'S'], ['Omer', 'P'], ['David E.', 'R'], ['Richard X.', 'P']] 

Vous pouvez le rendre plus facile à lire et à maintenir en brisant votre programme en plusieurs parties. Par exemple, créer une méthode pour déterminer une victoire:

# This is incomplete as it doesn't deal with ties. I'll let you do that part 
def win(first, second) 
    if (first == "p" && second == "r") || (first == "r" && second == "s") || (first == "s" && second == "p") 
    return true 
    else 
    return false 
    end 
end 

Maintenant, il est plus facile d'écrire et de comprendre le jeu lui-même, en utilisant la méthode ci-dessus:

def rps_game_winner(player1, player2) 
    first = player1[1].downcase 
    second = player2[1].downcase 
    win(first, second) ? player1 : player2 # ternary operator returns the winner 
end 

Vous avez maintenant une méthode pour mettre tout cela en jeu (sorte de la logique principale), et nous allons utiliser la récursivité ici:

def rps_tournament_winner(player_list) 
    round_winners = [] # place to hold the winners for each round 

    if player_list.size == 1 # final condition to stop the recursion 
    puts "The winner is #{player_list[0][0]}." 
    else 
    player_list.each_slice(2) do |l1, l2| # take pairs from your list to play each other 
     round_winners << rps_game_winner(l1, l2) 
    end 

    rps_tournament_winner(round_winners) # use recursion to play the winners against each other 
    end 
end 

# put it into play 
puts test_array(my_arr) 

C'est tout. Le gagnant est Richard et ce sera toujours Richard parce que le jeu est déterministe. Bien que cela fonctionne, sachez que j'ai omis certaines choses importantes comme traiter les liens et les nombres impairs de joueurs. Le programme ne fonctionnera pas dans ces conditions. Mais je vais laisser à vous de résoudre ces parties.

EDIT: Modification du tableau d'origine:

new_array = [] 
my_arr.flatten.each_slice(2) do |name, pick| 
    new_array << [name, pick] 
end 
+0

Il y avait une faute de frappe que j'ai corrigé, donc ça devrait marcher maintenant si ce n'était pas le cas auparavant ... à moins qu'il y ait une autre faute de frappe que j'ai manquée. : o – robotcookies

+0

Merci beaucoup, je suis nouveau à très nouveau à ruby ​​et codage en général, chacun de votre point est un bijou en effet, je vais prendre tous à cœur. En ce qui concerne le nombre de joueurs, il sera toujours pair (c'est ainsi que ma méthode est supposée recevoir le tableau des tournois). Obtenir la logique "Tie" sera facile. Encore une fois merci de disséquer ce code hideux et pour les astuces inestimables. Une dernière question, comment puis-je "éclaircir" mon tableau? peut-être Array # flatten –

+0

Salut, je vais modifier mon message pour montrer un moyen d'éclaircir votre tableau d'origine. Le champ de commentaire ne facilite pas l'affichage du code. Voir au dessus. – robotcookies

0

Il est très difficile de déboguer votre code.

Mais je pense que c'est fondamentalement vicié.

Lorsque vous appelez rps_tournament_winner vous passez

[ 
    [ [['Armando', 'P'], ['Dave', 'S']], [['Richard', 'R'], ['Michael', 'S']] ], 
    [ [['Allen', 'S'], ['Omer', 'P']], [['David E.', 'R'], ['Richard X.', 'P']] ] 
] 

Il demande tournament[0][0].is_a?(Array)

[['Armando', 'P'], ['Dave', 'S']], [['Richard', 'R'], ['Michael', 'S']] 

Oui il est.

Il appelle rps_tournament_winner(tournament[0])

tournament = [ [['Armando', 'P'], ['Dave', 'S']], [['Richard', 'R'], ['Michael', 'S']] ] 

Il demande tournament[0][0].is_a?(Array)

['Armando', 'P'] 

Oui il est.

appelle rps_tournament_winner(tournament[0])

tournament = [['Armando', 'P'], ['Dave', 'S']] 

Il demande tournament[0][0].is_a?(Array)

'Armando' 

Pas ses pas.

Il appelle rps_game_winner(tournament)

Et dans le jeu bat Dave Armando!

Je ne pense pas que ce soit la fonctionnalité que vous vouliez.

Je vous suggère de réécrire ceci, en essayant de garder les choses simples.

+0

TY, j'ai pensé qu'après 'victoires Armando', puis 'Richard' et 'Michael' s'affrontent dans lequel 'Richard' gagne et arrive à battre 'Armando' dans la récursivité suivante. Hors sujet: pouvez-vous suggérer des moyens pour que mon code soit plus simple, plus facile à lire et à déboguer? –

1

Votre récursion descend tournoi seulement [0] avant la fin du tournoi ne [1]. Vous devez jouer à la fois au tournoi [0] et au tournoi [1], puis jouez-les les uns contre les autres.

Quelque chose comme. (Je vous laisse écrire le code Ruby)

rps_game_winner ([rps_tournament_winner (tournoi [0], rps_tournament_winner (tournoi [1]])

+0

Oui, vous avez raison, l'exemple ci-dessus donne le mauvais résultat puisque le gagnant dans le "tableau entre parenthèses" décrit à l'origine par Osama Husain - mènerait à Richard X. gagnant. Le point important à noter est que la ligue est entre crochets. –