Permalänk
Medlem

C++ klasser relationer

Hej!

Jag arbetar på att göra ett 2d monopolspel och håller just nu på att konstruera klasser för spelare, spelrutor, tomter mm. Mitt problem är hur jag ska konstruera tomt klassen och spelare klassen så att tomten har en ägare och spelaren vet vilka tomter den äger. Just nu har jag lagt in in pekare i tomt klassen som pekar på en spelare som ägare men hur ska spelaren veta vilka tomter han/hon äger? Ska jag skapa en array med pekare som pekar på de tomter spelaren äger eller finns det något smartare sätt?

Visa signatur

3770k @4,5ghz, EK-Supremacy, 2x hd 7970 @1050/1500 , 4x 4 GB corsair vengeance LP 1600 mhz, Corsair RM1000x, z77a-gd65, Samsung 840 pro 256 GB, Crucial m4 128 GB, Nzxt switch 810

Permalänk
Medlem

Det tycker jag låter som en logiskt upplägg. Använd lämplig metod från STL biblioteket så blir det smidigt att dynamiskt ändra arrayen som anger vilka tomter spelaren äger.

Permalänk
Medlem

Bara som ett alternativ; det kan eventuellt vara en poäng att ha en separat mappning också. Skapa en klass (med singelton-mönster kanske?) som endast innehåller en lista med tomt-spelare par, och anropa metoder i den klassen för att få tillbaka den spelare som äger en given tomt, eller en lista med de tomter som en given spelare äger. Det kan vara enklare från ett designperspektiv då du endast behöver ändra kopplingen på en plats i programmet (din mappningsklass) till skillnad från det du föreslår, vilket kräver att du ändrar i både spelaren som äger tomten och i tomten i sig när den byter ägare. I just ditt fall spelar det inte så stor roll kanske, men om du gör något mer komplicerat är det lätt att man glömmer att ändra på ett ställe, och då blir det tvetydigheter i programmet om hur kopplingen faktiskt är.

Permalänk
Skrivet av Thomas H:

Bara som ett alternativ; det kan eventuellt vara en poäng att ha en separat mappning också. Skapa en klass (med singelton-mönster kanske?) som endast innehåller en lista med tomt-spelare par, och anropa metoder i den klassen för att få tillbaka den spelare som äger en given tomt, eller en lista med de tomter som en given spelare äger. Det kan vara enklare från ett designperspektiv då du endast behöver ändra kopplingen på en plats i programmet (din mappningsklass) till skillnad från det du föreslår, vilket kräver att du ändrar i både spelaren som äger tomten och i tomten i sig när den byter ägare. I just ditt fall spelar det inte så stor roll kanske, men om du gör något mer komplicerat är det lätt att man glömmer att ändra på ett ställe, och då blir det tvetydigheter i programmet om hur kopplingen faktiskt är.

I approve of this. Det här är ungefär vad jag tänkte skriva. För att tillföra något: lek med tanken att använda t.ex. sqlite för att lagra mappningarna. Säkerligen lite overhead men kan inte tänka mig att det skulle vara ett problem. Då har du (om du vill) fixat så du kan spara en spelsession persistent på samma gång (nästan). Sqlite har också stöd för rena in-memory-tabeller om man vill. Sen får man en sån varm känsla av att kunna återanvända existerande mjukvara. Det är inte säkert att fördelarna är tillräckliga för att motivera ett beroende till sqlite, men det kan vara värt en tanke eller två i alla fall.

Permalänk
Medlem

Att köra en separat lista för ägare av tomter som Thomas_h föreslår verkar intressant. Det eliminerar risken att tomterna och spelarna inte är överrens om vem som äger vad. Men att blanda in sql är inte det lite väl avancerat? Jag är nybörjare och detta är mitt första stora projekt. Är det inte bättre att följa KISS principen så att jag inte får en massa onödiga problem :)?

Visa signatur

3770k @4,5ghz, EK-Supremacy, 2x hd 7970 @1050/1500 , 4x 4 GB corsair vengeance LP 1600 mhz, Corsair RM1000x, z77a-gd65, Samsung 840 pro 256 GB, Crucial m4 128 GB, Nzxt switch 810

Permalänk
Medlem

Jag skulle uppskatta det om denna tråd blir en slags WIP med temat "öppet diskutera designmönster".
Dessutom, vem älskar inte monopol?

