Trädvy Permalänk
Medlem
Plats
Karlskrona
Registrerad
Dec 2010

Black Jack C-programmering

Tjenare alla kära medlemmar, snart kommer någonting gå sönder, känner mig så totalt jävla usel att det är helt otroligt....

Sitter med ett sista projekt i skolan nu i kursen Inledande programmering C. Vi ska koda i olika dokument, alltså ett dokument för funktionsdeklarationer, ett dokument för funktionsdefinitoner och ett med själva programmet så att säga.

Det jag gjort än så länge är att skapa en struct för kort (enum color och enum value) hela kortleken, och en funktion som blandar hela kortleken. Jag vill nu på något sett ge ut 2 kort var till båda spelare och sedan göra en funktion som fortsätter ge ut ett kort. Jag tänker att eftersom att kortleken är blandad, så kanske man kan göra en loop som bara ger nästa kort som ligger i leken, så tar man bort chansen att man ger ut samma kort 2 gånger.

Det största problemet för mig egentligen är hur man får över färgen och värdet på kortet över från funktionsdefinitionen till själva programfilen.

giveCardToPlayer(color, rank); {
printf("Your starting cards is %s of %s and %s of %s", rank1, color1, rank2, color2);
}

Tänker mig att något i stil med koden ovan i programfilen ska göra att vid start av program står det "Your starting cards is Four of Diamonds and Six of Hearts".

Har förstått att man inte kan returnera 2 värden, men kan jag returnera en struct? För Struct Card består ju av just Rank och Color, så det vore väl perfekt?

Gigabyte 1070 G1 Gaming 8GB | I5 4690k @ 4.4GHz | 16GB ram @ 1600MHz | SSD 500gb | Qpad 8K | MK-85 RED | Logitech G933

Trädvy Permalänk
Medlem
Plats
åkersberga, Täby
Registrerad
Jun 2004
Skrivet av Craiser:

Tjenare alla kära medlemmar, snart kommer någonting gå sönder, känner mig så totalt jävla usel att det är helt otroligt....

Sitter med ett sista projekt i skolan nu i kursen Inledande programmering C. Vi ska koda i olika dokument, alltså ett dokument för funktionsdeklarationer, ett dokument för funktionsdefinitoner och ett med själva programmet så att säga.

Det jag gjort än så länge är att skapa en struct för kort (enum color och enum value) hela kortleken, och en funktion som blandar hela kortleken. Jag vill nu på något sett ge ut 2 kort var till båda spelare och sedan göra en funktion som fortsätter ge ut ett kort. Jag tänker att eftersom att kortleken är blandad, så kanske man kan göra en loop som bara ger nästa kort som ligger i leken, så tar man bort chansen att man ger ut samma kort 2 gånger.

Det största problemet för mig egentligen är hur man får över färgen och värdet på kortet över från funktionsdefinitionen till själva programfilen.

giveCardToPlayer(color, rank); {
printf("Your starting cards is %s of %s and %s of %s", rank1, color1, rank2, color2);
}

Tänker mig att något i stil med koden ovan i programfilen ska göra att vid start av program står det "Your starting cards is Four of Diamonds and Six of Hearts".

Har förstått att man inte kan returnera 2 värden, men kan jag returnera en struct? För Struct Card består ju av just Rank och Color, så det vore väl perfekt?

Jag svarar nog inte på din fråga nu, men vill dela med mig hur jag hade löst problemet.

Först hade jag lagrat alla kort i en lista.

Sedan hade jag skapat en lika stor lista som håller koll på vilka kort som redan givits.

Sedan en funktion som delar ut korten. Funktionen ligger i en loop och användaren kan dra hur många kort han vill så länge han inte överskrider 21.

Samtidigt uppdateras listorna för vilka kort som varit och vilka som är kvar.

Något sådant=)

Det är sant att du inte kan returnera 2 värden. Dock kan du returnera listor som kan ta ton av värden.

Skickades från m.sweclockers.com

Dator 1.
FX 8350 4.7Ghz | 24GB ram | MSI Radeon RX 480 | Kingston SSD | Fractal design R2.0 | PSU : Fractal 650W
Dator 2 (Bärbar). HP Folio 9470m

Trädvy Permalänk
Datavetare
Plats
Stockholm
Registrerad
Jun 2011
Skrivet av Craiser:

Har förstått att man inte kan returnera 2 värden, men kan jag returnera en struct? För Struct Card består ju av just Rank och Color, så det vore väl perfekt?

Ja, du kan returnera en struct, detta är helt OK

enum rank { ACE, TWO, ... QUEEN, KING, NUM_RANKS }; enum color { CLUBS, DIAMONDS, HEARTS, SPADES, NUM_COLORS }; struct card { enum color; enum rank; }; struct card_deck { int top; /* index to top of deck */ struct card cards[NUM_RANKS * NUM_COLORS]; /* deck of card, bottom card at index 0 */ }; ... struct card draw_top(struct card_deck *deck) { if (deck->top == 0) { fail("tried to draw from empty deck"); } return deck->cards[--deck->top]; }

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Trädvy Permalänk
Medlem
Plats
Karlskrona
Registrerad
Dec 2010
Skrivet av martin_cs:

Jag svarar nog inte på din fråga nu, men vill dela med mig hur jag hade löst problemet.

Först hade jag lagrat alla kort i en lista.

Sedan hade jag skapat en lika stor lista som håller koll på vilka kort som redan givits.

Sedan en funktion som delar ut korten. Funktionen ligger i en loop och användaren kan dra hur många kort han vill så länge han inte överskrider 21.

Samtidigt uppdateras listorna för vilka kort som varit och vilka som är kvar.

Något sådant=)

Det är sant att du inte kan returnera 2 värden. Dock kan du returnera listor som kan ta ton av värden.

Skickades från m.sweclockers.com

Tack för svar, tänker du att jag ska göra i en array? förstår inte riktigt hur det ska fungera...

