dsoftark E2007 Gruppe 14: Anders, Troels & Søren 15. november 2007 Rapport til a. 1

Relaterede dokumenter
dsoftark E2007 Gruppe 14: Anders, Troels & Søren 15. november 2007 Rapport til a. 1 'TDD rytmen'

Spilstrategier. 1 Vindermængde og tabermængde

Projekt - Visual Basic for Applications N på stribe

Undo Jo flere jo bedre! 1/9

Spilstrategier. Indhold. Georg Mohr-Konkurrencen. 1 Vindermængde og tabermængde 2. 2 Kopier modpartens træk 4

Skriftlig eksamen i Datalogi

Skriftlig eksamen i Datalogi

Spilstrategier, Kirsten Rosenkilde, september Spilstrategier

Algoritmeskabeloner: Sweep- og søgealgoritmer C#-version

Hukommelsesspil. Introduktion. Scratch

b) Udvid din implementation af forme til at understøtte.equals. To objekter af samme form er ens hvis de har samme værdier i felterne.

Mircobit Kursus Lektion 3 (Du skal her vælge Lets Code Og nederst Microsoft Block Editor.)

Begreber om Godt Software

Matematikken i kunstig intelligens Opgaver om koordinerende robotter

Matematikken i kunstig intelligens Opgaver om koordinerende robotter LØSNINGER

Indhold: Spillebræt 5 hære med 40 infanteri-, 12 kavaleri- og 8 artillerienheder i hver 43 kort 2 referencekort 5 terninger

Hvad er Objekter - Programmering

R15 PaSOOS (22/ )

Undersøgende aktivitet om primtal. Af Petur Birgir Petersen

Sikre Beregninger. Kryptologi ved Datalogisk Institut, Aarhus Universitet

Fang Prikkerne. Introduktion. Scratch

Lærervejledning. Beskriv ideen med spillet i plenum, herunder dets funktion og de tre vigtigste pointer med spillet:

class Time { int hours, min; } } Time t1; // Erklær variabel af type Time class Time1 { public static void main(string[] args) { Time t1; t1.

Forelæsning Uge 2 Mandag

DANMARKS TEKNISKE UNIVERSITET

Hvorfor skal vi bruge objekt orienteret databaser?

Systematisk testning af program til udregning af mellemskat

Tip til 1. runde af Georg Mohr-Konkurrencen Kombinatorik

Målet for disse slides er at diskutere nogle metoder til at gemme og hente data effektivt.

Partners er et spil med mange klare regler og en masse uskrevne regler, som varierer alt efter, hvem man spiller sammen med.

Tree klassen fra sidste forelæsning

Forelæsning Uge 1 Torsdag

Abstrakte datatyper C#-version

16/04/12 50% 50% Waveform Chart Waveform Graph XY Graph Indicator Graph 33% 17% 88% 13%

Greenfoot En kort introduktion til Programmering og Objekt-Orientering

Spillets formål og opsætning

Skriftlig eksamen i Datalogi

Som sagt kræves der helst lidt viden om OOP hvis man virkelig vil lærer noget, og ikke bare lave copypaste

Løsning af simple Ligninger

Ide med Diff. Mål. Tidsplan. 1.uge: 2.uge:

Kursus i OOP og Java. Kursus i Objektorienteret programmering i Java

Elasund Rules Forberedelse Marker byggeområdet

Michael Jokil

Programming Project Report. Programmeringsprojekt i PaSOOS fagpakken Bobby Nielsen; Jon Rune Jørgensen

Forelæsning Uge 4 Mandag

Lad os som eksempel se på samtidigt kast med en terning og en mønt:

Computerspil Dokumentation

Mircobit Kursus Lektion 4 (Du skal her vælge Lets Code Og herefter Block Editor.)

DM507 Algoritmer og datastrukturer

π er irrationel Frank Nasser 10. december 2011

Digital Choice 12 + MERE, MERE, MERE!

Side 1 af 8. Vejledning

Skriftlig eksamen i Datalogi

Udfordringer og problemstillinger. En liste over de udfordringer og problemstillinger, der er ved Java og JEE udvikling

Forelæsning Uge 2 Torsdag

Programmering 1999 KVL Side 5-4. Klassen Time: metoder. Metoder i objektet giver mulighed for at ændre tilstanden, eller kigge på tilstanden.

Gennemsnit og normalfordeling illustreret med terningkast, simulering og SLUMP()

Design by Contract Bertrand Meyer Design and Programming by Contract. Oversigt. Prædikater

