Blackjack dynamisk programmering

I dette avsnittet ser vi pa enkelte konkrete eksempler pa objektorientert design i et domene som er enkelt nok til at vi har mulighet til a komme opp med noe som er rimelig gjenbrukbart. Vurder kortspill som spilles med en standard kortstokk (et sakalt «poker» dekk, siden det brukes i pokerspillet).

5.4.1 Design av klassene.

I et typisk kortspill far hver spiller en hand med kort. Dekket er blandet og kortene deles en om gangen fra dekk og legges til spillernes hender. I noen spill kan kortene fjernes fra en hand, og nye kort kan legges til. Spillet er vunnet eller tapt avhengig av verdien (ess, 2,. King) og dress (spades, diamanter, klubber, hjerter) av kortene som en spiller mottar. Hvis vi ser etter substantiver i denne beskrivelsen, er det flere kandidater til objekter: spill, spiller, hand, kort, dekk, verdi og kostyme. Av disse er verdien og kostnaden av et kort enkle verdier, og de kan bare v re representert som forekomstvariabler i et kortobjekt. I et komplett program kan de andre fem substantivene v re representert av klasser. Men la oss jobbe med de som er mest apenbart gjenbrukbare: kort, hand og dekk.

Hvis vi ser etter verb i beskrivelsen av et kortspill, ser vi at vi kan blande et dekk og handtere et kort fra et dekk. Dette gir oss to kandidater for eksempel metoder i en Dekk klasse: shuffle () og dealCard (). Kort kan legges til og fjernes fra hender. Dette gir to kandidater for eksempel metoder i en handklasse: addCard () og removeCard (). Kort er relativt passive ting, men vi ma i det minste kunne bestemme sine drag og verdier. Vi vil oppdage flere eksempelmetoder nar vi gar.

Forst skal vi utforme dekksklassen i detalj. Nar en kortstokk forst er opprettet, inneholder den 52 kort i noen standard rekkefolge. Dekk-klassen trenger en konstruktor for a lage et nytt dekk. Konstruktoren trenger ingen parametre fordi noe nytt dekk er det samme som noe annet. Det vil bli en instansmetode kalt shuffle () som vil omorganisere 52 kortene i en tilfeldig rekkefolge. AvtaleCard () -metoden vil fa neste kort fra kortstokken. Dette vil v re en funksjon med returtype kort, siden den som ringer trenger a vite hvilket kort som blir behandlet. Det har ingen parametere – nar du handterer det neste kortet fra dekk, gir du ingen informasjon til dekkene; du far bare det neste kortet, uansett hva det er. Hva skjer hvis det ikke er flere kort i dekk nar sin dealCard () metode kalles? Det bor antas a v re en feil a prove a handtere et kort fra en tom dekk, slik at dekkene kan kaste et unntak i det tilfellet. Men dette reiser et annet sporsmal: Hvordan vil resten av programmet vite om dekket er tomt? Selvfolgelig kan programmet holde styr pa hvor mange kort det har brukt. Men selve dekket bor vite hvor mange kort det er igjen, sa programmet burde bare kunne sporre dekkobjektet. Vi kan gjore dette mulig ved a spesifisere en annen instansmetode, cardsLeft (), som returnerer antall kort som er igjen i dekk. Dette forer til en fullstendig beskrivelse av alle delrutiner i dekkklassen:

Dette er alt du trenger a vite for a kunne bruke dekk-klassen. Selvfolgelig forteller det oss ikke hvordan du skal skrive klassen. Dette har v rt en ovelse i design, ikke i koding. Du kan se pa kildekoden, Deck.java, hvis du vil. Det bor ikke v re en overraskelse at klassen inneholder en rekke kort som en instansvariabel, men det er noen ting du kanskje ikke forstar pa dette tidspunktet. Selvfolgelig kan du bruke klassen i dine programmer som en svart boks, uten a forsta implementeringen.

Vi kan gjore en lignende analyse for Hand-klassen. Nar et handobjekt forst opprettes, har det ingen kort i det. En addCard () -metode vil legge til et kort for handen. Denne metoden trenger en parameter av typen Kort for a spesifisere hvilket kort som legges til. For methoden removeCard (), er det nodvendig med en parameter for a spesifisere hvilket kort som skal fjernes. Men skal vi spesifisere selve kortet («Fjern spades ess»), eller skal vi spesifisere kortet ved sin posisjon i handen («Fjern det tredje kortet i handen»)? Faktisk behover vi ikke a bestemme, siden vi kan tillate begge alternativene. Vi har to removeCard () forekomstmetoder, en med en parameter av typen Card som angir kortet som skal fjernes, og en med en parameter av typen int som angir posisjonen til kortet i handen. (Husk at du kan ha to metoder i en klasse med samme navn, forutsatt at de har forskjellige tall eller typer parametere.) Siden en hand kan inneholde et variabelt antall kort, er det praktisk a kunne sporre en handobjekt hvor mange kortene den inneholder. Sa, vi trenger en instansmetode getCardCount () som returnerer antall kort i handen. Nar jeg spiller kort, liker jeg a ordne kortene i handen min slik at kort av samme verdi er ved siden av hverandre. Siden dette er en generelt nyttig ting a kunne gjore, kan vi gi eksempler pa metoder for sortering av kortene i handen. Her er en full spesifikasjon for en gjenbrukbar Hand-klasse:

