#include #include #include /*************************************************************************** Perpetual Motion Play the Solitaire game Perpetual Motion. Given an initial deck, indicate whether the game was won, blocked, or we got bored. ***************************************************************************/ #define MAX 80 /* maximum line length */ #define NUM 52 /* number of cards */ #define STOP 100 /* if no cards removed for this many rounds, stop */ void play(char deck[MAX]); /*************************************************************************** main ***************************************************************************/ void main(void) { char line[MAX]; int i; int seed; for (i = 1; ; i++) { /* Read a line containing the cards. If the line is blank, it's the end of input. */ if (gets(line) == NULL) /* EOF detected. End of input. */ return; if (strlen(line) == 0) /* Blank line detected. End of input. */ return; /* Play the game, and do appropriate output. */ printf("Game %2d: ", i); play(line); } } /*************************************************************************** play Play the card game, and print the appropriate message. ***************************************************************************/ void play(char deck[MAX]) { char pile[4][NUM]; int index[4]; char deck2[NUM]; int n = 52; int i, j, k; int same, removed; int round, no; #define JUNK 'X' #define card(q) (index[q] > 0 ? pile[q][index[q]-1] : JUNK) round = 0; for (round = 1; ; round++) { /* Initialize all piles to empty. */ for (j = 0; j < 4; j++) index[j] = 0; removed = 0; /* Deal out the cards onto the piles. Remove cards and move to left if possible. */ for (i = 0; i < n; i += 4) { /* Deal 4 cards, face up, one per stack. */ for (j = 0; j < 4; j++) { pile[j][index[j]] = deck[i+j]; index[j] ++; } /* Check if cards can be removed, or moved to left. */ top: /* Check if cards can be removed. */ if (card(0) != JUNK) { same = 1; for (j = 1; j < 4; j++) if (card(j) != card(0)) same = 0; if (same) { for (j = 0; j < 4; j++) index[j] --; removed = 1; goto top; } } /* Check if cards can be moved to left. */ for (j = 0; j < 3; j++) if (card(j) != JUNK) for (k = j+1; k < 4; k++) if (card(j) == card(k)) { pile[j][index[j]] = card(k); index[j] ++; index[k] --; goto top; } /* Cannot remove or move to left. Deal 4 more cards. */ } /* Remake the deck from the piles. */ n = 0; for (j = 0; j < 4; j++) for (k = 0; k < index[j]; k++) deck2[n++] = pile[j][k]; /* Check if we've won. */ if (n == 0) break; /* We haven't won. Check if we're blocked or bored. */ if (! removed) { /* Make sure decks haven't repeated. */ same = 1; for (i = 0; i < n; i++) if (deck[i] != deck2[i]) same = 0; if (same) break; /* If too many rounds with same number of cards, stop. */ no ++; if (no == STOP) break; } else /* There have been 0 rounds with same number of cards. */ no = 0; /* Copy the secondary deck into the primary deck. */ for (i = 0; i < n; i++) deck[i] = deck2[i]; } /* Print winning or losing message. */ if (n == 0) printf("Won after %d rounds.\n", round); else if (same) printf("Blocked after %d rounds with %d cards left.\n", round, n); else printf("Got bored after %d rounds with %d cards left.\n", round, n); }