Gå til indholdet

O293 LINQ (Yatzy bæger)

Denne opgave bygger lidt videre på opgave N207 Simpel klasse (Yatzy bæger) hvor du skulle skabe en klasse til at repræsentere en terning og et Yatzy bæger.

Nu skal du bruge LINQ til at tilføje de almindelige Yatzy regler til bægeret - herunder:

  • En metode AntalEns(int værdi) som returnerer antallet af terninger med den givne værdi.
  • En metode Sum(int værdi) som returnerer summen af terninger med den givne værdi.
  • En egenskab (get) SamletSum som returnerer summen af alle terninger.
  • En egenskab (get) Par som returnerer summen af de to terninger, der udgør et par.
  • En egenskab (get) ToPar som returnerer summen af de to terninger, der udgør to par.
  • En egenskab (get) TreEns som returnerer summen af de tre terninger, der udgør tre ens.
  • En egenskab (get) FireEns som returnerer summen af de fire terninger, der udgør fire ens.
  • En egenskab (get) LilleStraight som returnerer 15, hvis terningerne udgør en lille straight.
  • En egenskab (get) StorStraight som returnerer 20, hvis terningerne udgør en stor straight.
  • En egenskab (get) FuldtHus som returnerer summen af terningerne, hvis de udgør et fuldt hus.
  • En egenskab (get) Chance som returnerer summen af alle terninger.
  • En egenskab (get) Yatzy som returnerer 50, hvis terningerne udgør en Yatzy.
  • En egenskab (get) Indhold som viser alle terningerne.

Her er et forslag til en klassestruktur:

classDiagram
    class Bæger {
        -Terning[] terninger
        +Bæger()
        +Bæger(Terning[] terninger)
        +Bæger(params int[] værdier)
        +void Ryst()
        +string Indhold
        +int AntalEns(int værdi)
        +int Sum(int værdi)
        +int SamletSum
        +int Par
        +int ToPar
        +int TreEns
        +int FireEns
        +int LilleStraight
        +int StorStraight
        +int FuldtHus
        +int Chance
        +int Yatzy
    }

    class Terning {
        +int Værdi
        +Terning()
        +Terning(int værdi)
        +void Ryst()
        +string ToString()
    }

    Bæger "1" --> "5" Terning

Bemærk, at der skal oprettes egenskaber (get) for de forskellige regler. Det vil gøre det nemmere at teste, seriatisere og vise bægerets indhold.

Du kan eksempelvis blot tilføje NuGet-pakken Dumpify og bruge Dump() metoden til at vise bægerets indhold.

Bemærk også de forskellige konstruktører til klassen Bæger og Terning.

I min løsning kan jeg skrive:

using Dumpify;

Bæger bæger;

bæger = new Bæger(1, 1, 1, 1, 1);
bæger.Dump();

bæger = new Bæger(1, 1, 1, 2, 2);
bæger.Dump();


bæger = new Bæger();
bæger.Dump();

Hvilket vil give følgende output men du kan kode det som du vil - det vigtigste er at du får implementeret de forskellige regler.

Output fra Dumpify
Klik for at se et forslag til en løsning
using Dumpify;

Bæger bæger;

bæger = new Bæger(1, 1, 1, 1, 1);
bæger.Dump();

bæger = new Bæger(1, 1, 1, 2, 2);
bæger.Dump();


bæger = new Bæger();
bæger.Dump();

public class Bæger
{
    private Terning[] terninger = new Terning[5];

    public Bæger()
    {
        for (int i = 0; i < 5; i++)
            terninger[i] = new Terning();
        Ryst();
    }

    public Bæger(Terning[] terninger)
    {
        if (terninger.Length != 5)
            throw new ArgumentException("Der skal være 5 terninger i bægeret");
        this.terninger = terninger;
    }

    public Bæger(params int[] værdier)
    {
        if (værdier.Length != 5)
            throw new ArgumentException("Der skal være 5 terninger i bægeret");
        for (int i = 0; i < 5; i++)
            terninger[i] = new Terning(værdier[i]);
    }

    public void Ryst()
    {
        for (int i = 0; i < 5; i++)
            terninger[i].Ryst();
    }

    public string Indhold
    {
        get
        {
            return string.Join(" ", terninger.Select(t => t.ToString()));
        }
    }

    public int AntalEns(int værdi)
    {
        return terninger.Count(t => t.Værdi == værdi);
    }

    public int Sum(int værdi)
    {
        return terninger.Where(t => t.Værdi == værdi).Sum(t => t.Værdi);
    }

    public int SamletSum
    {
        get
        {
            return terninger.Sum(t => t.Værdi);
        }
    }

    public int Par
    {
        get
        {
            var par = terninger.GroupBy(t => t.Værdi)
                            .Where(g => g.Count() >= 2)
                            .OrderByDescending(g => g.Key)
                            .FirstOrDefault();
            return par != null ? par.Key * 2 : 0;
        }
    }

    public int ToPar
    {
        get
        {
            var par = terninger.GroupBy(t => t.Værdi)
                            .Where(g => g.Count() >= 2)
                            .OrderByDescending(g => g.Key)
                            .Take(2)
                            .ToArray();
            return par.Length == 2 ? par[0].Key * 2 + par[1].Key * 2 : 0;
        }
    }

    public int TreEns
    {
        get
        {
            var treEns = terninger.GroupBy(t => t.Værdi)
                                .Where(g => g.Count() >= 3)
                                .Select(g => g.Key * 3)
                                .FirstOrDefault();
            return treEns;
        }
    }

    public int FireEns
    {
        get
        {
            var fireEns = terninger.GroupBy(t => t.Værdi)
                                .Where(g => g.Count() >= 4)
                                .Select(g => g.Key * 4)
                                .FirstOrDefault();
            return fireEns;
        }
    }

    public int LilleStraight
    {
        get
        {
            var værdier = terninger.Select(t => t.Værdi).OrderBy(v => v).ToArray();
            return værdier.SequenceEqual(new[] { 1, 2, 3, 4, 5 }) ? 15 : 0;
        }
    }

    public int StorStraight
    {
        get
        {
            var værdier = terninger.Select(t => t.Værdi).OrderBy(v => v).ToArray();
            return værdier.SequenceEqual(new[] { 2, 3, 4, 5, 6 }) ? 20 : 0;
        }
    }

    public int FuldtHus
    {
        get
        {
            var grupper = terninger.GroupBy(t => t.Værdi).ToArray();
            var treEns = grupper.FirstOrDefault(g => g.Count() == 3);
            var toEns = grupper.FirstOrDefault(g => g.Count() == 2);
            return treEns != null && toEns != null ? treEns.Key * 3 + toEns.Key * 2 : 0;
        }
    }

    public int Chance
    {
        get
        {
            return SamletSum;
        }
    }

    public int Yatzy
    {
        get
        {
            return terninger.All(t => t.Værdi == terninger[0].Værdi) ? 50 : 0;
        }
    }
}

public class Terning
{
    public int Værdi { get; private set; }

    public Terning()
    {
        Ryst();
    }

    public Terning(int værdi)
    {
        this.Værdi = værdi;
    }

    public override string ToString()
    {
        return "[ " + this.Værdi + " ]";
    }

    public void Ryst()
    {
        this.Værdi = Random.Shared.Next(1, 7);
    }
}