Skriftlig Eksamen Kombinatorik, sandsynlighed og randomiserede algoritmer (DM528)

Videregående Programmering Obligatorisk opgave - 3. semester, efterår 2004

Skak, backgammon & dam

Bumser og Drager. Antal spillere: 3-5 Alder: 16+ Spilletid: 40min+

Flere ligninger med flere ukendte

Anvendelse af metoder - Programmering

Forelæsning Uge 1 Torsdag

Forelæsning Uge 2 Torsdag

Forelæsning Uge 2 Torsdag

Baggrundsnote om logiske operatorer

Du trækker 2 gange, hvis begge spillere bekender begge gange, så er der kun 1 trumf tilbage, og du vil ALTID vinde.

Java Klasse nedarvninger

Simulering af stokastiske fænomener med Excel

DM507 Algoritmer og datastrukturer

Dokumentation af programmering i Python 2.75

Lavet af Danni jensen og David Olsen

Rolf Fagerberg. Forår 2013

Lederens ressourceoptimering

Odder og Samsø biavl Nyhedsbrev om biavl for Odder og Omegns Biavlerforening Specialnummer 11. maj 2013 nr. 44

Løsning af møntproblemet

Collegetable.dk præsenterer. College Table grøn

Afstande, skæringer og vinkler i rummet

Mircobit Kursus Lektion 2

Andreas Lauge V. Hansen klasse 3.3t Roskilde HTX

Rekursion C#-version

DM507 Algoritmer og datastrukturer

Projekt 9.5 Racefordomme i USA og Simpsons paradoks (B og A)

DM13-1. Obligatoriske Opgave - Kredsløbs design

Lineære sammenhænge, residualplot og regression

Mattip om. Statistik 2. Tilhørende kopier: Statistik 3, 4 og 5. Du skal lære om: Faglig læsning. Chance og risiko. Sandsynlighed

Invarianter. Invariant: Et forhold, som vedligeholdes af algoritmen gennem (dele af) dens udførelse. Udgør ofte kernen af ideen bag algoritmen.

Afstande, skæringer og vinkler i rummet

DM507 Algoritmer og datastrukturer

Forelæsning Uge 2 Torsdag

Scratch. - introduktionshæfte

Daglig brug af JitBesked 2.0

Programmering C Eksamensprojekt. Lavet af Suayb Köse & Nikolaj Egholk Jakobsen

Spil Rapport. Spil lavet i GameMaker. Kevin, Mads og Thor

Opgave: BOW Bowling. Rules of Bowling. danish. BOI 2015, dag 1. Tilgængelig hukommelse: 256 MB

Transkript:

dsoftark E2007 Gruppe 14: Anders, Troels & Søren 15. november 2007 Rapport til a. 1 'TDD rytmen' Vi bruger gennem vores arbejde, rytmen fra Test Driven Development-paradigmet. Quickly add a test Run tests and see new test fail Make a little change Run tests and see all succed Refactor to remove duplication Tests og iterationer TDD har mantraet 'Clean code that works' - dette opnår vi ved at konstruere test-cases for alle tænkelige tilfælde hvorpå softwaren kunne tænkes at blive anvendt. Til at begynde med, har vi vores interface til Boardet - metoderne herfra laver vi den konkrete implementation af i klassen BoardImpl. Herefter skal vi teste at de forskellige implementationer virker som tiltænkt. Først tilføjer vi en test til iterator-metoden. Denne failer da den ikke returnere et Iterator-objekt. Det faker vi ved bare at returnere et sådan. Det giver grøn bar. Så skal de øvrige metoder implementeres... vi starter med getcount Test: antal brikker på B1 skal i standardopstillingen være 2 Rød bar Fake it: returner 2 Test: antal brikker på B1 skal i standardopstillingen være 2 Rød bar Fake it: returner 2 Test: farven på B1 skal i standardopstillingen være rød 1

Rød bar Fake it: returner Color.RED Test: inden yt skal der være 2 på B1 og 0 på B2, efter yt skal der være 1 på B1 og 1 på B2. Rød bar Kan ikke fake længere. Implementerer boardet som et HashMap<Location,int> Bruger obvious implementation til at resette boardet i konstruktoren. Move implementeret -> Får stadig red bar > Implementerer getcount rigtigt Rød bar! (boarded er ikke resat) Implementerer reset() Rød bar Implementerede move()! Test: Der skal være sorte brikker på R1 Rød bar Kan ikke fake, så implementerer getcolor() rigtigt.! Test: Vi forventer at getcount på Rød's BEAR OFF plads er 0 samt farven er NONE Rød bar! Why?!?! Fordi vi havde glemt at tilføje specialfelterne til iteratoren. Disse er nu implementeret! Hurrah! Test: Vi forventer at der konstant er 30 brikker på brættet også efter et yt 2