Permalänk
Medlem
Skrivet av Equadex:

Att köra en separat lista för ägare av tomter som Thomas_h föreslår verkar intressant. Det eliminerar risken att tomterna och spelarna inte är överrens om vem som äger vad. Men att blanda in sql är inte det lite väl avancerat? Jag är nybörjare och detta är mitt första stora projekt. Är det inte bättre att följa KISS principen så att jag inte får en massa onödiga problem :)?

Kanske inte rätt tänkt av mig men jag tänkter att om du ni inte vill lära dig SQL i samma veva nu, kan du alltid tänka modulärt. D.v.s. att byta ut de du har tänkt att använda idag mot SQL eller annat i framtiden. Lite på spåret som Thomas nämnde med SRP, att ha en mappning som tar hand om vilken spelare som äger vad. Samma tanke om att ha separata klasser med vilken klass som styr, hämtar och ändrar data (mappningen) mot hur och var den sparas(sql, txt/ini/bin, array/list etc.).
Då kan du byta ut var och hur du vill spara utan att skada "mappning-klassen"

Permalänk
Medlem

Glöm allt snack och korkade gissningar om SQL och gå tillbaka till din C++ bok, eller hur du nu har lärt dig språket.

När du behärskar språket bra, behöver du inte fråga om sådana här simpla saker.

Visa signatur

Intel Core i7 3770K 3,5Ghz @ 4,5Ghz, Noctua NH-D14, ASUS P8Z77-V , 16GB Corsair Vengeance DDR3 1600MHz, Gigabyte Nvidia GTX 660, Samsung 830 128GB, OCZ Vertex 2 60GB, WD 250GB, Corsair TX 650W, BenQ G2420HDBE, HP L2208w.

Permalänk

Det var dumt av mig att dra upp sql i den här tråden. Men jag rekommenderar fortfarande att bryta ut mappningen så som har föreslagits.

Permalänk
Medlem
Skrivet av Tobijjah:

Glöm allt snack och korkade gissningar om SQL och gå tillbaka till din C++ bok, eller hur du nu har lärt dig språket.

När du behärskar språket bra, behöver du inte fråga om sådana här simpla saker.

Jag behärskar svenska språket, men det automatiskt medför inte att jag blir en grym retoriker, insiktsfull författare, känd bloggare. Hur tänker du egentligen?
Bara för att man behärskar control flows, några bibliotek och vet inte vad, gör en inte till en bra programmerare. HUR man strukturerar är en viktig nyckel. Det har inget med språkets grammatik att göra. Tvärtom så utvecklas programmeringsspråken efter framgångsrika lyckade koncept och verktyg för strukturering av program, i flesta fall dock

Eftersom jag är relativt ny på de med design patterns, srp och allt vad de heter, så är jag inte riktigt varm i kläderna än. Men jag vet att om jag hade lärt mig dessa saker tidigt hade jag inte behövt glömma alla de stökiga, trasslande programmering jag har lärt mig från förr. Vanor är tufft att bryta kan jag säga dig.
Sen kan man inte läsa i böcker om "ett rätt sätt" att programmera. Varje situation är unik och därmed blir dessa typer av trådar då intressanta.

Skrivet av Antonovskij:

Det var dumt av mig att dra upp sql i den här tråden. Men jag rekommenderar fortfarande att bryta ut mappningen så som har föreslagits.

Jag tycker att det var bra att du drog upp SQL, att ha i åtanke om en flexibel lösning för att möta framtiden är A & O! Kan bara svära åt gamla programmerare som står i grund till dessa gamla system som mitt förra jobb hade! Ni vet, gamla system som är dyra att hålla uppe och svåra att utveckla när företaget växer. Regeln var att om man ändrade en funktion på ett ställe fick man debugga överallt annat än där man gjorde ändringen! Fixa dessa buggar ledde i sin tur till andra ändringar och flera andra buggar... hemskt! Där jobbade jag som säljare som fick höra hur stackars programmerarna hade det
Programmerarna hatade när vi säljare kom med önskningar om nya funktioner som vi behövde Missriktad "ilska" tack vare de gamla programmerarna som lämnade sig smutskod till de nya programmerarna

Hursomhelst, hoppas att man får insiktsfulla inlägg här så att jag kan glömma de fel jag har lärt mig sedan tidigare och bli en bättre människa

Permalänk
Medlem
Skrivet av Tobijjah:

Glöm allt snack och korkade gissningar om SQL och gå tillbaka till din C++ bok, eller hur du nu har lärt dig språket.

När du behärskar språket bra, behöver du inte fråga om sådana här simpla saker.

Har läst på om c++ från en bok kallad C++ direkt av Jan Skansholm och använder den som uppslagsverk när jag känner mig osäker på någotting. Har även gått Programmering A och B i java. Mitt problem just nu är inte huvudsakligen språket. Det är hur man designar och konstruerar ett program som just nu är mitt största problem.

Skrivet av SolidReactor:

Kanske inte rätt tänkt av mig men jag tänkter att om du ni inte vill lära dig SQL i samma veva nu, kan du alltid tänka modulärt. D.v.s. att byta ut de du har tänkt att använda idag mot SQL eller annat i framtiden. Lite på spåret som Thomas nämnde med SRP, att ha en mappning som tar hand om vilken spelare som äger vad. Samma tanke om att ha separata klasser med vilken klass som styr, hämtar och ändrar data (mappningen) mot hur och var den sparas(sql, txt/ini/bin, array/list etc.).
Då kan du byta ut var och hur du vill spara utan att skada "mappning-klassen"

Det verkar vara en bra lösning:). Att ha en klass med funktioner för att lagra och hämta data skulle säkert fungera utmärkt. Klassen kan lagra informationen hur den vill internt och resten av programmet behöver inte bekymra sig över det så länge funktionerna utför det dem ska. Skulle det inte räcka med att lagra informationen i en vektor? Om varje tomt får ett id mellan 0-27 (finns bara 28 tomter som går att äga i monopol) och så kan tex det första elementet i vektor specificera vem som äger tomt 0. Eller finns det ett bättre alternativt sätt att göra det på?

En annan fråga som kanske är lite offtopic är hur gör man egentligen när man designar och konstruera program. Jag försökte att bara sätta mig ned och skriva ihop programmet direkt men det är svårt att veta vilka funktioner som behövs, hur data ska hanteras, hur klasser ska kommunicera med varandra mm. Min pappa tipsa mig om att man kunde göra en flowchart för att se hur programmet ska uppföra sig och jag arbetar på att göra en sådan nu. Sedan kan man utifrån flowcharten börja designa klasser och funktioner. Är detta ett bra sätt eller finns det en bättre metod?

Visa signatur

3770k @4,5ghz, EK-Supremacy, 2x hd 7970 @1050/1500 , 4x 4 GB corsair vengeance LP 1600 mhz, Corsair RM1000x, z77a-gd65, Samsung 840 pro 256 GB, Crucial m4 128 GB, Nzxt switch 810

Permalänk
Medlem

Tycker det beror på vilken nivå man ligger på, flowchart/UML tycker jag hjälper mig mycket iaf.
Man får igång tänket och börjar brainstorma på ett helt annat sätt.
Man ser lättare vad som saknas och behövs etc, sen är det ju bara att följa det man kommit fram till och koda.
Finns bra böcker där ute, köpte nyligen en grymt bra bok om "GameEngine", kanske är på en helt annan nivå men man kommer igång med tankesättet på ett helt annat sätt.

Visa signatur

Corsair 16GB (4x4096MB) CL9 1600Mhz | Asus P8Z77-V PRO |
Samsung SSD Basic 830-Series 256GB | Intel Core i7 3770K 3,5Ghz |
Asus Xonar Essence STX | Noctua NH-U9B SE2 | Antec Performance One P280 | Corsair HX 850W 80+ Gold Modulär | MSI GTX 770

Permalänk
Medlem

Får man fråga hur det går/gått? Nyfiken på hur du har gått till väga och hur du har strukturerat programmet

Permalänk
Medlem

Jag tycker också Thomas Hs förslag verkar vettigt. Jag har ett ytterligare förslag. Om du tror det är enklare, så ha bara pekare åt ett håll, tex från tomter till ägare eller tvärt om! Säg att bara tomterna vet vem som äger dem. Då kan du iterera igenom alla tomter för att se vilka en viss spelare äger. Eftersom tomterna är så få så spelar det absolut ingen roll att man får linjär komplexitet i stället för konstant.

