/* Om du undrar: Spelet är på engelska för att undvika problem med
  teckenkodning. */

#include <stdio.h> /* fclose fopen fscanf getchar printf puts remove scanf
*/
#include <stdlib.h> /* rand srand NULL */
#include <time.h> /* time */
#include <conio.h> /* 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?

   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;
}