• Let op Ook op een List schrijf je elke bewerking zelf met een lus: geen LINQ zoals .Sum(), .Max(), .Where() of .Count() (boeteblad). De methoden van de List zelf (Add, Remove, Contains, IndexOf, …) en de property Count zonder haakjes mag je wel gebruiken.
  • Na new Student[5] staat er vijf keer null in de array. Maak elk object zelf aan met new, en controleer op null voor je een plaats gebruikt (uitleg).
  • Verwijderen terwijl je een lijst overloopt, doe je met een for van achter naar voor, nooit in een foreach (uitleg).
  • Contains, IndexOf en Remove zoeken op referentie: een nieuw object met dezelfde inhoud vinden ze niet.

Het kasticket

Je deed de boodschappen voor de week. Op het kasticket staan vijf prijzen. Welke artikels kostten 5 euro of meer, en wat was de gemiddelde prijs?

Deel 1. Maak een array voor de prijzen (double). Leg het aantal artikels vast in een const, zodat je het later op één plek kan veranderen. Vraag de gebruiker de vijf prijzen en bewaar ze in de array. Overloop daarna de array met een foreach en toon enkel de prijzen van 5 euro of meer. Toon op het einde het gemiddelde van alle prijzen, ook van de goedkope. Toon alle bedragen met twee cijfers na de komma.

Prijs van artikel 1:
>2,49
Prijs van artikel 2:
>7,99
Prijs van artikel 3:
>1,15
Prijs van artikel 4:
>12,50
Prijs van artikel 5:
>2,37
Artikels van 5 euro of meer:
7,99 euro
12,50 euro
Gemiddelde prijs: 5,30 euro

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

Deel 2. Kan het vullen ook met een foreach? Vervang de for die de prijzen inleest door deze lus:

foreach (double prijs in prijzen)
{
    Console.WriteLine("Prijs van een artikel:");
    prijs = double.Parse(Console.ReadLine());
}

Wat zegt de compiler, en waarom?

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

  • Een foreach overloopt alle elementen zonder teller. Handig om te lezen, maar schrijven in de array kan er niet mee.
  • Met een const voor het aantal test je met vijf prijzen, en verander je het later op één plek.
  • Zie Opgelet bij het gebruik van foreach loops.

Groepswerk met vijf (Essential)

Jij trekt het groepswerk voor programmeren. Een groep telt vijf plaatsen. Wie afhaakt, laat een lege plaats achter, en daar kan iemand anders in. Omdat het aantal plaatsen vastligt en de plaats een nummer heeft, gebruik je hier een array: Student[] groep = new Student[5];.

Gebruik de klasse Student uit de oefening Studentklasse van hoofdstuk 9 (met de enum Klassen en de methode BerekenGemiddelde()). Kopieer ze naar je nieuwe project.

Deel 1: lege plaatsen. Zet deze code in je Main en voer ze uit:

Student[] groep = new Student[5];
groep[0] = new Student() { Naam = "Jana" };
groep[2] = new Student() { Naam = "Mo" };

for (int i = 0; i < groep.Length; i++)
{
    Console.WriteLine($"Plaats {i + 1}: {groep[i].Naam}");
}

Wat gebeurt er, en op welke plaats loopt het mis? Pas de lus daarna aan zodat het programma dit toont:

Plaats 1: Jana
Plaats 2: vrij
Plaats 3: Mo
Plaats 4: vrij
Plaats 5: vrij

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

Deel 2: het groepsprogramma. Begin met een lege groep van vijf plaatsen en schrijf een menu dat blijft terugkomen tot de gebruiker 0 kiest:

  1. Iemand toevoegen. Vraag een plaats van 1 tot 5. Vraag opnieuw zolang de plaats daarbuiten ligt. Is de plaats al ingenomen, vraag dan of die student overschreven mag worden. Vraag daarna de naam, de klas (TI1, TI2 of TI3) en de punten voor de drie vakken, en zet een nieuwe student op die plaats.
  2. Groep tonen. Per plaats de naam, de klas en het gemiddelde, of vrij.
  3. Iemand verwijderen. Vraag een plaats en maak ze weer vrij.
  4. Groepsgemiddelde. Het gemiddelde van de gemiddeldes van wie er in de groep zit. Lege plaatsen tellen niet mee. Zit er nog niemand in, zeg dat dan.

Schrijf voor elk menu-item een methode die de array als parameter krijgt.