========================== ALPHAMON ============ Vi implementerede metoderne fra board via "Obvious Implementation"pattern. Test: Når man starter spillet skal ingen spiller have turen. (farven = NONE) Rød bar Fake det hele: returnerer Color.NONE Test: Arrayet returneret skal have længden 2 og må ikke være null. Rød bar (nullpointerexception) Fake it: returnerer en tom array af størrelse 2 (begge værdier er 0) Test: Terningekastene er inden for grænsen [1-6] Rød bar Fake it: vi returnerer 2,2 istedet Test: winner() er altid NONE så længe spillet kører Rød bar (null) Fake it: Returnerer Color.NONE Test: Spillet er ikke igang endnu så playerinturn skal returnere Color.NONE Rød bar (null) Fake it: Returnerer Color.NONE Test: Første spiller er forventet BLACK efter første nextturn() grundet dicethrown implementationen (fast deneret). Rød bar: Vi kan ikke fake playerinturn længere Implementerer den.! 3

Test: Når spillet er igang: Alle moves er valid bortset fra hvis der er en modstanders brik på pladsen. n Flytter R1 til R2. (sort brik til tom plads) Forventer true da playerinturn er BLACK Test: Flytter B1 til B2. (rød brik til tom plads) Forventer false da playerinturn er BLACK men det er røde brikker vi forsøger yttet Test: Flytter B1 til B2 da det er røds tur. (rød brik til tom plads) Forventer true da det netop er røds tur Test: Vi gerne sikre os at spillet når til en afslutning og rød altid vinder. Rød bar: winner er ikke implementeret, det gør vi. Test: Fordelingen mellem terningernes værdier skal være nogenlunde fair Vi forventer at på 200000 kast vil der kun være en lille forskel. eektivt vil vi dividere med 2000 for at oprette fejlmargenen. Rød bar Vi kan ikke fake den længere. Derfor returnerer vi 2 tilfældige tal med Math.Random metoden. 4

Vores note om denne test. Vigtigheden af denne test kan diskuteres, da dens opførsel af natur er en anelse non-deterministisk. Men jo ere gange testen køres jo mere pålideligt er resultatet. Ved denne opførsel er vi også nød til at teste dicerange ere gange, men på grund af denne tests implementation så bliver dette testet implicit. Det er en advanceret test. men Vi synes den er god nok at have med. Denne test kan synes grotesk, da testkoden er markant større og mere kompleks end vores produktionskode, på den anden side kunne Danske Spil godt have brugt en sådan her for nyligt... 5

dsoftark E2007 Gruppe 14: Anders, Troels & Søren 23. november 2007 Rapport til a. 2 1

