/* Om du undrar: Spelet är på engelska för att undvika problem med teckenkodning. */ #include /* fclose fopen fscanf getchar printf puts remove scanf */ #include /* rand srand NULL */ #include /* time */ #include /* getche */ #define HANDLENGTH 12 #define INITIALMONEY 100 #define FILENAME "21.dat" int game(); /* Kallas efter att spelaren har satsat. Returvärde: 1 = spelaren vinner 2 = spelaren vinner dubbelt 3 = spelaren vinner blackjack (betalas 3:2) 4 = banken vinner 5 = banken vinner dubbelt 0 = lika */ int drawhand(char, char, char); /* Kallas när spelaren eller banken ska spela sin hand. */ char drawcard(); /* Drar ett kort från en kortlek som lagras "static". Vid början och när korten är slut blandas de med... */ void shuffle52(char*); /* Blandar kortleken. */ char cardname(char); /* Returnerar kortets namn. 1 -> 'A', 2 ... 9 -> '2' ... '9', 10 -> 'T', 11 -> 'J', 12 -> 'Q', 13 -> 'K'.*/ int printcards_sum(char*); /* Kallas av drawhand. Skriver ut handen. */ int main() { int result; double money, bet; FILE *save = fopen(FILENAME, "r"); if (save == NULL) { /* Om filen inte existerar, ge spelaren $100... */ money = INITIALMONEY; puts("Welcome to Blackjack!"); } else { while (fscanf(save, "%lf", &money) != 1) /* ...annars, ta summan från}*/ while(getchar() != '\n'); /* filen. */ fclose(save); } while (1) { if (money < 0.0) { puts("You're in the red. Farewell!"); /* Slut på pengar? Då försvinner */ remove(FILENAME); /* filen. */ return 0; } printf("You have $%.2f. How much do you want to bet? ", money); while (scanf("%lf", &bet) != 1) { printf("Sorry, didn't catch that. "); while(getchar() != '\n'); /* Få en satsning och ta bort alla */ } /* felaktiga karaktärer. */ while(getchar() != '\n'); if (bet <= 0.0) { puts("See you later!"); /* Blank satsning = spara och sluta. */ save = fopen(FILENAME, "w"); fprintf(save, "%.2f", money); return 0; } switch (result = game()) { case 1: /* Ge eller ta bort en summa, beroende på */ money += bet; /* resultat. */ break; case 2: money += 2.0 * bet; break; case 3: money += 1.5 * bet; break; case 4: money -= bet; break; case 5: money -= 2.0 * bet; } } } int game() { char card1 = drawcard(), card2 = drawcard(), doubled = 0; int player, bank; if (card1 == 1 && card2 >= 10 || card2 == 1 && card1 >= 10) { printf("My hand is %c %c, I got a blackjack!\n", /* Först drar banken */ cardname(card1), cardname(card2)); /* två kort. Blackjack? Då return 4; /* vinner banken. */ } printf("My hole card is %c\n", cardname(card1)); /* Ett av bankens kort är */ player = drawhand(1, 0, 0); /* öppet. */ if (player == -21) { puts("You got a blackjack!"); return 3; /* Får spelaren blackjack vinner han direkt.*/ } if (player & 32) { doubled = 1; player ^= 32; /* Ta bort bitmasken. */ } if (player > 21) { /* Om spelaren går över... */ puts("You're busted!"); return 4 + doubled; } puts("My turn."); bank = drawhand(0, card1, card2); /* Korten som redan drogs passeras till */ if (bank > 21) { /* drawhand. */ puts("I'm busted!"); /* Om banken går över... */ return 1 + doubled; } if (bank > player) { puts("I win!"); return 4 + doubled; } if (player > bank) { puts("You win!"); return 1 + doubled; } puts("Push."); /* Har koden utförts så här långt är det oavgjort. */ return 0; } int drawhand(char player, char card1, char card2) { char c[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, decision; int i = 2, sum; c[0] = card1 ? card1 : drawcard(); c[1] = card2 ? card2 : drawcard(); sum = printcards_sum(c); if (sum == 21) return -21; /* Blackjack returnerar -21. */ while (1) { /* Den här delen är kul. Om player != 0 bestämmer spelaren vad som skall göras. Om player = 0 bestämmer programmet automatiskt! */ if (player) { if (i == 2) printf("d = Double "); printf("h = Hit s = Stand\n>"); decision = getche(); puts(""); } else { if (sum >= 17) decision = 's'; else decision = 'h'; } switch (decision) { case 'd': case 'D': if (i > 2) { /* Man får bara dubbla om man har två kort. */ puts("Huh?"); continue; } case 'h': case 'H': c[i++] = drawcard(); /* Om 'h' eller 'd', dra kort. */ break; case 's': case 'S': return sum; /* Om spelaren/banken stannar, returnera värdet. */ default: puts("Huh?"); continue; } sum = printcards_sum(c); if (sum > 21) /* Gick över? */ return sum; if (decision == 'd' || decision == 'D') return sum + 32; /* Bitmask! Sjätte biten från höger slås på. Den betecknar dubblering. */ } } char drawcard() { static int card = 51; static char deck[52] = {1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13}; if (card == 51) { printf("Shuffling deck.\n"); shuffle52(deck); card = 0; } card++; return deck[card - 1]; } void shuffle52(char *a) { char i, j, tmp; srand(time(NULL)); for (i = 51; i > 0; i--) { j = rand() % (i + 1); tmp = a[j]; /* Se även "Fisher-Yates shuffle" på engelska Wikipedia. */ a[j] = a[i]; a[i] = tmp; } } char cardname(char card) { switch (card) { case 1: return 'A'; break; case 10: return 'T'; break; case 11: return 'J'; break; case 12: return 'Q'; break; case 13: return 'K'; break; default: return (card + 48); break; } } int printcards_sum(char *c) { int i = 0, sum = 0, ace = 0; while (i < HANDLENGTH && c[i]) { printf("%c ", cardname(c[i])); /* Skriv först ut kortnamnen. */ if (c[i] >= 10) sum += 10; /* T, J, Q, K är alla värda 10. */ else if (c[i] == 1) { sum += 1; ace = 1; } else sum += c[i]; i++; } if (ace && sum <= 11) /* Kan ett av ässen räknas som 11? */ sum += 10; /* 11 - 1 = 10, så lägg till 10. */ printf("(%d)\n", sum); return sum; }