1. Iemand toevoegen
2. Groep tonen
3. Iemand verwijderen
4. Groepsgemiddelde
0. Stoppen
>1
Welke plaats (1 tot 5)?
>1
Naam?
>Jana
Klas (TI1, TI2 of TI3)?
>TI1
Punten communicatie?
>12
Punten programming principles?
>15
Punten web technology?
>13
...
>1
Welke plaats (1 tot 5)?
>3
Plaats 3 is al ingenomen door Mo. Overschrijven (j/n)?
>j
Naam?
>Mo Peeters
...
>2
Plaats 1: Jana (TI1), gemiddelde 13,33
Plaats 2: vrij
Plaats 3: Mo Peeters (TI2), gemiddelde 11,33
Plaats 4: vrij
Plaats 5: vrij
...
>4
Groepsgemiddelde van 2 studenten: 12,33

Wil je meer? Voeg een menu-item 5. Zoek op naam toe dat zegt op welke plaats iemand zit, of dat hij niet in de groep zit.

Tip

De klas komt als tekst binnen. Zet ze om naar de enum met Enum.Parse<Klassen>(Console.ReadLine()), of met een switch.

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

  • new Student[5] maakt vijf lege plaatsen (null), geen vijf studenten. Elke student maak je zelf met new.
  • Wie een lege plaats aanspreekt, krijgt een NullReferenceException. Controleer eerst met != null. Wil je enkel iets oproepen als het object bestaat, dan kan het ook korter met ?.: groep[i]?.GeefOverzicht();.
  • Een plaats vrijmaken is de referentie weer op null zetten.
  • Een array past hier, omdat het aantal plaatsen vastligt en de positie iets betekent. Zie Arrays van objecten aanmaken.

Voorspel de uitvoer: de playlist van de carpool (Essential)

In de carpool naar de campus ben jij de dj. Voor je playlist-app schreef je deze klasse:

internal class Nummer
{
    public string Titel { get; set; }
    public int KeerGespeeld { get; set; }
}

Schrijf bij elk deel eerst op papier wat het programma toont, lijn per lijn. Typ de code pas daarna over en vergelijk.

Deel 1. Een array met je top 3:

Nummer favoriet = new Nummer() { Titel = "Mr. Brightside" };
Nummer[] top3 = new Nummer[]
{
    favoriet,
    new Nummer() { Titel = "Sweet Caroline" },
    favoriet
};
Nummer kopie = top3[1];
kopie.Titel = "Dancing Queen";
top3[2].KeerGespeeld = 5;

Console.WriteLine(top3[1].Titel);
Console.WriteLine(favoriet.KeerGespeeld);
Console.WriteLine(top3[0].KeerGespeeld);

Hoeveel objecten van de klasse Nummer bestaan er in dit stuk code?

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

Deel 2. Zet deze code onder die van deel 1. Remove(x) zoekt x in de lijst, net zoals IndexOf, en haalt het eerste exemplaar dat het vindt weg.

List<Nummer> playlist = new List<Nummer>() { favoriet, top3[1], favoriet };
Nummer zoek = new Nummer() { Titel = "Dancing Queen" };
Console.WriteLine(playlist.Contains(zoek));
Console.WriteLine(playlist.IndexOf(top3[1]));

playlist.Remove(favoriet);
Console.WriteLine(playlist.Count);
Console.WriteLine(playlist.IndexOf(favoriet));

foreach (Nummer nummer in playlist)
{
    nummer.KeerGespeeld++;
}
Console.WriteLine(favoriet.KeerGespeeld);
Console.WriteLine(top3[1].KeerGespeeld);

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

  • Een array of lijst van objecten bevat referenties. Hetzelfde object kan er meer dan eens in staan, en een variabele erbuiten kan er ook naar verwijzen.
  • Contains, IndexOf en Remove zoeken op referentie. Zie Wat kan een List nog?.
  • In een foreach mag je een property van het object aanpassen. De iteration variabele zelf vervangen mag niet.

Stevens opruimactie (Essential)

De webshop waar stagiair Steven werkt, houdt een opruimactie: alle artikelen onder de 10 euro gaan uit het aanbod. Steven moet die prijzen uit een lijst verwijderen. Hij vroeg het aan een A.I. en levert na elkaar drie versies in. Het begin en het einde van zijn programma blijven telkens hetzelfde:

List<int> prijzen = new List<int>() { 12, 4, 7, 25, 3, 9, 8, 30 };

// hier komt de versie die opruimt

foreach (int prijs in prijzen)
{
    Console.Write($"{prijs} ");
}

Deel 1. De eerste versie:

foreach (int prijs in prijzen)
{
    if (prijs < 10)
    {
        prijzen.Remove(prijs);
    }
}

Het compileert. Voer het uit. Wat gebeurt er, en naar welke lijn wijst de foutmelding?

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

Deel 2. De tweede versie:

for (int i = 0; i < prijzen.Count; i++)
{
    if (prijzen[i] < 10)
    {
        prijzen.RemoveAt(i);
    }
}

Deze crasht niet. Steven testte ze met de lijst { 12, 4, 25, 3, 30 } en kreeg 12 25 30, dus hij is tevreden.

Voer ze nog niet uit met de startlijst van hierboven. Voorspel eerst op papier welke prijzen er op het scherm komen. Hou daarvoor per ronde bij wat i is, welke prijs er op die index staat, en hoe de lijst er na die ronde uitziet. Voer het daarna uit en vergelijk. Waarom blijven er prijzen onder de 10 euro staan, en waarom zag Steven dat niet bij zijn eigen test?

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

Deel 3. De derde versie:

for (int i = prijzen.Count - 1; i >= 0; i--)
{
    if (prijzen[i] < 10)
    {
        prijzen.RemoveAt(i);
    }
}

Klopt deze versie? Leg uit waarom het overslaan uit deel 2 hier niet kan gebeuren.

Maak er daarna een methode VerwijderOnderGrens van die de lijst en de grens als parameter krijgt, zodat de opruimactie volgend jaar ook met een andere grens kan.

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

  • foreach met Remove crasht meteen. Een for van voor naar achter met RemoveAt crasht niet, maar slaat telkens het element over dat meteen achter een verwijderd element staat. Die fout zie je enkel aan een verkeerd resultaat.
  • Test met data waarin het kan mislopen: hier zijn dat twee prijzen onder de grens die naast elkaar staan.
  • Wil je verwijderen terwijl je een lijst overloopt, gebruik dan een for van achter naar voor met RemoveAt.
  • Zie Opgelet bij het gebruik van foreach loops, Wat kan een List nog? en Stagiair Steven.

Computer-winkel: de stockverkoop (Essential)

De IT-dienst van de hogeschool ruimt op: oude computeronderdelen worden goedkoop aan studenten verkocht. Jij schrijft het programma dat de stock bijhoudt en filtert.

Deel 1: de klasse. Maak een klasse ComputerOnderdeel met drie auto-properties:

  • Prijs (int), in euro;
  • ID (int);
  • InDoos (bool): zit het onderdeel nog in zijn doos?

De default constructor geeft elk onderdeel willekeurige waarden: een prijs van 1 tot en met 1000, een ID van 100 tot en met 999, en een kans van 50% dat InDoos true is. Geef de klasse daarvoor één private static Random.

De methode ToonInfo() toont de drie waarden zo:

Prijs: 845, ID: 452, InDoos: True

Deel 2: filteren. Maak in Main een List<ComputerOnderdeel> en vul ze met 20 nieuwe onderdelen. Toon daarna na elkaar, telkens met een titel erboven (bv. Onderdelen in een doos:):

  1. alle onderdelen;
  2. de onderdelen duurder dan 400 euro;
  3. de onderdelen in een doos;
  4. de onderdelen met een even ID die goedkoper zijn dan 200 euro.

Vier keer bijna dezelfde lus in Main is redundante code. Maak van elke filter een methode die de lijst als parameter krijgt.

Deel 3: opruimen. Vraag de gebruiker wat er weg moet:

Wat moet er weg?
1. Alle onderdelen in een doos
2. Alle onderdelen goedkoper dan 100 euro
>2

Verwijder die onderdelen uit de lijst (denk aan Stevens opruimactie) en toon daarna hoeveel onderdelen er over zijn, en welke. Je getallen zijn bij elke run anders.

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

Tip