RFSE Øvelse 30.4 ---------------- Da vi skulle oprette en Betamon-udgave, undersøgte vi forskellene og hvad der varierede ifht. alphamon, og benyttede hermed 3-1-2 metoden til at definere et interface, hvor forskellene bliver faktoriseret ud derfra. Vi omdøbte klassen AlphamonGame til den generelle HotGammonGame, som nu er den klasse som varetager ansvaret for de fælles metodesignaturer Alpha- og Betamon i mellem. Nu står vi så med to konkrete implementationer af vores interface som implementerer hhv. Alphamon og Betamon strategien. AlphamonStrategy og BetamonStrategy. En af disse giver, (eller en vilkårlig anden klasse) vi så med i konstruktøren til hotgammon, og den opfører sig derefter som ønsket, kun med de nødvendige signaturer for det pågældende spil. Vi har set på det som varierede mellem Alpha- og Betamon som reglerne for hvordan strukturen for spillet skulle opføre sig. Vi lagde to ansvarsområder ud, nemlig det at flytte spilleren rundt på pladen. Her skal Alphamon og Betamon nu selv afgøre hvorvidt det er et lovligt træk, og derefter flytte brikken. Derudover skal begge have en vinderstrategi, som nu også ligger i Alpha- og Betamon. Dette har vi gjort da vi så at det som de regler, der havde ændret sig mellem de to. - Igennem dette brugte vi TDD for på den måde at være sikker på en konsistent løsning, så man når en ny implementation giver 'Grøn Bar' kan man være sikker på at man har lavet en godt abstraktion til det nye niveau. Så langsomt begynder TDD fremgangsmåden at give mere og mere pote, så at sige. Man har undervejs slet ikke fornemmelsen af at sidde med et massivt ansvar, for at det hele stadig virker. Da man, hvis testforløbet går godt, ved at systemet er konsistent. Enkelte af de tilføjede testcases måtte vi refaktoriserer koden for at bringe til 'Grøn Bar' tilstanden, men det viste sig senere at være en rigtig god ting. For efter det, fejlede overraskende få af de nyoprettede testcases. - Da vi i 3-1-2 processen undersøgte hvad det var som varierede ved vores produktionskode, kom vi frem til at det var reglerne for spillet der varierede (hvilket vi nu indser var forkert, da vi derved flyttede mange ansvarsområder ind i regelstrategien og dermed programmeret 'in anticipation of needs, not when need arise'

RFSE Øvelse 30.5 ---------------- Her skulle vi benytte flere forskellige terningstategier. Så vi brugte her 3-1-2 processen, og vi identificerede terningeansvaret som vores varierende punkt. Det blev derefter faktoriseret ud i et interface for sig selv, DiceStrategy, som kan realiseres af de mulige spilkonfigurationer der måtte opstå. - Herfra har vi lavet 3 konkrete implementationer af interfacet: - FixedDiceStrategy: Som Alpha- og Betamon benytter, da denne har terningværdier der hele tiden forøges. - RandDiceStrategy: Denne klasse giver tilfældige tal i intervallet [1,6] men denne klasse kan vi ikke teste med automatiserede tests, da den bygger på Javas indbyggede tilfældighedsgenerator Math.random() som, ud fra Obvious Implemtation, bare virker. - TestStubDiceStrategy: Denne klasse ligger i modsætning til de andre, i test-mappen. Det gør den da vi kun bruger den som placeholder for den reelle tilfældige stategi, da denne ikke ellers lader sig teste. Vores test-stub virker således at vi inde fra testen beholder en reference til TestStubDiceStrategy objektet så vi kan kalde en metode der gemmer en serie af tal som terningen skal vise i rækkefølge. Derved kan vi fuldstændigt styre hvilke "tilfældige" tal som vores terning genererer. Med TDD lavede vi nogle nye tests for at kontrollere konsistensen af de nye regler som fulgte med Gammamon. Vi copy-pastede indtil videre den gamle kode for at teste om et move er gyldigt fra Alphamon, men vi ved godt at vi senere skal have ændret ansvarsområdet så Gammamon kan genbruge kode fra Alphamon stategien og bare bruge den nye tilfældige terning. Vi lavede en del fejl mht. 3-1-2 metoden underfejs men vi føler at vi nu står med et system som ikke er helt dumt længere. Der er stadig mange områder hvor abstraktionen kan gøres bedre, men vi føler selv vi er på rette vej igen nu. Gruppe 14.

Sekvens Diagram UML Diagram! #

dsoftark aflevering 3 Gruppe 14: Anders Riggelsen, Søren Løbner, Troels Hansen Vi har tænkt en del over hvordan vi har kunnet afkoble endnu mere funktionalitet fra strategierne, gøre dem simplere, og ikke mindst gøre det muligt at kunne kombinere dem på simpel vis. Vi har jo bunke af tests så vi kan roligt gå igang med af refactorisere og ændre. I sidste uge havde vi i vores Gamestrategy en metode der hed HasMoreValidMoves(Game, Color), da den på mange måder minder meget om vores move metode, og der iøvrigt kun reelt var en metode i HotgammonGame klassen der benyttede den, besluttede vi at smide den væk! Vores HasMoreValidMoves metode stod for et check som var meget tæt koblet med validering af 'move' metoder, så vi lavede en generel løsning istedet. For at opretholde en grønbar oprettede vi en metode isvalid i Gamestrategy, movemetoden kan så kan spørge derom et træk lovligt, en simpel refactoring. Nu kommer humlen så ved at have en isvalid, for at emulere HasMoreValidMoves er det blot at afprøve alle tænkelige træk, på en givenkonfiguration (game), det virker ved første øjekast tåbeligt, men den asymptotiske tid er O(1). Da der som tidligere nævnt kun reelt en metodeder benytter sig af denne funktionalitet, så derfor har vi ladet denne del synke ned i HotgammonGame klassen. Og vi har stadig grøn bar. Vi står nu med en move metode der altid synes at gøre det samme, så den har vi også ladet synke ned i HotgammonGame.. Tilbage i Gamestrategy er der blot 2 metoder, isvalid og determinewinner, disse har vi valgt at splitte op i 2 nye strategi typer, defineret ved interfacene MoveValidationStrategy og WinStrategy, da der giver mulighed for bedre at kunne kombinere disse og bygge nye varianter. Dette indebærer dog en Konstruktor ændring i HotgammomGame, samt lidt ændringer af variabel navne, men det er hurtigt overstået.. Vi vil nu kigge på MoveValidationStrategy implementationerne, for de har faktisk en del kode tilfælles, f.eks. at man ikke må flytte fjendens brikker osv. Dette bad næsten om at blive lavet om til at benytte composite patternet. Så vi factoriserede alle de små regler ud i mindre strategi implementationer der så kan kombineres med en CompositeMoveValidatorStrategy klasse.

Ideen med CompositeMoveValidatorStrategy er at man kan betragte de enkelte regler som Constraints, for at et træk er lovligt så skal alle constraints være opfyldt. En constraint i denne sammenhæng er en anden klasse der implementerer MoveValidationStrategy, CompositeMoveValidationStrategy er således blot en bunke af constraints der blot ligner en enkelt constraint. På denne her måde får vi nogle mindre byggesten som nemt kan kombineres og derved skabe et nyt regelsæt. Hvis man så ellers husker at tilføje de rigtige regler til Composite klassen så han man stadig grønbar. Deltamon er implementeret ved at oprette en CompositeMoveValidationStrategy der aggregerer de samme MoveValidationStrategy'er som Alphamon bruger, dog bruges der en "InnerTableWinStrategy" istedet for en "WinAfterSixMovesStrategy" samt at der er tilføjet den strategi kaldet "OnlyMoveRightDirectionStrategy" som oprindeligt kommer fra Gammamon og allerede er blevet testet. Da vi allerede har testet de andre strategier tilfører Deltamon kun få nye tests da der ikke er rigtig brug for at teste alle de foregående strategier igen. Vores tests tester først om begge farver kan vinde spillet efter at alle brikkerne er flyttet ind i deres inner-table. Derefter tester vi for en sikkerheds skyld at ingen endnu har vundet hvis vi flytter *næsten* alle brikkerne ind i spillernes inner-table. Ansvarsområder: HotgammonGame - Ansvarlig for at samle trådene. flytte brikker slå terninger, skiftetur, udregne tilbageværende træk. MoveValidationStrategy - har ansvaret for at bestemme om et givent træk, givet en tilstand, er gyldigt. DiceStrategy - er algoritmen der kaster terningen, og har ansvaret for at levere de udfald vi måtte ønske. WinStrategy - Har ansvaret for at afgøre hvem der har vundet, hvis nogen, givet en konfiguration. AlphamonFactory DeltamonFactory - Har ansvaret for at oprette en fuldt fungerende konkret Game implementation. Dette gør de i praksis ved at oprette/instansiere alle strategier relevant for deres respektive spiltype, men kunne principielt set godt have returneret en annonym klasse med strategierne hardcoded uden brug af andet.

Diagram: På de konkrete factories har vi ikke tegnet pile til HotGammonGame og til de andre konkrete MoveValidationStrategies da det hele ellers vil blive uoverskueligt. Vi har også kun nøjet med at tegne Alphamon og Betamon's factories for simplicitetens skyld. Roller: AbstractFactory bruger Abstract Factory pattern til at instantiere de strategier der skal bruges for det aktuelle spil. AlphamonFactory - DeltamonStrategy er alle konkrete fabrikker i Abstract Factory Pattern, hvor det abstrakte produkt fra fabrikkerne er Game. Det konkrete produkt er et HotGammonGame. Interfacet AbstractFactory leverer en fælles tilgang til instantiering af vores konkrete produkter, dvs. spilvarianter. Produktet er et Game, defineret ud fra game interfacet. Vores konkrete fabrikker, dvs. AlphamonFactory - DeltamonFactory, har ansvaret for at levere produkter af den konkrete variant. I praksis betyder dette blot en instatiering af HotgammonGame klassen med forsklellige parametre, svarende til forskellige strategier. WinStrategy, MoveValidationStrategy og DiceStrategy er en del af Strategy Pattern hvor NoMoveToEnemyOccupiedFieldsStrategy - ValidMoveStrategy er alle konkrete strategier af den abstrakte (ikke af forveksle med javas 'abstract') strategi (interfacet). Contexten i alle disse Strategy Patterns er HotgammomGame der aggregerer alle strategierne i en liste der kan indeholde en hvilket som helst strategi på grund af den løse kobling vi laver ved at programmere op mod et interface (pr. strategitype) frem for konkrete strategi-implementationer.

dsoftark Aflevering 5 Gruppe 14: Anders Riggelsen 20063138, Søren Løbner 20050677, Troels Hansen 20062372 Opgave 1: ------------ Vi grublede en del over hvordan vi skulle gribe testning af dette an. Som sådan er det jo blot nogle byggeklodser der sættes sammen på en anden, og de er jo allerede testet. Sammensætningen grænser det åbenlyse, og ingen af komponenterne er afhængige af hinanden, de kender ikke engang til hinandens eksistens. Så vi lavede en enkelt simulering af fuldt spil, og vupti grønbar fra start. Testen er dog lavet med den forudsigelige terning, da alt andet næsten ville kræve en AI. Opgave 3: Shesh-Besh: ------------ I dette tilfælde vil vi nemt kunne indføre Shesh-Besh uden nogen form for ændringer nogen steder, kun ved at tilføje. En hurtig analyse vil vise at det eneste der ændrer sig for denne spil-type er en mængde MoveValidationStrategies baseret på om terningerne har slået (6,5) Shesh-besh beskrivelsen lægger op til at man også kan flytte modstanderens brikker og det er jo i sig selv også bare en MoveValidationStrategy som skal "slås" fra når den specielle tilstand opnåes. En løsning ville være at tilføje en klasse, der implementerer MoveValidationStrategy interfacet, som vælger hvilke MoveValidationStrategies der skal bruges ved at kigge på terningernes øjne (State pattern). Vi har en god kode-genbrug og vi ændrer ikke i vores eksisterende kode. Acey-Ducey: ----------- Denne spilvariant er desværre ikke helt ligetil da vi ikke kan implementere dette så hurtigt som Shesh-Besh da vi først er nødt til at refaktorisere. For det første så har vores nuværende spiltype en hård kobling på brikkernes start-position som nu skal til at variere. Brikkernes start-position bliver lige nu specificeret i BoardImpl's 'reset()' metode så en refaktorisering er nødvendig. En løsning til dette kunne være at lave et BoardSetupStrategy interface og lave to konkrete implementationer: StandardSetup og OffBoardSetup. Strategien kunne så gives med i BoardImpl's konstruktør. Lige nu er vores kobling på BoardImpl så stor at der ikke kan pilles ved den udefra overhovedet hvilket vi nu er interesseret i. I vores refaktorisering vil vi så flytte ansvaret for instansiering af et Board væk fra Game og over i vores AbstractFactory der opretter hele spillet. Vi får derved en højere grad fleksibilitet kun ved at flytte ansvaret en smule. Vores nuværende opdeling af Move-Validation regler er tilstrækkelig til at kunne udtrykke de fleste af Acey-deucy's regler på det område. Vi kommer dog i problemer når det gælder terningeslaget (1,2). For det første skal vi have tilføjet en interface-del der tillader spilleren at fortælle spillet hvilken terning han/hende vil vælge. (en sådan tilføjelse til MiniDraw

vil jeg ikke gå i detaljer med). Dernest har vores nuværende HotGammonGame implementation heller ikke support for "ekstra-tur" konceptet som vi også bliver nødt til at tilføje. Dette kunne gøres ved at tilføje en set-metode til Game-interfacet som i de konkrete implementationer vil sætte en "extra-turn" variabel. Er den over 0 vil nextturn() trække 1 fra variablen og lade den nuværende spiller få nyt slag. Denne metode skal så bruges af noget der holder øje med om nogle kriterier er opfyldt. Der er mange måder at gøre dette på, der kunne blandt andet bruges et nyt brug af strategy pattern med tilhørende interface. Der kan så laves konkrete implementation som f.eks. i dette tilfælde "12ExtraTurn" strategy eller i Backgammons tilfælde en "TwoEqualDicesExtraTurn" strategy. Opgave 4 --------- Hvis vi skal implementere SemiMon som et polymofisk design, så står vi med lidt af et dilemma, Vi kan arve fra enten Betamon, Gammamom eller Deltamon. Alle tre har elementer som vi skal bruge. Drejer sig primært om 3 metoder i game interfacet: nextturn() - som er korrekt i Gammamon move() - som er korrekt i Betamon winner() - som er korrekt i Deltamon med korrekt menes der at de er korrekte i forhold til Semimon. Desværre har vi kun et "skud i bøssen" når det kommer til arv, og valget om hvilken vi vælger at arve fra, skal bero på hvilken metode vi helst ikke vil implementere igen (eller copy paste for den sags skyld...). nextturn() er en relativ simpel metode at implementere, så der er ikke så meget ide i at arve fra Gammamon. move er en meget kompleks metode så den ville ikke være helt skidt at arve fra betamon. winner ligger lidt i mellem og er bestemt også en kandidat da vi skal skitsere 2 kandidater. Et andet problem er metoden getnumberofmovesleft(), der jo beror en del på om move vil tillade et træk eller ej. Den mest favorable løsning hvad angår arbejdsmængden er Betamon. Som pseudo kode vil den blive noget i den retning: class Semimon extends Betamon{ nextturn(){ /*implementationen fra Gammamon */ } } winner(){ /*implementationen fra Deltamon */ }

UML'en er da: hvis vi derimod vælger at arve fra Deltamon så ville den blive noget i den retning: class Semimon extends DeltaMon{ nextturn(){ /*implementationen fra Gammamon */ } } move(from, to){ /*implementationen fra Betamon */ } getnumberofmovesleft() { /*implementationen fra Betamon */ } UML'en er da: Opgave 5 --------- Som vi kunne se fra 4 så fik vi faktisk ikke ret meget kode genbrug ud af det, vi fik allerhøjst et multiple maintainence problem ud af det, og om muligt endnu værre, hvis en uforsigtig programmør pillede lidt i alphamon i forbindelse med en fejlrettelse, så kan der potentielt set opstå fejl i alle andre varianter. I polymofien stabler man alt ovenpå de nederste kasser. Hvis den nederste kasse går i stykker så vælter hele bundtet.. hårdt... Sammenlignet med vores kompositionelle design hvor vi kunne implementere ca. 7 linjers kode (hvis den komprimeres lidt), det er kodegenbrug af rang, og oven i det er koden ufattelig simpel kode, mod det polymorfiskedesigns mere komplekse kode som man rent faktisk skal tænke over.

Der er naturligvis en bagside ved medaljen, det polymorfiske design er meget nemt at overskue, der er ikke ret mange klasser, hvor vores kompositionelle design har en ti-fold flere klasser, hvilket gør det sværere at overskue. Navnene på klasserne bliver også langt mere komplekse hvilket i et stortset projekt gør codecompletion til en must. Der stilles således også visse editor krav. Ansvarsdelen i det polymorfiske design er på sin vis ret overskuelig set udefra ("Disse klasser har ansvar for alt") men det er i praksis én stor "blob" af ansvarsområder som er næsten umulig at håndtere når der kommer mange varianter af ens software. Det kompositionelle design har klart definerede ansvarsområder. Så hvis man kan overskue alle de mange klasser kompositionelt design giver, så er ansvarsområderne meget nemmere at overskue.

Sidste dsoftark aflevering Gruppe 14 December 19, 2007 1 Til validering af standard træk (dvs. der ikke er en checker i bar, for den respektive spiller, og han ikke vil flytte den til bear off). Vi betragter vores validering som en boolsk funktion med følgende parametre v( move, player, board-state, die-value), hvilket betyder at det er det vi har tilgængeligt at regne på. Vi startede med at definere en funktion dist(f,t) (from og to henholdsvis) der beregner afstanden mellem 2 felter. Som vores første slice i partitioneringen ligger de to tilfælde: dist(f, t) = dice value - Valid dist(f, t) dice value - Invalid f og t er afledt af move parametren. dist(f, t) = dice value dist(f, t) dice value Som en lille note så er en valid partitioner markeret med Som det næste definerede vi en color(c) funktion der giver farven på et felt, vi kan så opdele vores partitionering yderligere Med hensyn til color, så vil vi også gerne skelne mellem farven på spilleren, på den måde om han er none eller ej. vores første farve inddeling bliver derfor player = none som er invalid. Den næste måde som vi vil skelne mellem farver på, er om felt farven på from feltet er det samme som spilleren eller ej. det giver os 2 yderligere: color(f) player player none - Invalid color(f) = player player none - Valid 1

color(f) player player NONE color(f) = player player NONE player = NONE dist(f, t) = dice value dist(f, t) dice value Det sidste vi skal have checket er om et felt er blocked (om der står 2 af fjendens brikker der eller mere). I vores partitionering har vi nu lige præcis en partition der er valid, den vil vi arbejde videre med, og efterlade de andre som de er (I dette eksempel bliver de restende 5 partitioner ikke valid af at vi finindeler dem). Vi definerer en ny funktion isblocked(f, p) der afgør om et felt er blocked ud fra et felt og en player, lidt mere detaljeret kunne den beskrives således: isblocked(f, p) = count(f) >= 2 color(f) p læg mærke til at vi brugte funktionen count, den tæller antallet af brikker på et felt. vi opdeler nu den valide partition i 2 nye, defineret ud fra: isblocked(f, player) - Invalid isblocked(f, player) - Valid dist(f, t) = dice value dist(f, t) dice value color(f) player player NONE color(f) = player player NONE isblocked(t, player) isblocked(t, player) Udfra denne partionering er vi nu endt op med en masse ækvivalensklasser. De er intuitivt disjunkte da enhver slice vi har lavet har været mere eller mindre binær, og begge tilfælde er dækket, alle tilfælde er dækket og der er ingen ækvivalensklasser der overlapper hinanden. player = NONE 2