Skrivet av Yoshman:

Ja, du kan returnera en struct, detta är helt OK

enum rank { ACE, TWO, ... QUEEN, KING, NUM_RANKS }; enum color { CLUBS, DIAMONDS, HEARTS, SPADES, NUM_COLORS }; struct card { enum color; enum rank; }; struct card_deck { int top; /* index to top of deck */ struct card cards[NUM_RANKS * NUM_COLORS]; /* deck of card, bottom card at index 0 */ }; ... struct card draw_top(struct card_deck *deck) { if (deck->top == 0) { fail("tried to draw from empty deck"); } return deck->cards[--deck->top]; }

Ja du, förstår vad koden gör men inte hur den fungerar... Blir så sjukt besviken på att jag inte fattar...

struct Card* createDeck() {
struct Card* deck = NULL;
deck = (struct Card*)malloc(sizeof(struct Card) * 52);

int currentColor = 0;
for (int i = 0; i < 52; i++) {
deck[i].rank = (enum value)(i % 13);

//färgbyte
if (i != 0 && i % 13 == 0) {
currentColor++;
}

deck[i].color = (enum suite)
currentColor;
}
return deck;

Så ser createDeck ut just nu, fick hjälp av läraren för att få ihop det där. Men jag förstår mig inte på "enum"

Gigabyte 1070 G1 Gaming 8GB | I5 4690k @ 4.4GHz | 16GB ram @ 1600MHz | SSD 500gb | Qpad 8K | MK-85 RED | Logitech G933

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Sep 2006
Skrivet av Craiser:

Tack för svar, tänker du att jag ska göra i en array? förstår inte riktigt hur det ska fungera...

Ja du, förstår vad koden gör men inte hur den fungerar... Blir så sjukt besviken på att jag inte fattar...

struct Card* createDeck() {
struct Card* deck = NULL;
deck = (struct Card*)malloc(sizeof(struct Card) * 52);

int currentColor = 0;
for (int i = 0; i < 52; i++) {
deck[i].rank = (enum value)(i % 13);

//färgbyte
if (i != 0 && i % 13 == 0) {
currentColor++;
}

deck[i].color = (enum suite)
currentColor;
}
return deck;

Så ser createDeck ut just nu, fick hjälp av läraren för att få ihop det där. Men jag förstår mig inte på "enum"

Jag har programmerat C/C++ i 15 år och den där loopen gjorde mig lite förvirrad också, så känn dig inte dålig om du inte förstår. Jag hade nog gjort så här istället:

int cardIndex = 0; for(int c = 0; c < 4; c++) { for(int r = 0; r < 13; r++, cardIndex++) { deck[cardIndex].rank = (enum value)r; deck[cardIndex].color = (enum suite)c; } }

Rent allmänt är det svårt att läsa andras kod eftersom man tappar så mycket information som personen som skrev koden hade i huvudet.

Läs tex här om vad en enum är.

Och ja, du kan returnera en struct i stil med:

struct Card giefcardplx(struct Card* deck, int index) { return deck[index]; }

Trädvy Permalänk
Medlem
Plats
Karlskrona
Registrerad
Dec 2010
Skrivet av grovlimpa:

Jag har programmerat C/C++ i 15 år och den där loopen gjorde mig lite förvirrad också, så känn dig inte dålig om du inte förstår. Jag hade nog gjort så här istället:

int cardIndex = 0; for(int c = 0; c < 4; c++) { for(int r = 0; r < 13; r++, cardIndex++) { deck[cardIndex].rank = (enum value)r; deck[cardIndex].color = (enum suite)c; } }

Rent allmänt är det svårt att läsa andras kod eftersom man tappar så mycket information som personen som skrev koden hade i huvudet.

Läs tex här om vad en enum är.

Och ja, du kan returnera en struct i stil med:

struct Card giefcardplx(struct Card* deck, int index) { return deck[index]; }

Haha, tack så mycket! Har gjort något i stil med det där, gjorde så en funktion för att ge startkorten till player1 och en för player2 sen tänkte jag göra en gemensam funktion som kan ge 1 kort åt gången. Jag satte även printfunktionen i funktionsdefinitionen och i och med att det är 13 värden och 4 färger blev det 17 if-satser 3 gånger, haha. Ser väldigt ineffektivt ut, men fungerar för det jag vill ÄN sålänge.

Funktionsdefinition
void giveStartingCardsToPlayer1(struct Card deck[], int nrOfCards) {
for (int i = 0; i < 2; i++) {
if (deck[i].rank == ACE)
printf("Ace");
else if (deck[i].rank == TWO)
printf("Two");
else if (deck[i].rank == THREE)
printf("Three");
else if (deck[i].rank == FOUR)
printf("Four");
else if (deck[i].rank == FIVE)
printf("Five");
else if (deck[i].rank == SIX)
printf("Six");
else if (deck[i].rank == SEVEN)
printf("Seven");
else if (deck[i].rank == EIGHT)
printf("Eight");
else if (deck[i].rank == NINE)
printf("Nine");
else if (deck[i].rank == TEN)
printf("Ten");
else if (deck[i].rank == JACK)
printf("Jack");
else if (deck[i].rank == QUEEN)
printf("Queen");
else
printf("King");

printf(" of ");

if (deck[i].color == HEARTS)
printf("Hearts");
else if (deck[i].color == SPADES)
printf("Spades");
else if (deck[i].color == CLUBS)
printf("Clubs");
else
printf("Diamonds");
printf("\n");
}
}

Blackjack.C
printf("%s, these are your starting cards, would you like another? (Yes or no)\n", player1Name);

giveStartingCardsToPlayer1(deck, 2);

scanf_s("%s", answer, sizeof(answer));
if (answer == "yes") {
giveCardToPlayer();
}
else if (answer == "no") {
return 0;
}

Och nu kommer ju funktionsdefinitionen för "giveCardToPlayer();" bli lika stor som "giveStartingCardsToPlayer1", haha. Bara att den startar på ett annat index. Känns detta som en vettig lösning?

Gigabyte 1070 G1 Gaming 8GB | I5 4690k @ 4.4GHz | 16GB ram @ 1600MHz | SSD 500gb | Qpad 8K | MK-85 RED | Logitech G933

Trädvy Permalänk
Datavetare
Plats
Stockholm
Registrerad
Jun 2011

@Craiser: tänk på varje "enum" som en en samling etiketter på något som hör ihop.

enum suite { CLUBS, DIAMONDS, HEARTS, SPADES };

är då mänskligt läsbara etiketter för heltalsvärdena 0 (CLUBS), 1 (DIAMONDS), 2 (HEARTS) och 3 (SPADES).

Är ju lättare att förstå kod som

if (card->suite == HEARTS) { ... }

jämfört med

if (card->suite == 2) { ... }

då siffran 2 blir lite "magisk" och inte alls självklar.

Vad din lärare hjälp dig med är en funktion som skapar en hel kortlek genom att allokera en minne som är stort nog att hålla 52 st "struct Card". Pekaren som createDeck() returnerar är en pekare till första kortet i kortleken. Fungerar rent logiskt, men skulle nog själv definiera en speciell typ för kortleken.

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Trädvy Permalänk
Datavetare
Plats
Stockholm
Registrerad
Jun 2011

Blir lite lättare att läs koden om du bryter ut detta till en funktion

if (deck[i].rank == ACE) printf("Ace"); else if (deck[i].rank == TWO) printf("Two"); else if (deck[i].rank == THREE) printf("Three"); else if (deck[i].rank == FOUR) printf("Four"); else if (deck[i].rank == FIVE) printf("Five"); else if (deck[i].rank == SIX) printf("Six"); else if (deck[i].rank == SEVEN) printf("Seven"); else if (deck[i].rank == EIGHT) printf("Eight"); else if (deck[i].rank == NINE) printf("Nine"); else if (deck[i].rank == TEN) printf("Ten"); else if (deck[i].rank == JACK) printf("Jack"); else if (deck[i].rank == QUEEN) printf("Queen"); else printf("King");

Kan i stället bli

const char * rankToStr (enum Rank rank) { switch (rank) { case ACE: return "Ace"; case TWO: return "Two"; case THREE: return "Three"; case FOUR: return "Four"; case FIVE: return "Five"; case SIX: return "Six"; case SEVEN: return "Seven"; case EIGTH: return "Eigth"; case NINE: return "Nine"; case TEN: return "Ten"; case JACK: return "Jack"; case QUEEN: return "Queen"; default: return "King"; } } ... printf("%s", rankToStr(deck[i].rank));

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Trädvy Permalänk
Medlem
Plats
Karlskrona
Registrerad
Dec 2010
Skrivet av Yoshman:

@Craiser: tänk på varje "enum" som en en samling etiketter på något som hör ihop.

enum suite { CLUBS, DIAMONDS, HEARTS, SPADES };

är då mänskligt läsbara etiketter för heltalsvärdena 0 (CLUBS), 1 (DIAMONDS), 2 (HEARTS) och 3 (SPADES).

Är ju lättare att förstå kod som

if (card->suite == HEARTS) { ... }

jämfört med

if (card->suite == 2) { ... }

då siffran 2 blir lite "magisk" och inte alls självklar.

Vad din lärare hjälp dig med är en funktion som skapar en hel kortlek genom att allokera en minne som är stort nog att hålla 52 st "struct Card". Pekaren som createDeck() returnerar är en pekare till första kortet i kortleken. Fungerar rent logiskt, men skulle nog själv definiera en speciell typ för kortleken.

Det där var pedagogiskt, tack så mycket! :). Vad tror du om lösningen jag gjorde ovan? Jag tänker mig att jag nu kommer behöva göra funktioner som håller koll på Player1CurrentValue och Player2CurrentValue dessutom göra en playerHouse, eller vad man kallar dealern :D.
Sen en funktion som berättar vem som vinner. Är Enum ett effektivt sätt att göra detta på? Min programmeringskunniga vän, sa att han tyckte det var mycket lättare med arrayer för kortlekarna, då kunde han använda en för att ta bort kort som han ger ut.

Gör gärna programmet min egen väg, även om det är oeffektivt så tror jag att jag lär mig bäst så, se kanske reflektera över koden i efterhand, men som jag nämnde tidigare, tror du att min lösning i kommentaren ovan fungerar?

Gigabyte 1070 G1 Gaming 8GB | I5 4690k @ 4.4GHz | 16GB ram @ 1600MHz | SSD 500gb | Qpad 8K | MK-85 RED | Logitech G933

Trädvy Permalänk
Medlem
Plats
Karlskrona
Registrerad
Dec 2010
Skrivet av Yoshman:

Blir lite lättare att läs koden om du bryter ut detta till en funktion

if (deck[i].rank == ACE) printf("Ace"); else if (deck[i].rank == TWO) printf("Two"); else if (deck[i].rank == THREE) printf("Three"); else if (deck[i].rank == FOUR) printf("Four"); else if (deck[i].rank == FIVE) printf("Five"); else if (deck[i].rank == SIX) printf("Six"); else if (deck[i].rank == SEVEN) printf("Seven"); else if (deck[i].rank == EIGHT) printf("Eight"); else if (deck[i].rank == NINE) printf("Nine"); else if (deck[i].rank == TEN) printf("Ten"); else if (deck[i].rank == JACK) printf("Jack"); else if (deck[i].rank == QUEEN) printf("Queen"); else printf("King");

Kan i stället bli

const char * rankToStr (enum Rank rank) { switch (rank) { case ACE: return "Ace"; case TWO: return "Two"; case THREE: return "Three"; case FOUR: return "Four"; case FIVE: return "Five"; case SIX: return "Six"; case SEVEN: return "Seven"; case EIGTH: return "Eigth"; case NINE: return "Nine"; case TEN: return "Ten"; case JACK: return "Jack"; case QUEEN: return "Queen"; default: return "King"; } } ... printf("%s", rankToStr(deck[i].rank));

Oj, dem där funktionerna har jag aldrig hört talas om! Kraven i uppgiften är att använda Struct, allokeringar och inte ha NÅGRA memorylekages. Sen får inte heller några globala variabler finnas med.

Gigabyte 1070 G1 Gaming 8GB | I5 4690k @ 4.4GHz | 16GB ram @ 1600MHz | SSD 500gb | Qpad 8K | MK-85 RED | Logitech G933

Trädvy Permalänk
Datavetare
Plats
Stockholm
Registrerad
Jun 2011
Skrivet av Craiser:

Oj, dem där funktionerna har jag aldrig hört talas om! Kraven i uppgiften är att använda Struct, allokeringar och inte ha NÅGRA memorylekages. Sen får inte heller några globala variabler finnas med.

OK, är bättre att du håller dig till konstruktioner du förstår än att göra saker lite kortare/effektivare.

Om du har möjlighet så kan det vara lärorikt att köra det du har så här långt i en debugger för att se hur programmet uppför sig under körning.

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Trädvy Permalänk
Medlem
Plats
Karlskrona
Registrerad
Dec 2010
Skrivet av Yoshman:

OK, är bättre att du håller dig till konstruktioner du förstår än att göra saker lite kortare/effektivare.

Om du har möjlighet så kan det vara lärorikt att köra det du har så här långt i en debugger för att se hur programmet uppför sig under körning.

Skriver ju i visualstudio. Prövade köra programmet, det som händer än så länge är att den frågar person 1 och 2 om namn, sedan printas de 2 första korten i kortleken ut och den frågar spelare1 om den vill ha fler kort, har inte hunnit göra en funktion som printar ut ett kort åt gången, men om svaret blir något annat än "ja", så hoppar den till spelare 2 och gör samma grej där. tanken är väl att jag ska ha ännu en funktion som printar ut totalpoängen innan den frågar om man vill ha ett till kort och sen hur jag ska göra med dealern har jag ännu ingen aning om

Gigabyte 1070 G1 Gaming 8GB | I5 4690k @ 4.4GHz | 16GB ram @ 1600MHz | SSD 500gb | Qpad 8K | MK-85 RED | Logitech G933

Trädvy Permalänk
Medlem
Plats
Karlskrona
Registrerad
Dec 2010
Skrivet av Yoshman:

OK, är bättre att du håller dig till konstruktioner du förstår än att göra saker lite kortare/effektivare.

Om du har möjlighet så kan det vara lärorikt att köra det du har så här långt i en debugger för att se hur programmet uppför sig under körning.

Ursäkta att jag citerar dig, men hoppas på proffshjälp igen, Haha.

har fastnat när jag ska göra en if-loop med en char. I detta fall ser det ut såhär

char answer1[16];

printf("%s, would you like another card? (yes or no) \n", player1Name);
scanf_s("%s", answer1, sizeof(answer1));

printf("%s", answer1); //bara här för att kontrollera om scanf tog ut rätt svar (vilket den gör)

if (answer1 == "yes") {
printf("\n%s, This is your new card.\n", player1Name); //För att kontrollera om programmet går in i loopen, vilket den inte gör...
}

Gigabyte 1070 G1 Gaming 8GB | I5 4690k @ 4.4GHz | 16GB ram @ 1600MHz | SSD 500gb | Qpad 8K | MK-85 RED | Logitech G933

Trädvy Permalänk
Medlem
Plats
Karlskrona
Registrerad
Dec 2010

Okej, lyckades lösa det problemet, genom att köra strcmp. Men nu har ett nytt problem dykt upp.

Denna funktion

void giveCardToPlayer(struct Card deck[], int nrOfCards) {
for (int i = 6; i < 52; i++) {
alla kort
}

gör att när jag kallar på den genom dessa kodrader

printf("Okey, this is your new card.\n", player1Name);
giveCardToPlayer(deck, 1);

printar ut alla kort i hela kortleken som finns kvar, jag vill ju bara att funktionen ska printa ut ett kort :/

Gigabyte 1070 G1 Gaming 8GB | I5 4690k @ 4.4GHz | 16GB ram @ 1600MHz | SSD 500gb | Qpad 8K | MK-85 RED | Logitech G933

Trädvy Permalänk
Medlem
Plats
åkersberga, Täby
Registrerad
Jun 2004

@Craiser:

har inte kollat igenom all din kod & jag orkar inte heller . . .

Vad använder du variabeln intnrOfCards till?

Ser inte att den används i din funktion.

Du kanske råkar skriva ut alla element i din array?

Peka på det kortet du vill skriva ut t.ex. printf(kort[det_kortet_du_vill_skriva_ut]);

Dator 1.
FX 8350 4.7Ghz | 24GB ram | MSI Radeon RX 480 | Kingston SSD | Fractal design R2.0 | PSU : Fractal 650W
Dator 2 (Bärbar). HP Folio 9470m

Trädvy Permalänk
Medlem
Plats
Uppsala
Registrerad
Dec 2008

@Craiser:

Borde du verkligen sitta och programmera 05:41?

Jag tror att du borde sätta dig och bryta ner problemet i mindre delar som du kan lösa ett i taget. Ta ett delproblem i taget och tänk igenom steg för steg hur du kan lösa det. Verkar något delproblem krångligt, se om du kan bryta ner det i ännu mindre delar. Gör detta på svenska, inte i ett programmeringsspråk. När jag läser dina inlägg hittills i tråden får jag intrycket av att du inte tänkt hela vägen innan du börjar skriva kod.

När du har lite rutin kommer det att gå mer eller mindre automatiskt, men som nybörjare är det viktigat att ha tänkt igenom problemet hela vägen innan man börjar koda.

Om vi börjar från början:

Hur skall du representera ETT kort?

Hur skall du representera en hel lek av kort? Hur blandas leken? Hur skall du hantera att man tar ett kort ur leken? Hur många kort har du kvar i leken? Vad skall hända när korten tar slut? Spelar man på krogen har dealern fler kort än 52 i leken, skall du kunna hantera det?

Hur skall du representera EN spelare? Hur hanterar du spelarens kort, pott och insats?

Hur skall du representera FLERA spelare? Hur många skall du kunna hantera? Skall du ha en lista av spelare eller kanske en array?

Hur skall du hantera dealern? Ungefär som en spelare, men hen skall dra automatiskt.

Vad skall hända när dealern ger ett kort till en spelare? Vad händer med spelaren? Vad händer med leken?

När skall du fråga om en spelare vill ha fler kort? När har det spruckit? Essen kan ha två värden, hur fixar du det? Vad händer när en spelare vinner? Vad händer när en spelare förlorar?

Det är mycket att fundera på, men du borde ha tänkt igen om allt det här innan du börjar koda, annars sitter du där och undrar varför din funktion skriver skriver ut kort 6 till 51 i leken när du bara vill ha ett kort...

Trädvy Permalänk
Medlem
Plats
Karlskrona
Registrerad
Dec 2010
Skrivet av Ingetledigtnamn:

@Craiser:

Borde du verkligen sitta och programmera 05:41?

Jag tror att du borde sätta dig och bryta ner problemet i mindre delar som du kan lösa ett i taget. Ta ett delproblem i taget och tänk igenom steg för steg hur du kan lösa det. Verkar något delproblem krångligt, se om du kan bryta ner det i ännu mindre delar. Gör detta på svenska, inte i ett programmeringsspråk. När jag läser dina inlägg hittills i tråden får jag intrycket av att du inte tänkt hela vägen innan du börjar skriva kod.

När du har lite rutin kommer det att gå mer eller mindre automatiskt, men som nybörjare är det viktigat att ha tänkt igenom problemet hela vägen innan man börjar koda.

Om vi börjar från början:

Hur skall du representera ETT kort?

Hur skall du representera en hel lek av kort? Hur blandas leken? Hur skall du hantera att man tar ett kort ur leken? Hur många kort har du kvar i leken? Vad skall hända när korten tar slut? Spelar man på krogen har dealern fler kort än 52 i leken, skall du kunna hantera det?

Hur skall du representera EN spelare? Hur hanterar du spelarens kort, pott och insats?

Hur skall du representera FLERA spelare? Hur många skall du kunna hantera? Skall du ha en lista av spelare eller kanske en array?

Hur skall du hantera dealern? Ungefär som en spelare, men hen skall dra automatiskt.

Vad skall hända när dealern ger ett kort till en spelare? Vad händer med spelaren? Vad händer med leken?

När skall du fråga om en spelare vill ha fler kort? När har det spruckit? Essen kan ha två värden, hur fixar du det? Vad händer när en spelare vinner? Vad händer när en spelare förlorar?

Det är mycket att fundera på, men du borde ha tänkt igen om allt det här innan du börjar koda, annars sitter du där och undrar varför din funktion skriver skriver ut kort 6 till 51 i leken när du bara vill ha ett kort...

Har försökt tänka så, jag tycker bara att det är sjukt komplicerat att komma på själva koden. Jag tycker det verkar vettigt att blanda kortleken till att börja med och sen bara börja på index 0 och ta det som i verkligheten att man tar kortet högst upp i leken, sen går man steg för steg neråt och med det, ökar man indexen för varje nytt kort som tas. Problemet för mig är att jag inte har någon aning om hur man kan koda det i C.

Vi ska ju dessutom använda oss av Structs. Det jag gjort är så här

void giveStartingCardsToPlayer1(struct Card deck[], int nrOfCards) {
for (int i = 0; i < 52; i++) {
if (deck[i].rank == ACE)
printf("Ace");
else if (deck[i].rank == TWO)
printf("Two");
else if (deck[i].rank == THREE)
printf("Three");
else if (deck[i].rank == FOUR)
printf("Four");
else if (deck[i].rank == FIVE)
printf("Five");
else if (deck[i].rank == SIX)
printf("Six");
else if (deck[i].rank == SEVEN)
printf("Seven");
else if (deck[i].rank == EIGHT)
printf("Eight");
else if (deck[i].rank == NINE)
printf("Nine");
else if (deck[i].rank == TEN)
printf("Ten");
else if (deck[i].rank == JACK)
printf("Jack");
else if (deck[i].rank == QUEEN)
printf("Queen");
else
printf("King");

printf(" of ");

if (deck[i].color == HEARTS)
printf("Hearts");
else if (deck[i].color == SPADES)
printf("Spades");
else if (deck[i].color == CLUBS)
printf("Clubs");
else
printf("Diamonds");
printf("\n");
}
}

Problemet med denna, är att om jag inte begränsar forloopen till "int i = 0; i < 1; i++", så kommer den att fortsätta rulla på tills alla kort upp till 51 är utrprintade. Jag vet inte hur jag ska lyckas med det, jag kan ju sätta break i slutet av loopen och på så vis endast få den att printa ut ett kort, men nästa gång jag kallar på funktionen kommer den fortfarande kasta fram samma kort som förra gången...

Därav har jag gjort en forloop som har "int i = 0; i < 2; i++" för att kasta ut spelare 1's första kort och en som är "int i = 2; i < 4; i++", sen har jag en till som kastar ut "int i = 4; i < 5; i++", alltså ett kort. sen har jag gjort 45 sådana här loopar till typ. Tills jag kommer upp till "int i = 51; i < 52; i++". Detta blir ungefär 2100 rader kod, vilket ser väldigt dåligt ut och icke effektivt. Jag vill verkligen kunna koda bra, men det känns inte som att jag fått tillräckliga kunskaper för det. Jag har sökt som en galning efter olika funktioner på internet också, men blir inte jättemycket vettigare för det, då jag verkligen inte vill kopiera rakt av heller.

Gigabyte 1070 G1 Gaming 8GB | I5 4690k @ 4.4GHz | 16GB ram @ 1600MHz | SSD 500gb | Qpad 8K | MK-85 RED | Logitech G933

Trädvy Permalänk
Medlem
Plats
Karlskrona
Registrerad
Dec 2010
Skrivet av martin_cs:

@Craiser:

har inte kollat igenom all din kod & jag orkar inte heller . . .

Vad använder du variabeln intnrOfCards till?

Ser inte att den används i din funktion.

Du kanske råkar skriva ut alla element i din array?

Peka på det kortet du vill skriva ut t.ex. printf(kort[det_kortet_du_vill_skriva_ut]);

Förstår inte riktigt hur det fungerar med structs. Jag har ju t.ex

enum suit {
HEARTS, SPADES, CLUBS, DIAMONDS
};

enum value {
ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING
};

// deklarerar structs i headerfilen
struct Card {
enum suite color;
enum value rank;
};

Om jag nu vill printa ut color och rank på kortet på index 1 t.ex, hur går jag tillväga?

void giveCard1(struct Card deck[], int nrOfCards)
{
int i = 1;
printf("Your card is %s of %s", deck[i].rank, deck[i].color);
}
Denna funktion printar ju ut värdena som finns på index1, både färg och rank, men dessa returneras ju som int. Alltså blir det typ något i stil med "your card is 1 of 9", vilket inte är så förståeligt för den som spelar. Hur får jag över dessa till char utan att behöva göra sådär sjukt lång kod som jag skickat i kommentaren ovanför? För det känns så sjukt oeffektivt

Gigabyte 1070 G1 Gaming 8GB | I5 4690k @ 4.4GHz | 16GB ram @ 1600MHz | SSD 500gb | Qpad 8K | MK-85 RED | Logitech G933

Trädvy Permalänk
Datavetare
Plats
Stockholm
Registrerad
Jun 2011
Skrivet av Craiser:

Denna funktion printar ju ut värdena som finns på index1, både färg och rank, men dessa returneras ju som int. Alltså blir det typ något i stil med "your card is 1 of 9", vilket inte är så förståeligt för den som spelar. Hur får jag över dessa till char utan att behöva göra sådär sjukt lång kod som jag skickat i kommentaren ovanför? För det känns så sjukt oeffektivt

Du behöver något likt det du gjorde ovan för att översätta från heltal (enum värdet) till en av dig vald textrepresentation. Bättre att du gör det lite längre på ett sätt du förstår än att klippa till med något kort som du inte riktigt greppar.

Lusläser man ISO C standarden skulle man rent tekniskt kunna göra denna översättning så här kort

const char * suiteToStr[] = { "Hearts", "Spades", "Clubs", "Diamonds" }; ... printf("Suite is %s", suiteToStr[deck[i].color]);

Men för att förklara varför detta är korrekt (så länge som [i]deck.color bara har värden som är definerade i av enum Suite kräver att man verkligen har koll på detaljer i ISO C standarden kring hur kompilatorn får välja värden för enum, d.v.s. du ska låta bli detta.

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Trädvy Permalänk
Medlem
Plats
Karlskrona
Registrerad
Dec 2010
Skrivet av Yoshman:

Du behöver något likt det du gjorde ovan för att översätta från heltal (enum värdet) till en av dig vald textrepresentation. Bättre att du gör det lite längre på ett sätt du förstår än att klippa till med något kort som du inte riktigt greppar.

Lusläser man ISO C standarden skulle man rent tekniskt kunna göra denna översättning så här kort

const char * suiteToStr[] = { "Hearts", "Spades", "Clubs", "Diamonds" }; ... printf("Suite is %s", suiteToStr[deck[i].color]);

Men för att förklara varför detta är korrekt (så länge som [i]deck.color bara har värden som är definerade i av enum Suite kräver att man verkligen har koll på detaljer i ISO C standarden kring hur kompilatorn får välja värden för enum, d.v.s. du ska låta bli detta.

Så, du tycker inte att det verkar dumt som nybörjare att ha 2100 rader kod som i stort sätt repeterar sig själv för en funktion som egentligen kan förkortas mycket? Funderar på om jag bara ska låta det vara såhär, då det faktiskt fungerar. Med tanke på att vi ska presentera uppgiften muntligt för läraren, så kan jag ju berätta hur jag försökt på andra sätt men den där var den enda jag behärskade ordentligt.

Gigabyte 1070 G1 Gaming 8GB | I5 4690k @ 4.4GHz | 16GB ram @ 1600MHz | SSD 500gb | Qpad 8K | MK-85 RED | Logitech G933

Trädvy Permalänk
Medlem
Plats
Uppsala
Registrerad
Dec 2008
Skrivet av Yoshman:

Men för att förklara varför detta är korrekt (så länge som [i]deck.color bara har värden som är definerade i av enum Suite kräver att man verkligen har koll på detaljer i ISO C standarden kring hur kompilatorn får välja värden för enum, d.v.s. du ska låta bli detta.

Nja, det räcker ju att kolla lite en bok om C för att se att enum-typens uppräkning börjar på 0 och ökar med ett för varje identifierare. Jag tror det vore bättre att uppmuntra kunskapsinhämtande snarare än avråda från att använda saker man för tillfället inte har full koll på. Koden skulle bli mycket snyggare med strängtabeller istället för en if-kratta med 13 olika alternativ.

Trädvy Permalänk
Medlem
Plats
Uppsala
Registrerad
Dec 2008
Skrivet av Craiser:

Så, du tycker inte att det verkar dumt som nybörjare att ha 2100 rader kod som i stort sätt repeterar sig själv för en funktion som egentligen kan förkortas mycket? Funderar på om jag bara ska låta det vara såhär, då det faktiskt fungerar. Med tanke på att vi ska presentera uppgiften muntligt för läraren, så kan jag ju berätta hur jag försökt på andra sätt men den där var den enda jag behärskade ordentligt.

Jo, det verkar dumt att ha 2100 rader av samma sak. Har du funderat på vilka likheter och skillnader det finns mellan repeterade kodstycken? Skulle man kunna göra en funktion för att minska mängden repetition?

Trädvy Permalänk
Medlem
Plats
Karlskrona
Registrerad
Dec 2010
Skrivet av Ingetledigtnamn:

Jo, det verkar dumt att ha 2100 rader av samma sak. Har du funderat på vilka likheter och skillnader det finns mellan repeterade kodstycken? Skulle man kunna göra en funktion för att minska mängden repetition?

Jo, det som är samma är ju att man vill printa ut kortet på indexplatsen x. (0<x<52)
Jag har funderat på att göra en funktion för att printa ut kortleken utan att ha en for-loop, dvs en funktion som skulle returnera kortets värde på indexplatsen. Problemet är ju att vi inte får ha globala variabler och vi måste använda struct. Då måste man ju använda pekare och annat lullull som jag inte heller behärskar än. Lust att hjälpa?

Tänker just nu något i stil med

void giveCard(struct Card deck[], int nrOfCards) {
i=0
if (deck[i].rank == ACE)
return Ace;
else if (deck[i].rank == TWO)
return Two;
osvosvosv
i++
}
Problemet här är ju att den kommer sätta index till 0 varje gång och kommer därför skicka ut samma kort varje gång?

Sen tänkte jag mig som sagt denna funktion
void giveCard1(struct Card deck[])
{
int i = 1;
printf("Your card is %d of %d", deck[i].rank, deck[i].color);
}

Denna funktion skulle ju kräva att jag gör 52 stycken "void giveCardsX" (0<x<52)
Men här returnar den ju som sagt ett INT-värde, men jag vill ha en textrepresentation (char) på detta.

Gigabyte 1070 G1 Gaming 8GB | I5 4690k @ 4.4GHz | 16GB ram @ 1600MHz | SSD 500gb | Qpad 8K | MK-85 RED | Logitech G933

Trädvy Permalänk
Medlem
Plats
Karlskrona
Registrerad
Dec 2010

Kan även tillägga att det vore trevligt att göra på det sättet med 52 upprepelser, då jag i stort sätt gjort hela spelets grund på det sättet nu och skulle behöva skriva om main() helt annars, haha.

Gigabyte 1070 G1 Gaming 8GB | I5 4690k @ 4.4GHz | 16GB ram @ 1600MHz | SSD 500gb | Qpad 8K | MK-85 RED | Logitech G933

Trädvy Permalänk
Datavetare
Plats
Stockholm
Registrerad
Jun 2011
Skrivet av Ingetledigtnamn:

Nja, det räcker ju att kolla lite en bok om C för att se att enum-typens uppräkning börjar på 0 och ökar med ett för varje identifierare. Jag tror det vore bättre att uppmuntra kunskapsinhämtande snarare än avråda från att använda saker man för tillfället inte har full koll på. Koden skulle bli mycket snyggare med strängtabeller istället för en if-kratta med 13 olika alternativ.

Att använda en uppslagstabell må vara snabbt, men det är förenat med en rad problem.

  • kopplingen mellan enum-typen och strängrepresentationen blir implicit vilket betyder att kompilatorn har noll chans att upptäcka fel som att vissa enum-värden hanteras ej, programkonstruktören välde explicit att låta första värdet i sin enum ha ett värde !=0 etc

  • vad händer om man skickar in ett värde som är negativt eller större än största enum?

  • kanske viktigast i detta fall, hur lätt är det att förklara en uppslagstabell för TS då uppgiften ska redovisas muntligt?

Är inte alla böcker som beskriver att enums måste starta på från noll och öka sitt värde med ett förutsatt att man explicit inte väljer andra värden. K&R nämner naturligtvis detta, men t.ex. "The C-book" nämner det inte och säger felaktigt att en enum-typ alltid representeras som int.

Avsett så är enda rimliga sättet att reda ut detaljer i ett språk är att läsa språkdefinitionen (gäller alla språk, inte bara C). Kanske inte det första man vill föreslå för någon som kämpar med en uppgift i grundläggande programmering, men alla som jobbar professionellt med programmering bör rimligen läst språkdefinitionen för det språk man är "expert" i.

Mitt förslag ovan var att högsta prio är att bryta ut processen att översätta från en enum-typ till strängrepresentation till en egen funktion. Hur denna funktion sedan implementeras är mindre viktigt så länge som TS förstår hur den funktionen faktiskt fungerar. Förslog en switch då den har en rad fördelar

  • mindre kod än en if-kratta

  • enkelt att hantera värden som inte är definierade av enum-typen

  • kompilatorn upptäcker om man råkat definiera två enum-konstanter med samma värde

  • med pedantisk varningsnivå så upptäcker kompilatorn också om man missat någon enum->sträng översättning

  • för den som bryr sig om effektivitet kommer bra kompilatorer generera i stort sätt samma kod som en uppslagstabell om enums startar på något värde (behöver inte vara noll) för att sedan öka med 1 (gcc gör detta t.ex.)

Men nu kände inte TS till switch/case så kvar är då att lära sig detta alt. köra med if/else. Det blir som sagt inte 2100 rader utan borde bli 28+8 rader alt. 32+10 rader med hantering av som inte definieras av enum-typen för att översätta från enum-värdet till en strängrepresentation.

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Trädvy Permalänk
Medlem
Plats
Uppsala
Registrerad
Dec 2008
Skrivet av Craiser:

Jag har funderat på att göra en funktion för att printa ut kortleken utan att ha en for-loop, dvs en funktion som skulle returnera kortets värde på indexplatsen. Problemet är ju att vi inte får ha globala variabler och vi måste använda struct. Då måste man ju använda pekare och annat lullull som jag inte heller behärskar än. Lust att hjälpa?

Ojoj, var jag skall börja?

Även om du vill skriva kod så kommer det inte att funka förrän du TÄNKT färdigt. Jag uppfattar det som att du just nu tänker i for-loopar, vill uttrycka saker i for-loopar och då blir det bara for-loopar även om det borde bli någonting annat. Du måste bryta ner problemet du jobbar med till lämpligt stora delproblem. Se programmet som instruktioner till din någon av dina polares mest korkade lillebrorsor. Du skall skriva instruktioner som den korkade lillebrorsan kan följa. Om du börjar skriva instruktionerna innan du själv har klarat ut hur problemet skall lösas kommer den korkade lillebrorsan aldrig att kunna följa din instruktioner. Om du skriver "Ta översta kortet" måste du själv ha klurat ut hur lillebrorsan skall veta vilket kort som ligger överst i leken och vilka som redan är utdelade till spelarna. Om du själv inte har någon aning om hur det skall gå till är det ingen ide att börja koda.

Varför tror du din lärare vill att du skall använda struct och pekare och annan du inte behärskar? Detta är en övningsuppgift som du fått för att lära dig hur dessa saker fungerar. Du borde nog ta fram din kursbok och läsa på om structar och pekare och annat du inte behärskar än.

En struct är bara ett sätt att samla data som hör ihop för att kunna referera till dem som en enhet. Till exempel kan man vilja representera en punkt i ett diagram genom att lägga dess x-koordinat och y-koordinat i en struct. I ditt fall kan man vilja para ihop korten i leken med en variabel som talar om vilket som är det översta kortet. Kolla på Yoshmans kod tidigare i tråden.

Om du inte får använda globala variabler för att skicka information får du hitta på ett annat sätt. Du kan exempelvis skicka information via funktionsparametrar eller i dina structar.

Trädvy Permalänk
Medlem
Plats
Uppsala
Registrerad
Dec 2008

Jo, det finns risker med oskyddad tabelluppslagning, men om jag skriver "Jag tror det vore bättre att uppmuntra kunskapsinhämtande snarare än avråda från att använda saker man för tillfället inte har full koll på." menar jag inte att vi skall skriva kod åt TS för att sätta honom/henne/henom(?) i klistret på redovisningen. I mina ögon verkar TS behöva ta till sig en större delmängd av C än den som TS i dagsläget behärskar och i det läget skulle du göra TS en tjänst om du föreslog att TS läste på om switch.

Skrivet av Yoshman:

Är inte alla böcker som beskriver att enums måste starta på från noll och öka sitt värde med ett förutsatt att man explicit inte väljer andra värden. K&R nämner naturligtvis detta, men t.ex. "The C-book" nämner det inte och säger felaktigt att en enum-typ alltid representeras som int.

Det borde kanske rättats i modernare upplagor, men på den tiden som boken skrevs var enum-typerna representerade av en int.

Trädvy Permalänk
Datavetare
Plats
Stockholm
Registrerad
Jun 2011

@Ingetledigtnamn: som jag skrev så föreslog jag redan en suiteToStr() och kindToStr() funktion baserad på switch/case. Men om TS inte kan (och inte vill / anser sig ha tid) att lära sig om switch/case så fungerar ju även en if-kratta. Inte hela världen då det hela blir isolerat i separata funktioner + det är väldigt lätt att förklara logiken i en muntlig redovisning.

Redan i ISO C kunde enum-typen vara av annan storlek än int. Däremot så är det fortfarande så att de konstanta värden som definieras av en enum-typ är av typen int.

enum Foo { BAR };

I detta fall så kan mycket väl sizeof(enum Foo) vara < än sizeof(int), men värdet BAR har måste alltid hanteras som int när det används som en heltalskonstant. Så tror det mer är ett missförstånd i boken kring vad standarden säger än att den är för gammal. D.v.s. vill man veta hur det verkligen förhåller sig: läs språkdefinitionen, inte vad som står i böcker

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Trädvy Permalänk
Medlem
Plats
Uppsala
Registrerad
Dec 2008

@Yoshman: Jag kollade faktiskt i de två drafts jag hittade på nätet och där stod det implementation defined, men jag trodde att det var en av de saker C anammat från C++. Förr var det vanligt bland embedded-kompilatorerna att de skröt med att man kunde välja vilken typ enumerna skulle vara så jag fick för mig att det på den tiden skulle vara int. Men om du är säger att det även i C89 står implementation defined så litar jag på dig.

Trädvy Permalänk
Datavetare
Plats
Stockholm
Registrerad
Jun 2011
Skrivet av Ingetledigtnamn:

@Yoshman: Jag kollade faktiskt i de två drafts jag hittade på nätet och där stod det implementation defined, men jag trodde att det var en av de saker C anammat från C++. Förr var det vanligt bland embedded-kompilatorerna att de skröt med att man kunde välja vilken typ enumerna skulle vara så jag fick för mig att det på den tiden skulle vara int. Men om du är säger att det även i C89 står implementation defined så litar jag på dig.

Just enum är en sak som skiljer sig mellan C och C++, i C++ (i alla fall C++11) men inte C så är det möjligt att explicit specificera "integer storage type" för varje enum-definition. Enums är helt klart mer komplicerade än vad de verkar på ytan i C/C++, fast kör man med switch/case alt. if-kratta så fungerar saker som man intuitivt förväntar sig.

Lite förvånande att man inte lagt till detta i C, just p.g.a. av vad du skriver om inbyggda-system (tänker främst på mikrokontrollers).

Detta är tillåtet i C++ och garanterar då att sizeof(enum Suite) == sizeof(char)

enum Suite : char { CLUBS, HEARTS, DIAMONDS, SPADES };

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer