Eksempler
Disse eksempler kan bruges i forbindelse med undervisning i forskellige sammenhænge. Kontakt Michell for yderligere oplysninger.
OOP/FOP
Brug eventuelt disse klasser til at forklare OOP og FOP.
Tip
using TerningSpil;
// Sætter LogMetode til at skrive log til konsollen
Terning.LogMetode = Console.WriteLine;
// eller en fil
// Terning.LogMetode = tekst => File.AppendAllText("log.txt", tekst + Environment.NewLine); ;
// eller begge
Terning.LogMetode += tekst => File.AppendAllText("log.txt", tekst + Environment.NewLine); ;
// Opretter en ny terning og 'ryster' den
Terning t = new();
Skriv("Terningens værdi: " + t);
// Opretter en ny terning med en bestemt værdi
Terning t2 = new(4);
Skriv("Terningens værdi: " + t2);
// Opretter en ny snydeterning
Terning t3 = new(true);
Skriv("Terningens værdi: " + t3);
// Anden måde at oprette en terning på
Terning t4 = 5;
// Sætter LogMetode til at skrive log til en fil
// Opretter en ny LudoTerning og 'ryster' den
LudoTerning lt = new();
Skriv("LudoTerningens værdi: " + lt);
Skriv("Er Globus: " + lt.ErGlobus());
Skriv("Er Stjerne: " + lt.ErStjerne());
TerningBæger terningBæger = new(Terning.OpretTerninger(5));
Skriv(terningBæger);
TerningBæger terningBæger2 = new(LudoTerning.OpretTerninger(5));
Skriv(terningBæger2);
terningBæger2.Ryst();
Skriv(terningBæger2);
static void Skriv(object o)
{
Console.WriteLine("\r\n" + o + "\r\n");
}
namespace TerningSpil
{
/// <summary>
/// Klassen 'Terning' repræsenterer en terning i et spil.
/// Den kan have en værdi mellem 1 og 6, ligesom en almindelig terning.
/// Der er også mulighed for at lave en 'snydeterning', som altid lander på 6.
/// </summary>
public class Terning
{
// En statisk Random-instans, der bruges til at generere tilfældige tal.
private static readonly Random rnd = new();
// Et readonly felt, der angiver om terningen er en snydeterning.
private readonly bool snyd;
// Privat felt til at holde værdien af terningen.
private int værdi;
/// <summary>
/// Standardkonstruktør. Opretter en ny terning og 'ryster' den for at få en tilfældig værdi.
/// </summary>
public Terning()
{
Log("Ny terning");
this.Ryst();
}
/// <summary>
/// Konstruktør, der tillader angivelse af en bestemt værdi til terningen.
/// </summary>
/// <param name="værdi">Den ønskede værdi for terningen.</param>
public Terning(int værdi)
{
Log($"Ny terning med værdi {værdi}");
this.Værdi = værdi;
}
/// <summary>
/// Konstruktør, der skaber en snydeterning. En snydeterning har altid værdien 6.
/// </summary>
/// <param name="snyd">Hvis sat til true, laves en snydeterning.</param>
public Terning(bool snyd)
{
Log($"Ny snydeterning");
this.snyd = snyd;
this.værdi = 6;
}
/// <summary>
/// En statisk delegate, der kan holde en reference til en log-metode.
/// LogMetode bruges til at logge forskellige aktiviteter og begivenheder.
/// </summary>
public static Action<string?>? LogMetode { get; set; }
/// <summary>
/// Egenskab til at få eller sætte værdien af terningen.
/// Hvis værdien er uden for det tilladte område (1-6), kastes en fejl.
/// </summary>
/// <exception cref="ApplicationException">Kastes, hvis værdien er uden for intervallet 1-6.</exception>
public int Værdi
{
get
{
Log($"Værdi {værdi} aflæst");
return værdi;
}
set
{
if (value < 1 || value > 6)
{
Log($"Værdi {value} er ikke tilladt");
throw new ApplicationException("Forkert værdi");
}
Log($"Værdi sat til {value}");
værdi = value;
}
}
/// <summary>
/// Genererer en tilfældig værdi for en terning.
/// </summary>
/// <returns>En tilfældig værdi mellem 1 og 6.</returns>
public static int FindTilfældigTerningVærdi()
{
int v = rnd.Next(1, 7);
Log("FindTilfældigTerningVærdi kaldt - " + v + " fundet");
return v;
}
/// <summary>
/// Tillader implicit konvertering fra en Terning til en integer.
/// </summary>
/// <param name="terning">Terningen, der skal konverteres til en integer.</param>
public static implicit operator int(Terning terning)
{
Log($"Konvertering fra terning med værdi {terning.Værdi} til int");
return terning.Værdi;
}
/// <summary>
/// Tillader implicit konvertering fra en integer til en Terning.
/// </summary>
/// <param name="value">Integer værdien, der skal konverteres til en Terning.</param>
public static implicit operator Terning(int value)
{
Log($"Konvertering fra int til terning med værdi {value}");
return new(value);
}
// En privat metode til at logge beskeder. Bruger LogMetode, hvis den er sat.
public static void Log(string tekst)
{
string tid = DateTime.Now.ToString("HH:mm:ss:ffff");
LogMetode?.Invoke($"{tid} {tekst}");
}
/// <summary>
/// Overloader != operatoren for at sammenligne to terninger baseret på deres værdier.
/// </summary>
/// <param name="t1">Den første terning til sammenligning.</param>
/// <param name="t2">Den anden terning til sammenligning.</param>
/// <returns>True, hvis terningerne ikke har samme værdi, ellers false.</returns>
public static bool operator !=(Terning t1, Terning t2)
{
var v = !(t1 == t2);
Log("!= kaldt - resultat " + v);
return v;
}
/// <summary>
/// Overloader < operatoren for at bestemme, om en terning har en lavere værdi end en anden.
/// </summary>
/// <param name="t1">Den første terning til sammenligning.</param>
/// <param name="t2">Den anden terning til sammenligning.</param>
/// <returns>True, hvis den første ternings værdi er lavere end den anden, ellers false.</returns>
public static bool operator <(Terning t1, Terning t2)
{
var r = t1.Værdi < t2.Værdi;
Log("< kaldt - resultat " + r);
return r;
}
/// <summary>
/// Overloader == operatoren for at sammenligne to terninger baseret på deres værdier.
/// </summary>
/// <param name="t1">Den første terning til sammenligning.</param>
/// <param name="t2">Den anden terning til sammenligning.</param>
/// <returns>True, hvis terningerne har samme værdi, ellers false.</returns>
public static bool operator ==(Terning t1, Terning t2)
{
var v = t1.Værdi == t2.Værdi;
Log("== kaldt - resultat " + v);
return v;
}
/// <summary>
/// Overloader > operatoren for at bestemme, om en terning har en højere værdi end en anden.
/// </summary>
/// <param name="t1">Den første terning til sammenligning.</param>
/// <param name="t2">Den anden terning til sammenligning.</param>
/// <returns>True, hvis den første ternings værdi er højere end den anden, ellers false.</returns>
public static bool operator >(Terning t1, Terning t2)
{
var r = t1.Værdi > t2.Værdi;
Log("> kaldt - resultat " + r);
return r;
}
/// <summary>
/// Opretter en liste af terninger med en bestemt størrelse.
/// </summary>
/// <param name="antal">antal terninger</param>
/// <returns>Liste af terninger</returns>
public static List<Terning> OpretTerninger(int antal)
{
List<Terning> terninger = new();
for (int i = 0; i < antal; i++)
{
terninger.Add(new Terning());
}
return terninger;
}
/// <summary>
/// Bestemmer om et givet objekt er lig med den aktuelle terning.
/// </summary>
/// <param name="obj">Objektet, der skal sammenlignes med den aktuelle terning.</param>
/// <returns>True, hvis objekterne er ens, ellers false.</returns>
public override bool Equals(object? obj)
{
if (ReferenceEquals(this, obj))
{
Log("Equals kaldt - resultat true");
return true;
}
if (obj is null)
{
Log("Equals kaldt - resultat false");
return false;
}
throw new NotImplementedException();
}
/// <summary>
/// Returnerer en hashkode for denne instans.
/// </summary>
/// <returns>En hashkode for den aktuelle terning.</returns>
public override int GetHashCode()
{
Log("GetHashCode kaldt");
return base.GetHashCode();
}
/// <summary>
/// Metode til at 'ryste' terningen, hvilket resulterer i en ny tilfældig værdi.
/// For en snydeterning vil værdien altid være 6.
/// </summary>
public void Ryst()
{
if (snyd)
{
this.Værdi = 6;
Log("Snydeterning 'rystet' til en 6'er");
}
else
{
int v = FindTilfældigTerningVærdi();
Log("Terning rystet til en " + v + "'er");
this.Værdi = v;
}
}
/// <summary>
/// Returnerer en strengrepræsentation af terningens nuværende værdi.
/// </summary>
/// <returns>En streng, der viser terningens værdi i firkantede parenteser.</returns>
public override string ToString()
{
Log("Terning vist som tekst");
return $"[ {this.Værdi} ]";
}
}
/// <summary>
/// Klassen 'LudoTerning' udvider 'Terning'-klassen og tilføjer specifik funktionalitet for et Ludo-spil.
/// Denne klasse introducerer specielle terningsider som 'Globus' og 'Stjerne', udover de normale værdier fra 1 til 6.
/// </summary>
public class LudoTerning : Terning
{
/// <summary>
/// Standardkonstruktør. Opretter en ny LudoTerning med en tilfældig værdi.
/// </summary>
public LudoTerning() : base()
{
Log("Ny LudoTerning");
}
/// <summary>
/// Konstruktør, der tillader angivelse af en bestemt værdi til LudoTerningen.
/// </summary>
/// <param name="værdi">Den ønskede værdi for LudoTerningen.</param>
public LudoTerning(int værdi) : base(værdi)
{
Log("Ny LudoTerning med værdi " + værdi);
}
/// <summary>
/// Konstruktør, der skaber en LudoTerning, som kan være en snydeterning.
/// </summary>
/// <param name="snyd">Hvis sat til true, laves en snyde LudoTerning.</param>
public LudoTerning(bool snyd) : base(snyd)
{
Log("Ny LudoTerning med snyd " + snyd);
}
/// <summary>
/// Opretter en liste af ludo terninger med en bestemt størrelse.
/// </summary>
/// <param name="antal">antal terninger</param>
/// <returns>Liste af terninger</returns>
public static List<LudoTerning> OpretLudoTerninger(int antal)
{
List<LudoTerning> terninger = new();
for (int i = 0; i < antal; i++)
{
terninger.Add(new LudoTerning());
}
return terninger;
}
/// <summary>
/// Bestemmer om LudoTerningens nuværende værdi er et 'Globus' symbol.
/// I Ludo repræsenterer 'Globus' en speciel handling eller regel.
/// </summary>
/// <returns>True, hvis terningen viser et 'Globus', ellers false.</returns>
public bool ErGlobus()
{
var r = this.Værdi == 3;
Log("ErGlobus kaldt - resultat " + r);
return r;
}
/// <summary>
/// Bestemmer om LudoTerningens nuværende værdi er et 'Stjerne' symbol.
/// I Ludo repræsenterer 'Stjerne' en speciel handling eller regel.
/// </summary>
/// <returns>True, hvis terningen viser en 'Stjerne', ellers false.</returns>
public bool ErStjerne()
{
var r = this.Værdi == 5;
Log("ErStjerne kaldt - resultat " + r);
return r;
}
/// <summary>
/// Returnerer en strengrepræsentation af LudoTerningens nuværende værdi.
/// Viser 'G' for Globus, 'S' for Stjerne, eller den numeriske værdi for andre sider.
/// </summary>
/// <returns>En streng, der repræsenterer LudoTerningens nuværende side.</returns>
public override string ToString()
{
if (this.ErGlobus())
{
Log("LudoTerning vist som globus");
return "[ G ]";
}
else if (this.ErStjerne())
{
Log("LudoTerning vist som stjerne");
return "[ S ]";
}
else
{
Log("LudoTerning vist som tekst");
return base.ToString();
}
}
}
/// <summary>
/// Repræsenterer et bæger, der kan indeholde en samling af Terning-objekter.
/// </summary>
public class TerningBæger
{
// Liste til at holde terninger.
private readonly List<Terning> terninger;
/// <summary>
/// Initialiserer en ny instans af TerningBæger-klassen med en foruddefineret liste af Terning-objekter.
/// </summary>
/// <param name="terninger">Listen af terninger, der skal tilføjes til bægeret.</param>
/// <exception cref="ArgumentNullException">Kastes, hvis den medfølgende liste er null.</exception>
public TerningBæger(List<Terning> terninger)
{
// Sikrer, at den medfølgende liste ikke er null.
if (terninger is null)
{
throw new ArgumentNullException(nameof(terninger), "Liste af terninger må ikke være null.");
}
Terning.Log("Bæger med terninger oprettet");
this.terninger = terninger;
}
/// <summary>
/// Ryster alle terningerne i bægeret for at ændre deres værdi.
/// </summary>
public void Ryst()
{
foreach (var t in terninger)
{
t.Ryst();
}
Terning.Log("Bæger rystet");
}
/// <summary>
/// Returnerer en strengrepræsentation af bægerets indhold.
/// </summary>
/// <returns>En streng, der viser hver ternings værdi i bægeret.</returns>
public override string ToString()
{
Terning.Log("Bæger vist som tekst");
string result = "";
foreach (var t in terninger)
{
result += t.ToString() + " ";
}
return result.TrimEnd();
}
}
}