Udfra ækvivalensklasserne skal vi have følgende tests: en Hvor terningen ikke matcher distancen brikken flyttes, men derudover er alle regler overholdt, dette tester klassen behøver en test i og da de alligevel vil fejle.. Vi kan så argumentere for at vi ikke I samtlige af de næste tests lader vi terninge værdien matche distancen. I denne test lader vi player være none, og udfører derefter et ellers helt legalt træk, den skulle gerne fejle, vi har således testet klassen. I den næste test prøver vi at flytte på modstanderens brik, det svarer til at teste klassen, der skal naturligvis også melde false. I næste test vil vi prøve at flytte en brik hen på et felt hvor den står 2 af modstanderens brikker. Denne test giver klassen, og er invalid. i den sidste test prøver vi at udføre et fuldstændig legalt træk, der er valid, og så burde vi jo også få en true på den. Dette tester Det er diskutabelt om der burde have været en finere inddeling, f.eks. med blocked tilfældet, kunne man har haft mere end 2 brikker på feltet, netop 2 brikker på feltet og mindre en 2 brikker på feltet 2 Her skal vi lave en analyse af situatinen når en spiller har en brik på bar feltet. Det jo åbentlyst at vi ikke behøver at starte forfra men kan egentlig blot forfine vore nuværende partitionering, da regelsættet her blot er en stramning af det foregående. Vi vil derfor kun kigge på den valide partion fra det foregående, og så må man tænke sig til at den kan copy pastes oven på det tilsvarende felt fra opgave 1. Her kan vi igen bruge count funktionen, denne benytter vi til at tælle antallet af brikker i bar (vi har valgt ikke at skelne, det er nødagtig det samme hvadenten du er rød eller sort. vi har således 2 tilfælde: count(bar) = 0 og count(bar) > 0 Hvis vi er i det første tilfælde så er det egentlig blot reglerne fra opgave 1 der gælder (partitionen er altså lovlig) det andet tilfælde skal dog subinddeles lidt. Reglerne siger at hvis der ligger en brik på bar så skal den flyttes inden en anden må flyttes. Det giver jo anledning til 2 partionener: from = bar - Valid from bar - Invalid Vi ender således op med denne partition: count(bar) > 0 from = bar count(bar) > 0 from bar count(bar) = 0 Denne repartitionering giver kun anledning til 2 ekstra test: Et normalt valid move, hvor der dog ligger en brik i bar. Denne skal give false, og den tester. I den sidste test ligger der en brik på bar, og den flyttes helt legalt, Dette tester 3

. behøver vi ikke teste da den allerede er testet i opgave 1. 3 Ved sammenligning af vores eksisterende testcases blev det noget af en overraskelse, da det faktisk kun var 3-4 af ækvivalens klasserne der var dækket ind, af nye test s har vi fået følgende: playerisnonebutvalidmove - der dækker rightdistcolornotplayer1of2 - der dækker rightdistcolornotplayer2of2 - der dækker MoveFromColorNONE - der dækker MoveTooFar - der dækker MoveTooShort - der dækker resten var allerde dækket. Det er vores erfaring at denne tilgang både giver færre og betydeligt bedre testcases end den knopskydnings metode vi har brugt før. 4