Opdrachten
Algemene informatie
Hier vind je de opdrachten voor de permanente evaluatie van SES+EES. De opdrachten voor deel 1 worden gemaakt door alle studenten (SES+EES). De opdrachten voor deel 2 worden enkel gemaakt door de studenten SES.
GitHub repository linken
Om de permanente evaluatie opdrachten in te dienen voor het vak Software Engineering Skills maken we gebruik van GitHub. In de lessen zal je onder begeleiding een gratis account aanmaken op dit platform. Je maakt de opdrachten in een repository die je aanmaakt via GitHub Classroom. Daarvoor moet je je GitHub gebruikersnaam linken aan je naam, zodat wij weten bij welke student de repository van ‘FluffyBunny’ hoort :). Zie de instructies bij de eerste opdracht voor meer details.
Extra start files van andere start repositories downloaden in je eigen repo
Om jullie het leven makkelijk te maken, hebben we voor veel van de opdrachten al startcode geschreven in de vorm van een github repository. Die nieuwe repositories simpelweg clonen in een subdirectory van je eigen repository zorgt echter voor een aantal problemen. Die nieuwe directories met startcode worden dan namelijk als een submodule toegevoegd aan je main repo. Die repo wordt dus als een soort link beschouwd en aangezien die nieuwe repo niet van jullie zelf is ga je dan ook geen veranderingen aan die code kunnen pushen.
In de plaats moeten we die start-code-repositories als een subtree toevoegen. Dat heeft als voordeel dat je zelf gewoon wijzigingen kan aanbrengen, committen en pushen naar je eigen hoofd repository. Bovendien blijft er ook een zachte link met de originele start-code-repository zodat als hier iets aan wijzigt je die online wijzigingen nog wel kan fetchen. (Bijvoorbeeld als we merken dat er nog een foutje in de startcode stond!).
Zo een subtree aanmaken doe je dan op de volgende manier:
- Voeg de remote-start-code-repository toe aan je eigen repo met volgende commando:
git subtree add --prefix=<subdirectory_waarin_je_de_files_wil_clonen> <remote-start-code-repository-link> <branch_name> --squash
- met
--prefix=
geef je aan in welke subdirectory de inhoud van de externe repo moet komen. - je kan een specifieke branch meegeven (meestal
main
) - met
--squash
condenseer je de git history van de externe repo tot één enkele commit. (Je kan deze optie weglaten als je toch de hele git history wil bekijken)
- Zodra de files in jouw repo staan, kan je ze bewerken zoals normaal. De changes worden dan onderdeel van de history van JOUW repository, onafhankelijk van de oorspronkelijke externe repository.
- Moesten er later toch wijzigingen aangebracht worden in de remote-start-code-repository die je wil fetchen dan kan je volgend commando gebruiken:
git subtree pull --prefix=<subdirectory_waarin_je_de_files_wil_pullen> <remote-start-code-repository-link> <branch_name> --squash
Warning
Heb je toch al zo een repo gecloned en is dit nu een een submodule waarvan je de changes niet kan committen dan kan je best je wijzigingen even kopieren naar een andere locatie buiten je repo. De subdirectory verwijderen en nu als subtree toevoegen en dan je oplossingen terug erin zetten.
Naamgeving bij indienen (tags)
Om de verschillende (sub)opdrachten te identificeren wordt er gebruik gemaakt van “tags” bij het committen van je finale resultaat. (In de eerste lessen worden deze onderwerpen klassikaal uitgelegd zodat alle studenten de juiste werkwijze gebruiken).
De naamgeving: voor het committen van je resultaat van “Opdracht 1” gebruik je de tag v1
, voor “Opdracht 2” gebruik je de tag v2
, enzoverder.
Tags pushen naar github: git push --tags
Tags op github verwijderen: git push --delete origin <tagname>
. Dit moet je doen als je bijvoorbeeld lokaal een tag verplaatst hebt.
Lokaal een tag deleten: git tag --delete <tagname>
Deadlines
Er is 1 deadline voor alle opdrachten van het eerste deel (SES+EES): vrijdag 21/03/2025 23u59.
De deadline voor alle opdrachten van het tweede deel (enkel SES) is vrijdag 23/05/2025 23u59.
Opdrachten deel 1
Deze opdrachten worden door alle studenten (SES+EES) gemaakt en ingediend via Github Classroom. Klik hier voor de invite van de assignment “Opdrachten deel 1”.
Versiebeheer
Opdracht 1:
- Maak een nieuwe directory aan op je computer voor deze opdracht.
- Initialiseer die directory als een git directory.
- Download de file
Candy_Crush_spelregels.txt
van Toledo en plaats de file in je git directory. - Commit nu de veranderingen in je directory en tag als
v1
.
Opdracht 2:
- Los alle TODO’s in de file
Candy_Crush_spelregels.txt
op en commit de veranderingen in je directory en tag alsv2
.
Opdracht 3:
- Maak een branch aan met als naam “opdracht_branch”.
- Switch naar de nieuwe branch.
- In de
Candy_Crush_spelregels.txt
vul de gegevens voor auteur aan met je eigen voornaam en achternaam. Commit nu je aanpassingen in deze branch. - Switch terug naar de main branch en vul daar andere waarden in voor de auteur gegevens (Dit is bijvoorbeeld een bug in je software). Commit nu je aanpassingen in deze branch.
- Merge de “opdracht_brach” met je main branch. Hiervoor zal je dus ook het mergeconflict moeten oplossen.
- Commit nu de veranderingen in je directory en tag als
v3
.
Build systems
Opdracht 4:
Maak een folder in de root directory van deze git repository aan genaamd ‘build-systems’. Maak hierin 3 subdirectories: ‘c’, ‘java’ en ‘python’.
Extract alle files in dit zip bestand naar de
./build-systems/c
directory en los alle TODO’s in de documenten op. (Je kan met de TODO tree extensie in VSCode gemakkelijk zien of je alle TODO’s gedaan hebt) OF clone de repository van het startproject into./build-systems/c
.- Je moet de makefile aanpassen zodat het C-programma kan gecompiled+gelinked worden met
make compile
, dat de binaries en object files gedeletet worden metmake clean
en dat je project gerund kan worden metmake run
(je moet hier ook flags kunnen meegeven). De uiteindelijk binary moet in de root van je c-project directory staan met als naamfriendshiptester.bin
- Je moet de makefile aanpassen zodat het C-programma kan gecompiled+gelinked worden met
In de
./build-systems/java
-directory: Extract alle files in dit zip bestand OF clone de repository. Schrijf een simpele makefile dat de volgende dingen kan doen en plaats het in de root van je directory:
compile
: Compileert de bronbestanden naar de/build
-directoryjar
: packaged alle klassen naar een jar genaamd ‘app.jar’ in de ‘build’-directory met entrypoint de ‘App’-klasse.run
: Voert de jar file uitclean
: Verwijdert de ‘.class’-bestanden en het ‘.jar’-bestand uit de ‘build’-directory
- in de
./build-systems/python
-directory: Extract alle files in dit zip bestand OF clone de repository. Schrijf een simpele makefile dat de volgende dingen kan doen en plaats het in de root van je directory:
compile
: Compileert de bronbestanden naar de single ‘friendshiptester.bin’ file in de “/dist”-directoryclean
: Verwijdert het ‘.bin’-bestandrun
: Voert de ‘friendshiptester.bin’ uittest
: Voert de ‘app.py’ uit
- Commit nu de veranderingen en tag als
v4
.
Dependency management
Opdracht 5:
- Maak een folder in de root directory van je git repository aan genaamd ‘dependency-management’. Maak een javaproject met gradle aan in een subdirectory genaamd “checkneighbours” met package “be.ses”.
- Je kan de package name meegeven met het ‘gradle init’ commando op de volgende manier:
gradle init --package be.ses
- Je kan de package name meegeven met het ‘gradle init’ commando op de volgende manier:
- Voeg het volgende toe aan de
.gitignore
-file in de root van je repository.
./dependency-management/checkneighbours/.gradle/
./dependency-management/checkneighbours/build/
- In je
checkneigbours
gradle project, moet je nu een klasse ‘CheckNeighboursInGrid’ maken en onderstaande static method in implementeren, los ook de TODO op: Voorbeeld: voor het volgende grid:
[ 0, 0, 1, 0,
1, 1, 0, 2,
2, 0, 1, 3,
0, 1, 1, 1 ]
-> getSameNeighboursIds(grid, 4, 4, 5)
returns [2,4,10]
Genereer een
checkneigbours.jar
file van deze Javaklasse in debuild/libs
directory van je gradle project. Kopiëer de jar-file naar de folder “./dependency-management/” (dus./dependency-management/checkneigbours.jar
).Commit nu de veranderingen en tag als
v5
.
Opdracht 6:
Maak een folder in de “./dependency-management/” directory van deze git repository genaamd ‘checkneighbours_example’.
Extract het volgende gradle project in dit zip bestand naar die
./dependency-management/checkneighbours_example
directory en los alle TODO’s in de documenten op. (Je kan met de TODO tree extensie in VSCode gemakkelijk zien of je alle TODO’s gedaan hebt) OF clone via subtree de repository van het startproject into./dependency-management/checkneighbours_example
.- kopieer je
checkneigbours.jar
naar deapp/lib
directory van het gradle project - Pas de
build.gradle
aan zodat demain
-method in deApp.java
correct gebuild en gerund kan worden.
- kopieer je
Voeg ook het volgende toe aan de
.gitignore
-file in de root van je repository.
./dependency-management/checkneighbours_example/.gradle/
./dependency-management/checkneighbours_example/build/
- Commit nu de veranderingen en tag als
v6
.
Warning
Krijg je een type error in de main
method van App.java
in het ‘checkneighbours_example’ project. Verwissel de code ``
Test Driven Development
Opdracht 7:
- Voeg minstens 6 unittesten toe aan je gradle project
checkneighbours
waarbij de unittesten je oplossing voor degetSameNeighboursIds
-methode testen van deCheckNeighboursInGrid
-klasse. De testen moeten aan volgende vereisten voldoen:
- Gebruik de correcte naamgeving voor de testen
- Gebruik het correcte Arrange, Act, Assert principe
- Maak minstens 1 test die een
Exception
test - Probeer de randgevallen te testen en elke test moet een ander scenario testen. (bv. 1 test waarbij je een element aan de linker rand test mag maar 1 keer voorkomen. Eentje in een hoek testen kan dan wel al een ander scenario zijn.)
- Commit nu de veranderingen en tag als
v7
en push.
Opdracht 8: getSameNeighboursIds functie in python testen
Maak een folder in de root van je repository aan genaamd “./tdd/”.
Extract het volgende python project in dit zip bestand naar die
./tdd
directory OF clone via subtree de repository het startproject into./tdd
.- Het project bevat een
checkneighbours.py
-bestand met een implementatie van de functieget_same_neighbours_ids()
- Het project bevat ook een file
checkneighbours_test.py
met het geraamte van het unittest framework al ingevuld.
- Het project bevat een
Commit nu de veranderingen en tag als
v8
en push.
Continuous Integration and Continuous Deployment
Opdracht 9:
Gebruik Github Actions om een CI-pipeline aan te maken die steeds je testen van je ‘checkneighbours’ uit opdracht 7 uitvoert wanneer je naar de
main
branch pusht. Voorzie ook een badge in een README.md in de root folder van je git directory zodat je in één opslag kan zien wanneer de tests falen.Let op! Je wil nu dus de testen runnen van een specifiek gradle project dat in een subdirectory staat. Meer info hier
Commit nu de veranderingen en tag als
v9
en push.
Opdrachten deel 2
Deze opdrachten worden enkel door de studenten van SES gemaakt en ingediend via Github Classroom.
Gebruik van GenAI en samenwerking
GenAI (ChatGPT, Copilot, Claude, …) maakt een razendsnelle opgang in het leven van iedereen, en dus ook van informatici. Deze tools zijn dan ook zeer onderlegd in het schrijven van (beperkte hoeveelheden) code.
Omdat dit deel van het vak gericht is op het zelf leren programmeren, en de opdrachten gequoteerd worden, is het niet toegestaan om dergelijke tools in te schakelen om de opdrachten op te lossen. Met andere woorden, we verwachten dus dat je alle ingediende code zelf geschreven hebt. Ook code delen met mede-studenten, of buitenstaanders om hulp vragen, is om dezelfde reden niet toegestaan.
Op het examen zal een examenvraag toegevoegd worden die nagaat in welke mate je deze opdracht effectief onder de knie hebt. De score op die vraag zal ook invloed hebben op de punten van je werk doorheen het semester.
Tenslotte is het absoluut geen probleem om GenAI tools te gebruiken bij het studeren en verwerken van de leerstof. Begrijp je een concept niet goed, en wil je meer uitleg of voorbeelden? Wil je hulp bij het oplossen van een oefening? Krijg je een compiler error niet opgelost? Gebruik deze tools dan gerust (hou er wel rekening mee dat er ook fouten in hun antwoord kunnen zitten)! Maar gebruik ze dus niet voor de opdracht.
Setup
Volg onderstaande stappen nauwgezet om je project juist te configureren.
Maak hier (via GitHub Classroom) je repository aan voor de assignment “Opdrachten deel 2”. Deze repository is nog leeg.
Clone jouw (lege) repository naar een folder op je eigen machine.
Voeg vervolgens een tweede remote aan die repository op je machine toe, namelijk
git@github.com:KULeuven-Diepenbeek/ses-startcode-deel2-2425.git
onder de naamstartcode
. Dat kan je met volgend commando:git remote add startcode git@github.com:KULeuven-Diepenbeek/ses-startcode-deel2-2425.git
Je lokale repository heeft nu dus twee remote repositories (kijk dit na met
git remote -v
):- origin: je eigen GitHub repository
- startcode: de GitHub repository met de startcode die door ons aangeleverd wordt
Haal de laatste versie van de startcode op en merge die in je repository via
git pull startcode main
. Doe dit minstens voor elke nieuwe opdracht, en eventueel ook tussendoor (als er wijzigingen/bugfixes aan onze startcode gebeurd zijn).Open de folder
CandyCrush
uit de repository als project in IntelliJ. Opgelet! zorg dat je deCandyCrush
folder als project opent in IntelliJ, en niet de bovenliggende folder van je repository (ses-opdrachten-deel2-...
)!
Als alles goed gegaan is, wordt je project herkend en geïmporteerd als een Gradle-Java-project. Het is normaal dat de testen nog fouten geven bij het compileren, aangezien die code verwachten die je nog moet schrijven als deel van de opdracht.
Je kan normaalgezien wel al de main
-methode in CandyCrushMain
uitvoeren.
Startcode
De startcode bevat een JavaFX-applicatie voor het spel CandyCrush. Het is een Gradle-project voor IntelliJ, en maakt gebruik van Java 21. Je kan de folder openen als project in IntelliJ. De applicatie is gestructureerd volgens het Model-View-Controller (MVC) patroon.
Er zijn ook reeds enkele testen voorgedefinieerd met AssertJ, maar de set van testen is niet volledig. De voorgedefinieerde testen dienen voornamelijk om na te gaan of je oplossing automatisch getest kan worden.
Belangrijk!
Omdat je inzendingen (deels) automatisch verbeterd zullen worden, is het noodzakelijk dat alle gegeven testen compileren zonder enige aanpassingen. Je mag uiteraard wel extra testen toevoegen. Ook is het geen groot probleem indien een bepaalde test niet slaagt — zolang hij maar uitgevoerd kan worden.
Opdracht 1: Records
Startcode
Merge eerst de laatste versie van de startcode in je repository door git pull startcode main
uit te voeren in jouw lokale repository.
Maak, in package
ses.candycrush.board
een record genaamdBoardSize
dat de grootte van een candycrush speelveld voorstelt als een aantal rijen (rows
) en aantal kolommen (columns
).- Het aantal rijen en kolommen moeten beiden groter zijn dan 0, zoniet gooi je een
IllegalArgumentException
.
- Het aantal rijen en kolommen moeten beiden groter zijn dan 0, zoniet gooi je een
Maak, in hetzelfde package, ook een tweede record genaamd
Position
dat een geldige positie van een cel op een candycrush-speelveld voorstelt (row
encolumn
).- Rijen en kolommen worden genummerd vanaf 0.
- Aan de constructor van een Position-object moeten een rij- en kolomnummer alsook een
BoardSize
meegegeven worden. - Indien de positie ongeldig is voor de grootte van het speelveld, moet je een
IllegalArgumentException
gooien.
Voeg in
Position
volgende methodes toe, samen met zinvolle tests voor elke methode:een methode
int toIndex()
die de positie omzet in een index. Voor veld met 2 rijen en 4 kolommen lopen de indices als volgt:0 1 2 3 4 5 6 7
een statische methode
Position fromIndex(int index, BoardSize size)
die de positie teruggeeft die overeenkomt met de gegeven index. Deze methode moet eenIllegalArgumentException
gooien indien de index ongeldig is.methodes
boolean isFirstRow()
,boolean isFirstColumm()
,boolean isLastRow()
, enboolean isLastColumn()
die aangeven of de positie zich in de eerste/laatste rij/kolom van het bord bevindt.een methode
Collection<Position> neighbors()
die alle posities van (geldige) directe buren (horizontaal en vertikaal) in het speelveld teruggeeft.een methode
boolean isNeighborOf(Position other)
die nagaat of de gegeven positie een directe buur is van de huidige positie. Gooit eenIllegalArgumentException
als de gegeven positie bij een andere bordgrootte hoort.
Voeg in
BoardSize
de volgende methodes toe, samen met zinvolle tests:- een methode
Collection<Position> positions()
die een collectie (bv. een ArrayList) met daarin alle posities op het bord teruggeeft.
- een methode
Voeg, in package
ses.candycrush.model
, een sealed interfaceCandy
toe, met subklassen (telkens een record, die je in de Candy-interface plaatst) voorNoCandy
, wat staat voor het ontbreken van een snoepje.NormalCandy
, met een attribuutcolor
(een int met mogelijke waarden 0, 1, 2, of 3); je gooit eenIllegalArgumentException
indien een ongeldige kleur opgegeven wordt.- Elk van de volgende speciale soorten snoepjes:
- een
RowSnapper
- een
MultiCandy
- een
RareCandy
- een
TurnMaster
- een
Voeg, in het package
ses.candycrush.model
, een recordSwitch
toe. Een Switch-object stelt een mogelijke wissel voor tussen twee positiesfirst
ensecond
.- Beide posities moeten buren zijn van elkaar; je constructor moet een
IllegalArgumentException
gooien indien dat niet het geval is. - Zorg ervoor dat het niet uitmaakt in welke volgorde de twee posities meegegeven worden aan de constructor; maar het veld
first
moet uiteindelijk de positie bevatten met de kleinste index (zoals gedefinieerd bijtoIndex()
).
- Beide posities moeten buren zijn van elkaar; je constructor moet een
Voeg aan dat Switch-record een operatie
other(Position pos)
toe die de andere positie teruggeeft dan de gegeven positie (dus als je first meegeeft, krijg je second terug, en omgekeerd).- Indien de gegeven positie geen deel uitmaakt van het Switch-object, gooi je een
IllegalArgumentException
.
- Indien de gegeven positie geen deel uitmaakt van het Switch-object, gooi je een
Pas nu je code (
CandyCrushGame
,CandyCrushBoardUI
, enController
) aan zodat die op zoveel mogelijk plaatsen gebruik maakt van bovenstaande records in plaats van int’s (Switch moet je nog niet gebruiken). Dus:- op elke plaats waar voorheen een int voor width en/of height gebruikt of teruggegeven werd, moet nu
BoardSize
gebruikt worden - op elke plaats waar voorheen een rij- en/of kolomnummer gebruikt of teruggegeven werd, moet nu een
Position
object gebruikt worden - op elke plaats waar voorheen een int gebruikt of teruggegeven werd om een snoepje aan te duiden, moet nu een
Candy
object gebruikt worden. - In de klasse CandyCrushBoardUI moet je pattern matching gebruiken om een JavaFX Node aan te maken voor de gegeven candy op de gegeven positie.
Laat de compiler je helpen met het vinden van de nog aan te passen code, door bv. eerst de type van een veld te veranderen.
- op elke plaats waar voorheen een int voor width en/of height gebruikt of teruggegeven werd, moet nu
Maak in de model-klasse
CandyCrushGame
een publieke methodeCollection<Switch> getPotentialSwitchesOf(Position pos)
die alle mogelijke wissels teruggeeft (bv. in een ArrayList) van positiepos
. Positiepos
kan wisselen met een andere positie indien (1) ze buren zijn; (2) geen van beiden een NoCandy zijn; én (3) de snoepjes op beide posities verschillend zijn (qua soort of kleur). (Deze methode zullen we in een latere opdracht verfijnen, maar voorlopig volstaat dit).In de
update()
-methode vanCandyCrushBoardUI
kan je nu code uit commentaar halen, gerelateerd aan het tonen van hints (zie de TODO daarin).
Als je dit alles correct gedaan hebt, zou alle code moeten compileren, zou de applicatie moeten uitvoeren (./gradlew run
), en zouden de testen moeten slagen.
Tag het resultaat als v1
en push dit naar jouw remote repository (origin) op GitHub: git push origin
.
Opdracht 2: Generics
Startcode
Merge eerst de laatste versie van de startcode in je repository door git pull startcode 02-generics
uit te voeren in de main
-branch van jouw lokale repository.
Een rechthoekig spelbord met cellen (vakjes) kan ook voor andere spellen dan Candycrush gebruikt worden; denk bijvoorbeeld aan schaken, dammen, zeeslag, go, … . In deze opdracht ga je daarom een algemene klasse ontwikkelen voor een rechthoekig spelbord.
Maak, in package
ses.candycrush.board
, een generischeBoard
-klasse, met een generische parameter die het type van elke cel weergeeft. Deze klasse moet maximaal gebruik maken van deBoardSize
enPosition
records uit de vorige opdracht. De inhoud van de cellen kan je bijhouden als een array of ArrayList.De constructor van
Board
vereist enkel eenBoardSize
. Alle cellen zijn initieelnull
.Voeg volgende publieke methodes toe en implementeer ze:
BoardSize getSize()
die de grootte van het bord teruggeeft (als BoardSize-object)boolean isValidPosition(position)
die nagaat of de gegeven positie geldig is voor dit bord (dus of ze in het bord ligt).getCellAt(position)
om de cel op een gegeven positie van het bord op te vragen. Als de positie ongeldig is, gooi je eenIllegalArgumentException
.void replaceCellAt(position, newCell)
om de cel op een gegeven positie te vervangen door een meegegeven object. Als de positie ongeldig is, gooi je eenIllegalArgumentException
.void fill(cellCreatorFunction)
om het hele bord te vullen met objecten die teruggegeven worden door decellCreatorFunction
. DecellCreatorFunction
is eenjava.util.function.Function
-object dat, gegeven een Position-object als argument, het cel-object teruggeeft wat op die positie geplaatst moet worden.- een methode
copyTo(otherBoard)
die alle cellen van het huidige bord kopieert naar het meegegeven bord. Als het meegegeven bord niet dezelfde afmetingen heeft, gooi je eenIllegalArgumentException
.
Zorg dat deze laatste twee methodes zo algemeen mogelijk zijn qua type, en schrijf telkens een test waarin je hier gebruik van maakt.
Gebruik de Board-klasse nu zoveel mogelijk in
CandyCrushGame
, waarbij de cellenCandy
-objecten zijn.
Tag het resultaat als v2
en push dit naar je remote repository op GitHub.
Opdracht 3: Collections
Startcode
Merge eerst de laatste versie van de startcode in je repository door git pull startcode 03-collections
uit te voeren in de main
-branch van jouw lokale repository.
- Hou in je klasse
Board
de elementen (cellen) bij via eenMap
, metPosition
als de sleutel. - Hou ook een omgekeerde
Map
bij, dus van een element (cel) naar alle posities (in eenSet
) waarop dat element voorkomt.- Dus: (in de context van CandyCrush) kan je uit deze
Map
eenSet
halen met alle posities waarop een bepaalde Candy voorkomt. - Deze structuur moet altijd overeenkomen met de andere map (van positie naar cel). Zorg er dus voor dat andere klassen die de klasse Board gebruiken beide maps enkel via gepaste methodes kunnen aanpassen.
- Dus: (in de context van CandyCrush) kan je uit deze
- Voorzie een methode
getPositionsOfElement
die alle posities teruggeeft waarop het gegeven element (cel) voorkomt, gebruik makend van deMap
van hierboven. De teruggegeven collectie mag niet aanpasbaar zijn (dus: de ontvanger mag ze niet kunnen aanpassen). - Als je klasse Board goed geëncapsuleerd was, hoef je geen andere code (buiten de klasse Board) aan te passen na bovenstaande wijzigingen.
Tag het resultaat als v3
en push dit naar je remote repository op Github.
Opdracht 4: Concurrency
Startcode
Merge eerst de laatste versie van de startcode in je repository door git pull startcode 04-concurrency
uit te voeren in de main
-branch van jouw lokale repository.
In deze opdracht gaan we uit van een situatie dat er meerdere spelers (threads) tegelijk met één Board-object werken.
- Maak de
fill
-methode in deBoard
-klasse thread-safe. Wanneer meerdere threads fill oproepen, moet het resultaat overeenkomen met dan van één van de threads (met andere woorden, het uiteindelijke bord mag niet deels opgevuld zijn door één thread, en deels door een andere). - Schrijf een test (met jcstress) die het correcte gedrag van
fill
nagaat.In de startcode is jcstress al toegevoegd als dependency, en staat er een klasse
ses.candycrush.board.Assignment04_Concurrency_Tests
klaar in de mapsrc/jcstress/java
die je kan aanpassen. Vergeet niet eerst je gradle configuratie te herladen in IntelliJ. - Schrijf in package
ses.candycrush.experiment
een klasseMultithreadedBoardClient
met eenmain
-methode. In die methode maak je eenBoard<Integer>
aan (met grootte 10x10 en 0 als initiële waarde voor elke cel). Gebruik vervolgens een Executor om 10 threads te maken die elk de waarde van elke cel verhogen met 1. Als dat correct gebeurt, zodat alle cellen van het bord uiteindelijk waarde 10 moeten hebben (ga dat na). (Dit client-programma moet geen GUI starten en/of JavaFX gebruiken.)
Tag het resultaat als v4
en push dit naar je remote repository op Github.