Igjen er det noen ting i implementeringen av klassen som du ikke forstar pa dette tidspunktet, men det hindrer deg ikke fra a bruke klassen i prosjektene dine. Kildekoden finnes i filen Hand.java.

5.4.2 Kortklassen.

Vi vil se pa design og implementering av en kortklasse i full detalj. Klassen vil ha en konstruktor som spesifiserer verdien og kostnaden av kortet som blir opprettet. Det er fire dresser som kan representeres av heltallene 0, 1, 2 og 3. Det ville v re vanskelig a huske hvilket tall som representerer hvilken dress, sa jeg har definert kalt konstanter i kortklassen for a representere de fire mulighetene. For eksempel er Card.SPADES en konstant som representerer drakten, «spades». (Disse konstantene er erkl rt a v re offentlige endelige statiske ints. Det kan v re bedre a bruke en oppnadd type, men jeg vil stikke her til helt verdsatte konstanter.) De mulige verdiene til et kort er tallene 1, 2,. 13, med 1 staende for et ess, 11 for en jack, 12 for en dronning og 13 for en konge. Igjen har jeg definert noen navngitte konstanter for a representere verdiene til ess og kort. (Nar du leser kortklassen, ser du at jeg ogsa har lagt til stotte for jokere.)

Et kortobjekt kan bygges a kjenne verdien og kostnaden pa kortet. For eksempel kan vi ringe til konstruktoren med uttalelser som:

Et kortobjekt trenger forekomstvariabler for a representere verdien og kostnaden. Jeg har laget disse private slik at de ikke kan endres fra utenfor klassen, og jeg har gitt getter-metoder getSuit () og getValue () slik at det blir mulig a oppdage kostymen og verdi utenfor klassen. Instansvariablene initialiseres i konstruktoren, og blir aldri endret etter det. Faktisk har jeg erkl rt at forekomstvariablene passer og verdier for a v re endelige, siden de aldri blir endret etter at de er initialisert. En instansvariabel kan deklareres endelig dersom den enten er gitt en startverdi i sin erkl ring eller initialiseres i hver konstruktor i klassen. Siden alle instansvariablene er endelige, er et kort et uforanderlig objekt.

Til slutt har jeg lagt til noen fa enklighetsmetoder til klassen for a gjore det lettere a skrive ut kort i en lesbar form. For eksempel vil jeg v re i stand til a skrive ut en jakkesett som ordet «Diamanter», snarere enn det meningslose kodenummer 2, som brukes i klassen til a representere diamanter. Siden dette er noe jeg sannsynligvis ma gjore i mange programmer, er det fornuftig a ta med stotte for det i klassen. Sa, jeg har gitt forekomstmetoder getSuitAsString () og getValueAsString () for a returnere strengrepresentasjoner av drakten og verdien av et kort. Endelig har jeg definert forekomstmetoden toString () for a returnere en streng med bade verdien og kostymen, for eksempel «Queen of Hearts». Husk at denne metoden vil bli brukt automatisk nar et kort ma konverteres til en streng, for eksempel nar kortet er sammenkoblet pa en streng med + operatoren. Dermed erkl ringen.

tilsvarer.

Hvis kortet er dronningen av hjerter, vil noen av disse skrive ut «Ditt kort er Queen of Hearts».

Her er komplett kortklasse. Det er generelt nok til a v re sv rt gjenbrukbart, sa arbeidet som gikk inn i a designe, skrive og teste det, lonner seg godt i det lange lop.

5.4.3 Eksempel: Et enkelt kortspill.

Jeg vil fullfore denne delen ved a presentere et komplett program som bruker kort og dekk-klassene. Programmet lar brukeren spille et veldig enkelt kortspill som heter HighLow. Et kort av kort er blandet, og ett kort blir behandlet fra dekk og vist til brukeren. Brukeren spar om det neste kortet fra kortstokken vil v re hoyere eller lavere enn det nav rende kortet. Hvis brukeren forutsier riktig, blir neste kort fra kortstokken det nav rende kortet, og brukeren gjor en annen prediksjon. Dette fortsetter til brukeren gjor feil forutsigelse. Antall korrekte spadommer er brukerens poengsum.

Mitt program har en statisk metode som spiller ett spill av HighLow. Denne metoden har en returverdi som representerer brukerens poengsum i spillet. Hovedrutinen () lar brukeren spille flere spill av HighLow. Pa slutten rapporterer den brukerens gjennomsnittlige poengsum.

Jeg vil ikke ga gjennom utviklingen av algoritmene som brukes i dette programmet, men jeg oppfordrer deg til a lese det noye og sorge for at du forstar hvordan det fungerer. Merk spesielt at underrutinen som spiller ett spill HighLow, returnerer brukerens poengsum i spillet som returverdi. Dette far poengsummen tilbake til hovedprogrammet, der det trengs. Her er programmet:


Hello! Do you want to play in the most honest casino? We gathered it for you. Push here now!