Wil je verder? Maak er een echte stocktool van, met een menu dat blijft terugkomen: een onderdeel toevoegen, een onderdeel verkopen via zijn ID, de totale waarde van de stock tonen, … Een “inventaris” in een lijst is een geliefkoosde oefening, en je komt ze nog vaak tegen.

  • Een klasse die toevalsgetallen nodig heeft, krijgt één private static Random. Alle twintig onderdelen delen die generator.
  • Elke filter is een foreach met een if. Een methode per filter, met de lijst als parameter, houdt Main leesbaar.
  • Verwijderen terwijl je de lijst overloopt: een for van achter naar voor met RemoveAt(i).

GreenRide: de hele vloot

GreenRide uit hoofdstuk 11 groeit. Tot nu toe had elke step zijn eigen variabele in Main. Met een lijst kan je de hele vloot in één keer aanpakken. Bouw verder op je klasse DeelStep.

  1. Schrijf in Program.cs een methode ToonVloot(List<DeelStep> vloot) die per step het ID en de batterij toont, en of de step onderweg is of klaarstaat.
  2. Voeg aan DeelStep een methode public static void GeefGratisStroom(List<DeelStep> vloot) toe. Elke step die niet onderweg is, krijgt 100% batterij.

Testcode. Zet deze code in je Main. Je code werkt als je exact deze uitvoer krijgt.

List<DeelStep> vloot = new List<DeelStep>()
{
    new DeelStep(),
    new DeelStep(8),
    new DeelStep(55),
    new DeelStep(3)
};

foreach (DeelStep step in vloot)
{
    step.StartRit();
}
Console.WriteLine();
ToonVloot(vloot);

DeelStep.GeefGratisStroom(vloot);
Console.WriteLine();
Console.WriteLine("Na de gratis stroom:");
ToonVloot(vloot);
Step 1 vertrekt met 100% batterij.
Step 2 kan niet vertrekken: batterij te laag (8%).
Step 3 vertrekt met 55% batterij.
Step 4 kan niet vertrekken: batterij te laag (3%).

Step 1: 100%, onderweg
Step 2: 8%, staat klaar
Step 3: 55%, onderweg
Step 4: 3%, staat klaar

Na de gratis stroom:
Step 1: 100%, onderweg
Step 2: 100%, staat klaar
Step 3: 55%, onderweg
Step 4: 100%, staat klaar

Waarom staat GeefGratisStroom in de klasse DeelStep en niet in Program.cs? Probeer het: wat zegt de compiler?

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

  • Een lijst van objecten geef je mee aan een methode zoals een gewone variabele. De methode werkt op dezelfde objecten als Main.
  • In een foreach mag je de objecten zelf aanpassen, hier hun batterij.
  • Een private set is bereikbaar overal in de klasse, ook in een static methode.

Pokédex

Bouw een Pokédex: een lijst met alle Pokémon die je gevangen hebt. Gebruik je klasse Pokemon uit Pokémon deel 2 van hoofdstuk 11, met ShowInfo en Pokemon.GeneratorPokemon(naam).

Maak een List<Pokemon> en een menu dat blijft terugkomen tot de gebruiker 5 kiest:

  1. Vang een Pokémon. Vraag een naam, maak met GeneratorPokemon een wilde Pokémon met die naam en voeg hem achteraan toe.
  2. Toon Pokédex. Toon per Pokémon een nummer (vanaf 1) en daaronder zijn ShowInfo.
  3. Laat een Pokémon vrij. Vraag het nummer en haal die Pokémon uit de lijst. Vraag opnieuw zolang het nummer niet bestaat. Is de Pokédex leeg, zeg dat dan.
  4. Verwijder alles. De Pokédex wordt leeg.
  5. Stoppen.
1. Vang een Pokémon
2. Toon Pokédex
3. Laat een Pokémon vrij
4. Verwijder alles
5. Stoppen
>1
Naam van de Pokémon?
>Pikachu
Pikachu staat in je Pokédex.
...
>3
Welk nummer laat je vrij (1 tot 2)?
>1
Pikachu is vrij.

Probeer op het einde nog dit: zet pokedex.Sort(); in je programma, net na het vangen, en vang twee Pokémon. Wat gebeurt er?

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

  • De gebruiker telt vanaf 1, de lijst vanaf 0: RemoveAt(nummer - 1). Lees de naam voor je de Pokémon verwijdert.
  • Clear() maakt de hele lijst leeg.
  • Sort() werkt op een lijst van getallen of strings, niet zomaar op een lijst van je eigen klasse. Zie Wat kan een List nog?.

Bookmark Manager

