2012-02-27 15 views
10

Zapisuję wartości w konsoli. Dwie osoby "pojedynkują się" przeciwko sobie, a ja użyłem słownika, aby zachować nazwy wraz z zadawanymi obrażeniami.Słownik z dwoma kluczami?

var duels = new Dictionary<string, string>(); 
duels.Add("User1", "50"); 
duels.Add("User2","34"); 

Próbuję zapisać zarówno użytkownikom w tym samym słowniku rzędu, więc to może być zweryfikowany jako User1 jest pojedynków przeciwko User2. W ten sposób, jeśli rozpocznie się kolejny pojedynek, nie będzie to kolidować z User1 lub .

duels.Add("KeyUser1","KeyUser2","50","34",.../*Other attributes of the duel*/); 

Potrzebuję dwóch kluczy, aby sprawdzić, gdzie znajdują się uszkodzenia użytkownika. Uszkodzenie zawsze trafia do drugiego klawisza - na odwrót. Co mogę zrobić, aby to zadziałało?

Dziękuję.

+7

Polecam używać do tego krotek. Oto powiązany artykuł, który może poprowadzić Cię we właściwym kierunku: http://stackoverflow.com/questions/1171812/multi-key-dictionary-in-c. Powodzenia! – SMT

+0

Czy pojedynczy użytkownik może być zaangażowany w więcej niż jeden pojedynek na raz? –

+0

Czy pojedynki z "Użytkownikiem1" i "Użytkownikiem2" są inne niż pojedynki z udziałem "Użytkownik2" i "Użytkownik1"? –

Odpowiedz

4
public class Duel 
{ 
    public string User1 {get; protected set;} 
    public string User2 {get; protected set;} 
    public Duel(string user1, string user2) 
    { 
    User1 = user1; 
    User2 = user2; 
    } 

    public HashSet<string> GetUserSet() 
    { 
    HashSet<string> result = new HashSet<string>(); 
    result.Add(this.User1); 
    result.Add(this.User2); 
    return result; 
    } 

    //TODO ... more impl 
} 

Zróbmy kilka pojedynków. CreateSetComparer umożliwia słownikowi użycie wartości zestawu do testowania równości.

List<Duel> duelSource = GetDuels(); 
Dictionary<HashSet<string>, Duel> duels = 
    new Dictionary<HashSet<string>, Duel>(HashSet<string>.CreateSetComparer()); 

foreach(Duel d in duelSource) 
{ 
    duels.Add(d.GetUserSet(), d); 
} 

i znalezienie Pojedynek:

HashSet<string> key = new HashSet<string>(); 
key.Add("User1"); 
key.Add("User2"); 
Duel myDuel = duels[key]; 
3

Można spróbować dokonywania niestandardowy typ danych dla klucza:

class DualKey<T> : IEquatable<DualKey<T>> where T : IEquatable<T> 
{ 
    public T Key0 { get; set; } 
    public T Key1 { get; set; } 

    public DualKey(T key0, T key1) 
    { 
     Key0 = key0; 
     Key1 = key1; 
    } 

    public override int GetHashCode() 
    { 
     return Key0.GetHashCode()^Key1.GetHashCode(); 
    } 

    public bool Equals(DualKey<T> obj) 
    { 
     return (this.Key0.Equals(obj.Key0) && this.Key1.Equals(obj.Key1)) 
      || (this.Key0.Equals(obj.Key1) && this.Key0.Equals(obj.Key0)); 
    } 
} 

Następnie użyj Dictionary<DualKey<string>, string>;

+1

Nie chcę brzmieć niegrzecznie, ale zgodnie z normą Stack Overflow, powinien to być komentarz do pierwotnego pytania, a nie przesłany jako odpowiedź. Nie chciałbyś, żebyś został głosowany :) – SMT

+1

Nie próbowałem wbudowanego słownika. Czy nie oznacza to jednak posiadania różnych kluczowych słowników? – Kyle

+1

@Trereault Ach, masz rację :(Mój błąd .. – Daryl

4

Coś szybkiego.

class UserScores { 

    public string Key { get; set; } 

    public int User1Score { get; set; } 
    public int User2Score { get; set; } 

    public UserScores(string username1, string username2) 
    { 
      Key = username1 + ":" + username2; 
    } 
} 

void Main() 
{ 
    var userScore = new UserScores("fooUser", "barUser"); 

    var scores = new Dictionary<string, UserScores>(); 

    scores.Add(userScore.Key, userScore); 

    // Or use a list 

    var list = new List<UserScores>(); 

    list.Add(userScore); 

    list.Single (l => l.Key == userScore.Key); 
} 

Mimo że właściwym rozwiązaniem moim zdaniem byłby lepiej przemyślany obiekt UserScores, który śledzi tę konkretną sesję "pojedynek".

+1

Co jeśli 'vin' i' yetish' walczą, podczas gdy 'viny' i' etish' walczą? :) –

+0

Podoba mi się pomysł ich połączenia.Myślę, że mógłbym dodać coś takiego jak "username1 +": "+ username2" i podzielić ':', aby uzyskać 'user [0]' i 'user [1]'. – Kyle

+0

Dzięki @PaulBellora, odpowiedź zaktualizowana. –

2

Ponieważ jedna osoba może brać udział w co najwyżej jednym pojedynku na raz, można korzystać z jednego słownika bezpośrednio „Index” oba punkty końcowe we wszystkich pojedynkach, coś takiego:

class Duel { 

    public Duel(string user1, string user2) { 
     Debug.Assert(user1 != user2); 
     User1 = user1; 
     User2 = user2; 
    } 

    public readonly string User1; 
    public readonly string User2; 
    public int User1Score; 
    public int User2Score; 

} 

class Program { 

    static void Main(string[] args) { 

     var dict = new Dictionary<string, Duel>(); 

     // Add a new duel. A single duel has two keys in the dictionary, one for each "endpoint". 
     var duel = new Duel("Jon", "Rob"); 
     dict.Add(duel.User1, duel); 
     dict.Add(duel.User2, duel); 

     // Find Jon's score, without knowing in advance whether Jon is User1 or User2: 
     var jons_duel = dict["Jon"]; 
     if (jons_duel.User1 == "Jon") { 
      // Use jons_duel.User1Score. 
     } 
     else { 
      // Use jons_duel.User2Score. 
     } 

     // You can just as easily find Rob's score: 
     var robs_duel = dict["Rob"]; 
     if (robs_duel.User1 == "Rob") { 
      // Use robs_duel.User1Score. 
     } 
     else { 
      // Use robs_duel.User2Score. 
     } 

     // You are unsure whether Nick is currently duelling: 
     if (dict.ContainsKey("Nick")) { 
      // Yup! 
     } 
     else { 
      // Nope. 
     } 

     // If Jon tries to engage in another duel while still duelling Rob: 
     var duel2 = new Duel("Jon", "Nick"); 
     dict.Add(duel2.User1, duel); // Exception! Jon cannot be engaged in more than 1 duel at a time. 
     dict.Add(duel2.User2, duel); // NOTE: If exception happens here instead of above, don't forget remove User1 from the dictionary. 

     // Removing the duel requires removing both endpoints from the dictionary: 
     dict.Remove(jons_duel.User1); 
     dict.Remove(jons_duel.User2); 

     // Etc... 

    } 

} 

to jest właśnie podstawowa idea, można rozważyć owijania tę funkcję w swojej własnej klasie ...

Powiązane problemy