Permalänk
Medlem
Skrivet av SolidReactor:

Får man fråga hur det går/gått? Nyfiken på hur du har gått till väga och hur du har strukturerat programmet

Hej igen!
Kul att någon undrar:). Jag har inte haft så mycket tid som jag velat att lägga ned på mitt programeringsprojekt så därför har jag fortfarande mycket kvar att göra. Jag har försökt implementera en separat klass med singleton mönster men jag förstod inte hur det skulle fungera och fick inte rätt på det så därför kör jag med tufflax lösning istället och användar en pekare i tomt klassen som pekar på vilken spelare som äger den (om banken äger så är den 0).

Just nu arbetar jag på skapa tomt objekt med all nödvändig data för att jag ska kunna fortsätta utveckla spelet. De behöver data i form av koordianter på spelbrädet, nummret på spelrutan, vilken typ av tomt de är och olika priser, hyror och mycket mer.
Ett problem här är att många tomter får många onödiga variabler som inte gör någon nytta om man använder en och samma klass till dem alla. Tillexempel så behöver en tomt i av typen chans ingen information om varken priser eller hyror. Däremot kommer typen chans kräva andra funktioner och variabler som inte vanliga gator kommer ha någon nytta av tillexempel en array av chanskort och en funktion för ta upp ett nytt kort till spelarn om den hamnar där. Att lägga in allt detta i en och samma klass blir lite rörigt och jag funderar därför på om jag ska använda arv för att utöka klassen tomt med olika subklasser som t.e.x gata, chans och skatt.

Problemet som hindrar mig att göra detta är att jag lagrar alla mina gator i en array och jag är osäker på om man kan tilldela objekt av en subklass till en array av basklass. Går detta att göra eller får man problem då? Ska man använda arv eller bara slänga in alla funktioner och variabler i samma objekt och låta det som inte används initieras till 0? Kört fast lite på det här så skulle uppskatta lite hjälp

Visa signatur

3770k @4,5ghz, EK-Supremacy, 2x hd 7970 @1050/1500 , 4x 4 GB corsair vengeance LP 1600 mhz, Corsair RM1000x, z77a-gd65, Samsung 840 pro 256 GB, Crucial m4 128 GB, Nzxt switch 810

Permalänk
Medlem
Skrivet av Equadex:

...

Problemet som hindrar mig att göra detta är att jag lagrar alla mina gator i en array och jag är osäker på om man kan tilldela objekt av en subklass till en array av basklass. Går detta att göra eller får man problem då? Ska man använda arv eller bara slänga in alla funktioner och variabler i samma objekt och låta det som inte används initieras till 0? Kört fast lite på det här så skulle uppskatta lite hjälp

Arv låter som en passande idé, tycker jag. Basklass Ruta, subklass Tomt o.s.v. Det går bra att hantera subklasser som basklasser, vilket kallas polymorfism. E.g:

class B { virtual f() { printf("B::f()"); } g() { printf("B::g()"); } }; class S1: public B { f() { printf("S1::f()"); } g() { printf("S1::g()"); } f2() { printf("S1::f2()"); } }; class S2: public B { f() { printf("S2::f()"); } g() { printf("S2::g()"); } f3() { printf("S2::f3()"); } }; B* myArray[3]; myArray[0] = new S1(); myArray[1] = new S2(); myArray[2] = new B(); myArray[0]->f2(); //Går ej myArray[1]->f3(); //Går ej ((S1)myArray[0])->f2(); //S1::f2() ((S2)myArray[1])->f3(); //S2::f3() myArray[0]->f(); //S1::f() myArray[1]->f(); //S2::f() myArray[2]->f(); //B::f() myArray[0]->g(); //B::g() myArray[1]->g(); //B::g() myArray[2]->g(); //B::g()

Det du måste tänka på är att bara den funktionalitet som är synlig i B i koden ovanför kommer vara tillgänglig. Vill du ha tillgång till utökad funktionalitet måste du ta reda på vilken typ av klass objektet är (t.ex. genom att ha en variabel som beskriver typen) och sedan göra en cast på objektet till rätt subklass. Om du gör en funktion "virtual" i B så kommer subklassens implementation att användas i första hand (fallet med f()). Om funktionen inte är virtuell så körs basklassens implementation. även om objektet du kör det på råkar vara en instans av rätt subklass (fallet med g()).