Bouw je eigen “console browser”. De tool vraagt je 5 favoriete sites, met een naam en een URL. Daarna kies je in een menu een site en toont de tool er een vereenvoudigde versie van op het scherm.

Gebruik deze klasse BookMark. Hoe ze een pagina ophaalt en de html-code eruit haalt, hoef je niet te begrijpen: kopieer ze gewoon, met de using-lijnen bovenaan het bestand.

using System.Net.Http;
using System.Text.RegularExpressions;

class BookMark
{
    public string Naam { get; set; }
    public string URL { get; set; }

    public void ToonSite()
    {
        HttpClient client = new HttpClient();
        string result = client.GetStringAsync(URL).Result;
        Console.WriteLine(GetPlainTextFromHtml(result));
    }

    //Bron: https://www.mercator.eu/mercator/std/info_aruba/reporting-hoe-gegevens-afdrukken-met-html-tags.html
    private string GetPlainTextFromHtml(string htmlString)
    {
        string htmlTagPattern = "<.*?>";
        var regexCss = new Regex("(\\<script(.+?)\\</script\\>)|(\\<style(.+?)\\</style\\>)", RegexOptions.Singleline | RegexOptions.IgnoreCase);
        htmlString = regexCss.Replace(htmlString, string.Empty);
        htmlString = Regex.Replace(htmlString, htmlTagPattern, string.Empty);
        htmlString = Regex.Replace(htmlString, @"^\s+$[\r\n]*", "", RegexOptions.Multiline);
        htmlString = htmlString.Replace("&nbsp;", " ");
        return htmlString;
    }
}

Zo werkt de klasse:

BookMark voorbeeld = new BookMark() { Naam = "Voorbeeld", URL = "https://example.com" };
voorbeeld.ToonSite();

Deel 1. Vraag de 5 sites en bewaar ze in een List<BookMark>. Schrijf daarna een menu dat blijft terugkomen tot de gebruiker 0 kiest:

  • 1. Toon lijst: alle sites met een nummer ervoor, vanaf 1.
  • 2. Open een site: toon de lijst, vraag het nummer en roep ToonSite op.

Typ ook eens een URL zonder https:// of een site die niet bestaat. Het programma crasht. Zorg dat het een nette melding toont en daarna gewoon verder gaat.

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

Deel 2. Breid het menu uit:

  • 3. Pas een bookmark aan: vraag het nummer, daarna een nieuwe naam en een nieuwe URL. Laat de gebruiker iets leeg, dan blijft dat zoals het was.
  • 4. Verwijder een bookmark.
  • 5. Voeg een bookmark in: vraag op welke plaats de nieuwe bookmark moet komen (van 1 tot één na de laatste) en vraag daarna de naam en de URL. De bookmarks erachter schuiven op. Een List heeft daar de methode Insert(index, element) voor.

Nu kan de lijst leeg worden. Kiest de gebruiker dan 2, 3 of 4, toon dan Er zijn geen bookmarks. in plaats van een nummer te vragen.

Schrijf voor elk menu-item een methode in Program.cs, en hergebruik wat je kan: het nummer vragen en een bookmark inlezen heb je meer dan eens nodig.

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

  • Een List past hier beter dan een array: er komen bookmarks bij en er gaan er weg. Insert en RemoveAt schuiven de rest voor je op.
  • Nummeren doe je met een for, want je hebt de teller nodig. De gebruiker telt vanaf 1, de lijst vanaf 0.
  • Code die kan mislukken door iets buiten je programma (een site die niet antwoordt), zet je in een try.

Speelkaarten

Een spelletje kaarten in de pauze, maar dan in de console.

Deel 1: het pak. Maak een enum Kleur met de waarden Schoppen, Harten, Klaveren en Ruiten, en een klasse Speelkaart met twee auto-properties:

  • Getal (int): van 1 tot en met 13;
  • Kleur (van het type Kleur).

Geef de klasse een methode ToonKaart(). Die toont de kleur en de waarde, waarbij 1 een aas is, 11 een boer, 12 een koningin en 13 een heer: Harten koningin, Schoppen 7, Ruiten aas.

Een property mag dezelfde naam hebben als haar type, zoals Nature bij de Pokémon natures van hoofdstuk 11.

Vul in Main met twee lussen een List<Speelkaart> stapel met de 52 kaarten van een pak. Laat de buitenste lus met een int van 0 tot en met 3 lopen, en maak er een kleur van met een cast: (Kleur)kleur. Trek daarna telkens een willekeurige kaart uit de stapel, toon ze en haal ze uit de lijst, tot de stapel leeg is. De gebruiker drukt telkens op Enter voor de volgende kaart. Omdat je een willekeurige kaart trekt, hoef je het pak niet te schudden.

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

Deel 2: de aflegstapel. Elke getrokken kaart komt nu open op een aflegstapel, de laatste bovenop. Dat is een Stack<Speelkaart>: wat je er het laatst op legt (Push), haal je er als eerste af (Pop). Met Peek() kijk je naar de bovenste kaart zonder ze weg te nemen.

Vervang de lus uit deel 1 door een menu dat blijft terugkomen tot de gebruiker s typt. Toon telkens hoeveel kaarten er nog op de stapel liggen, en welke kaart er bovenop de aflegstapel ligt:

  • t trekt een willekeurige kaart uit de stapel en legt ze op de aflegstapel. Is de stapel leeg, zeg dat dan.
  • n neemt de bovenste kaart van de aflegstapel terug en steekt ze weer in de stapel. Ligt er niets, zeg dat dan.
Nog 52 kaarten op de stapel.
De aflegstapel is leeg.
t = trekken, n = terugnemen, s = stoppen
>t
Je trekt: Harten 6

Nog 51 kaarten op de stapel.
Bovenop de aflegstapel: Harten 6
t = trekken, n = terugnemen, s = stoppen
>t
Je trekt: Harten boer

Nog 50 kaarten op de stapel.
Bovenop de aflegstapel: Harten boer
t = trekken, n = terugnemen, s = stoppen
>n
Terug op de stapel: Harten boer

Nog 51 kaarten op de stapel.
Bovenop de aflegstapel: Harten 6
t = trekken, n = terugnemen, s = stoppen
>s

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

  • Van een int maak je een enum-waarde met een cast: (Kleur)kleur. Zo volstaan twee lussen voor 52 kaarten.
  • Een willekeurig element trekken uit een lijst die krimpt: Next(0, stapel.Count), dan RemoveAt.
  • Een Stack is last in, first out: wat je laatst neerlegt, neem je eerst terug. Zie Stack collectie.

Fastfood restaurant (Essential) (GPT)

Tip

Deze oefening werd gemaakt (en aangepast nadien) met behulp van volgende GPT en heeft daarom de tag (GPT) achter de titel staan.

Je maakt een bestelsysteem voor een fastfoodrestaurant. Klanten plaatsen bestellingen, de keuken maakt ze in volgorde, en de zaak houdt bij welke gerechten het populairst zijn.

Potloodtekening: klanten staan in een rij aan de toog van een fastfoodzaak, de robot neemt de bestelling op en het stokmannetje bakt burgers.

De klasse Bestelling. Neem deze klasse over en voeg een methode ToonGerechten() toe die elk gerecht op een eigen lijn toont, met - ervoor.

internal class Bestelling
{
    public List<string> Gerechten { get; set; }

    public Bestelling(List<string> gerechten)
    {
        Gerechten = gerechten;
    }
}

Het hoofdprogramma. Je hebt drie collecties nodig. Maak ze in Main en geef ze als parameter mee aan de methoden die ze nodig hebben:

Queue<Bestelling> bestellingen = new Queue<Bestelling>();
Dictionary<string, int> populariteit = new Dictionary<string, int>();
List<Bestelling> geschiedenis = new List<Bestelling>();

Schrijf een menu dat blijft terugkomen tot de gebruiker 4 kiest, met deze opties en methoden:

  1. Bestelling plaatsen: static void PlaatsBestelling(Queue<Bestelling> bestellingen). De gebruiker typt de gerechten, één per lijn, tot hij stop typt (Stop of STOP mag ook). Zit er minstens één gerecht in, dan maak je er een Bestelling van en zet je ze achteraan in de wachtrij.
  2. Bestelling verwerken: static void VerwerkBestelling(Queue<Bestelling> bestellingen, List<Bestelling> geschiedenis, Dictionary<string, int> populariteit). De keuken haalt de eerste bestelling uit de wachtrij en toont de gerechten. Per gerecht gaat de teller in populariteit één omhoog. Daarna komt de bestelling in de geschiedenis.
  3. Geschiedenis tonen: static void ToonGeschiedenis(List<Bestelling> geschiedenis, Dictionary<string, int> populariteit). Toon elke verwerkte bestelling met haar gerechten, en daaronder hoe vaak elk gerecht besteld is.
  4. Stoppen.
Tip

Een gerecht dat voor het eerst besteld wordt, staat nog niet in de dictionary. populariteit[gerecht]++ geeft dan een KeyNotFoundException, en Add geeft een ArgumentException als de sleutel er al in zit. Een Dictionary kan je vragen of een sleutel al bestaat met ContainsKey:

if (populariteit.ContainsKey(gerecht))
{
    // het gerecht staat er al in: verhoog de teller
}
else
{
    // eerste keer: voeg het toe met waarde 1
}
1. Bestelling plaatsen
2. Bestelling verwerken
3. Geschiedenis tonen
4. Stoppen
>1
Geef de gerechten, een per lijn. Typ stop als je klaar bent.
>cheeseburger
>frietjes
>cola
>stop
Bestelling geplaatst. Bestellingen in de wachtrij: 1
...
>1
Geef de gerechten, een per lijn. Typ stop als je klaar bent.
>frietjes
>Stop
Bestelling geplaatst. Bestellingen in de wachtrij: 2
...
>2
De keuken maakt:
- cheeseburger
- frietjes
- cola
...
>2
De keuken maakt:
- frietjes
...
>3
Bestelling 1:
- cheeseburger
- frietjes
- cola
Bestelling 2:
- frietjes
Populaire gerechten:
cheeseburger: 1 keer besteld
frietjes: 2 keer besteld
cola: 1 keer besteld

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

  • Een Queue is first in, first out: de bestelling die het eerst binnenkwam, komt het eerst uit de keuken. Dequeue op een lege queue crasht, dus eerst Count controleren.
  • Tellen per sleutel: bestaat de sleutel al (ContainsKey), verhoog dan de waarde, anders voeg je ze toe met 1.
  • De collecties staan in Main en gaan als parameter mee. Maak je ze in een methode, dan zijn ze weg zodra die methode stopt.
  • Zie Queue collectie en Dictionary collectie.

De vestiaire van de TD (Essential)

Op de TD van je studentenclub sta jij aan de vestiaire. Wie een jas afgeeft, krijgt een bonnetje met een nummer. Met dat nummer haalt hij zijn jas later weer op. Een nummer met een jas: dat is een Dictionary<int, string>, met het bonnummer als sleutel en een omschrijving van de jas als waarde.

Deel 1. Schrijf een menu dat blijft terugkomen tot de gebruiker 0 kiest:

  1. Jas afgeven. Vraag een omschrijving van de jas en geef ze het volgende vrije nummer: het eerste bonnetje is 1, het tweede 2, enzovoort.
  2. Jas ophalen. Vraag het nummer op het bonnetje, toon de jas en haal ze uit de vestiaire. Hangt er niets op dat nummer, toon dan een nette melding in plaats van te crashen. Een sleutel opvragen die niet bestaat, werpt een KeyNotFoundException op.
  3. Overzicht. Toon elk nummer met zijn jas. Hangt er niets, zeg dat dan. Een Dictionary heeft net als een List een property Count.
1. Jas afgeven
2. Jas ophalen
3. Overzicht
0. Sluiten
>1
Omschrijving van de jas?
>zwarte jas met rode sjaal
Je bonnetje heeft nummer 1.
...
>3
1: zwarte jas met rode sjaal
2: groene regenjas
3: jeansjas
...
>2
Nummer op je bonnetje?
>2
Hier is je groene regenjas.
...
>2
Nummer op je bonnetje?
>2
Op nummer 2 hangt hier niets.

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

Deel 2. Haal in Main de lijn volgendNummer++; weg en geef twee jassen af. Wat gebeurt er, en waarom?

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

  • Een Dictionary zoekt op een sleutel, niet op een positie. Na het ophalen van jas 2 blijven 1 en 3 gewoon 1 en 3.
  • [sleutel] met een onbekende sleutel geeft een KeyNotFoundException, Add met een bestaande sleutel een ArgumentException.
  • Overlopen met foreach: elk element heeft een .Key en een .Value. Zie Gebruik Dictionary.

Project: CodeChella (Final Essentials)

Je bent de organisator van CodeChella, het festival waar programmeurs en muziekliefhebbers samenkomen voor beats en bytes. Achter de schermen is het chaos: de line-up moet beheerd worden, de rijen aan de ingang puilen uit en niemand weet hoeveel bezoekers van elk tickettype er binnen zijn. Jij schrijft de FestivalManager die er orde in brengt. Je gebruikt de drie grote collecties: List, Queue en Dictionary.

De klassen.

  • Artiest met de auto-properties Naam (string), Genre (string, bv. “Rock”, “Techno”, “Pop”) en Gage (double): wat de artiest per uur kost.
  • Bezoeker met de auto-properties Naam (string), Ticket (van het type TicketType) en HeeftRugzak (bool).
  • Een enum TicketType met de waarden Dagticket, Combi en VIP.

De collecties in Main.

  • List<Artiest> lineUp: alle artiesten.
  • Queue<Bezoeker> ingangRij: de gewone rij aan de ingang.
  • Queue<Bezoeker> vipRij: VIP’s staan niet graag in de gewone rij, zij krijgen een eigen rij.
  • Dictionary<TicketType, int> ticketVerkoop: hoeveel bezoekers van elk tickettype er binnen zijn. Zet bij de start de drie tickettypes erin met waarde 0. Dan bestaat elke sleutel al en kan je gewoon ticketVerkoop[type]++ doen.

Het menu, tot de gebruiker 0 kiest:

  1. Artiest toevoegen: vraag naam, genre en gage, en voeg de artiest toe aan de line-up.
  2. Line-up filteren: vraag een genre en toon enkel de artiesten van dat genre. rock en Rock zijn hetzelfde genre.
  3. Totaalbudget: de som van alle gages. Schrijf die lus zelf.
  4. Rij simuleren: maak 5 bezoekers met een willekeurige naam uit de array hieronder, een willekeurig tickettype en een willekeurige rugzak (50% kans). Een VIP gaat in de VIP-rij, de anderen in de gewone rij.
  5. Security check: laat eerst de hele VIP-rij binnen en pas daarna de gewone rij. Haal de bezoekers er één voor één uit:
    • Heeft de bezoeker een rugzak, toon dan STOP! Security check voor [Naam]..., wacht 1 seconde met Thread.Sleep(1000); en toon [Naam] mag binnen.
    • Zonder rugzak toon je [Naam] mag doorlopen.
    • Na de check mag iedereen binnen: tel bij elke bezoeker zijn tickettype op in ticketVerkoop.
  6. Overzicht tickets: toon per tickettype hoeveel bezoekers er binnen zijn.
string[] namen = { "Lotte", "Mo", "Yasmine", "Arne", "Fien", "Bram", "Noor", "Wout" };

Een voorbeeld. Bij jou komen er andere bezoekers in de rij:

>2
Welk genre?
>ROCK
The Bugfixers (Rock), 450,00 euro per uur
Stack Overflow (rock), 300,00 euro per uur
...
>3
Totaalbudget: 1550,00 euro per uur
...
>4
Arne (VIP) gaat in de VIP-rij staan.
Yasmine (Combi) gaat in de gewone rij staan.
Wout (VIP) gaat in de VIP-rij staan.
Fien (Dagticket) gaat in de gewone rij staan.
Noor (Dagticket) gaat in de gewone rij staan.
...
>5
STOP! Security check voor Arne...
Arne mag binnen.
Wout mag doorlopen.
STOP! Security check voor Yasmine...
Yasmine mag binnen.
Fien mag doorlopen.
Noor mag doorlopen.
...
>6
Dagticket: 2
Combi: 1
VIP: 2

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel gebruikt, dan verschijnt de oplossing hier vanzelf.

  • Kies per taak de collectie: een List voor iets wat je overloopt en filtert, een Queue voor een rij die in volgorde afgewerkt wordt, een Dictionary om per sleutel iets bij te houden.
  • Een rij leegmaken doe je met een while op Count en Dequeue, niet met een foreach: de rij verandert terwijl je ze overloopt.
  • Ken je alle sleutels op voorhand (hier de drie tickettypes), zet ze er dan bij de start in met 0. Daarna is tellen gewoon ++.
  • Een som over een lijst schrijf je zelf met een lus: .Sum() is LINQ en kost punten.
Tip

Wil je verder? Bij de gecombineerde opgaven staat een tekstgebaseerd spel met kamers, items en een speler. Het gebruikt hier en daar het keyword this, dat je pas in hoofdstuk 15 ziet.