<mosaic.cnfolio.com>
PROGRAM
  1. /*
  2.  
  3.    Pseudocode
  4.    
  5.    Readcards: -Accepts an area of memory to store the cards into
  6.       Read quantity of cards
  7.       Check for validity(1 < Quantity < 11), exit if not valid
  8.       Read that quantity of cards, checking each is valid (0 < Card < 11) and saving into area of memory passed in
  9.       Call BubbleSort to sort the saved card values
  10.       If CheckLastNewLine is true, pop chars off StdIn until a newline is found. (This is to ensure that the input is in 4 lines as per the spec)
  11.      
  12.    CheckNewLine:
  13.       Read characters from input until either:
  14.          A newline is found, return 1
  15.          or the stream hits the end, return 0
  16.       - If numbers start getting popped before a newline is reached, this means that the input must have
  17.          been malformed. In this case, the fact that this function 'eats' the characters means that the validation checks
  18.          will pick up on the missing 'eaten' line, ensuring that invalid input will be caught.
  19.      
  20.    BubbleSort: -Accepts an area of memory with cards in, ending in a null terminator
  21.       (Fairly standard bubble sort algorithm)
  22.       Do until you can loop once through the data without swapping any elements:
  23.          Loop through the data from the first element to 2 before the null terminator:
  24.             If the next element if larger than the current element:
  25.                Swap the 2 elements around
  26.                Set Swapped to true
  27.          if Swapped is false return from the function
  28.      
  29.    PlayRound: -Accepts an index for the current card in play for both players
  30.       If any exit conditions are hit, the function will return FALSE after printing the outcome, else a TRUE is returned
  31.      
  32.       Check if it's a draw (Both players on null terminator)
  33.          Print "It's a draw!" return false
  34.          
  35.       Check if player one wins (Player 2 has hit null terminator or player one's current card is higher than player two's)
  36.          Print "Player one wins!" return false
  37.          
  38.       Check if player two wins (Player 1 has hit null terminator or player two's current card is higher than player one's)
  39.          Print "Player two wins!" return false
  40.          
  41.       If the function hasn't finished yet, then return true
  42.      
  43.    main:
  44.    
  45.       Load player one's cards
  46.       Load player two's cards
  47.       
  48.       While Playround returns true
  49.          Increment the value passed to Playround
  50. */
  51.  
  52. #include <stdio.h>
  53.  
  54. #define TRUE 1
  55. #define FALSE 0
  56.  
  57. int PlayerOne_Cards[11]; /* Can only have 10 cards, so the 11th */
  58. int PlayerTwo_Cards[11]; /*  element serves as a null-terminator */
  59.  
  60. void Error(char* Message) /*Print an error message then exit */
  61. {
  62.    fprintf(stderr, "\n Error: %s",Message);
  63.    exit(-1);
  64. }
  65.  
  66. /* Consume characters from stdin until a newline is found, then return TRUE
  67.       if no newline is found before the end of the string return FALSE    */
  68. int CheckNewLine()
  69. {
  70.    while (getc(stdin) != '\n')
  71.       if (feof(stdin))
  72.          return FALSE;
  73.    return TRUE;
  74. }
  75.  
  76. /* Reads in the number of cards, then the cards themselves.
  77.    Stores the card numbers (sorted highest to low) in the
  78.     memory area pointed to by 'HandPointer' with a trailing zero to indicate the end*/
  79.     /* If CheckLastNewLine is true, then the program will pop chars from StdIn until a new line is hit */
  80. void ReadCards(int* HandPointer, char CheckLastNewLine)
  81. {
  82.    int NumberOfCards = 0;
  83.    
  84.    memset(HandPointer, 0, 11); /* Clear out the block of memory, so it's ready for cards */
  85.    
  86.    /* Read in the quantity of cards and check if valid integer. */
  87.    /* If the program couldn't read an int, or the end of stream is reached, exit. */
  88.    if (!scanf("%d", &NumberOfCards) || feof(stdin) || !CheckNewLine())
  89.       Error("Invalid input");
  90.    
  91.    if (NumberOfCards < 2 || NumberOfCards > 10)
  92.       Error("Wrong number of cards (Should be between 2 & 10)");
  93.    
  94.    for (int CardIndex = 0; CardIndex < NumberOfCards; CardIndex++)
  95.    {
  96.       /* If there isn't as many cards as expected or the card numbers are non-integer */
  97.       if (scanf("%d", &HandPointer[CardIndex]) == 0)
  98.          Error("Invalid input");
  99.          
  100.       /* If the card is out of range */
  101.       if (HandPointer[CardIndex] < 1 || HandPointer[CardIndex] > 10)
  102.          Error("No such card");
  103.    }
  104.    
  105.    if (CheckLastNewLine && !CheckNewLine())
  106.       Error("Invalid input");
  107.    
  108.    /* Sort descending */
  109.    BubbleSort(HandPointer);
  110. }
  111.  
  112. /* Sort cards descending */
  113. void BubbleSort(int* HandPointer)
  114. {
  115.    int Temp;
  116.    char Swapped = FALSE;
  117.    
  118.    /* Standard bubble-sort algorithm. Loop until one full iteration of the
  119.          data can be performed without a single swap occuring     */
  120.    do
  121.    {
  122.       Swapped = FALSE;
  123.       for (int I = 0; HandPointer[I+1] != 0; I++)
  124.       {
  125.          if (HandPointer[I] < HandPointer[I + 1])
  126.          {
  127.             Temp = HandPointer[I];
  128.             HandPointer[I] = HandPointer[I+1];
  129.             HandPointer[I+1] = Temp;
  130.             Swapped = TRUE;
  131.          }
  132.       }
  133.    } while (Swapped);
  134. }
  135.  
  136.  
  137. /* Plays a round. Either returns FALSE and anounces the game outcome or silently returns TRUE. */
  138. /* Index indicates the players cards to compare. Cards at [0] are the players highest cards
  139.       while cards just before the null terminator are the players lowest value cards    */
  140. int PlayRound(int Index)
  141. {
  142.    
  143.    if (PlayerOne_Cards[Index] == 0 && PlayerTwo_Cards[Index] == 0)
  144.       printf("It's a draw!");     /* Both players have run out of cards */
  145.      
  146.    else /* Check to see that both players have an equal matching high card in play */
  147.    {
  148.       if (PlayerOne_Cards[Index] > PlayerTwo_Cards[Index])
  149.          printf("Player One Wins!");
  150.       else if (PlayerOne_Cards[Index] < PlayerTwo_Cards[Index])
  151.          printf("Player Two Wins!");
  152.       else
  153.          return TRUE; /* Game continues */
  154.    }
  155.    return FALSE; /* Outcome has been printed, end game */
  156. }
  157.  
  158. int main( void )
  159. {
  160.    /* Read the player's cards in from stdin */
  161.    ReadCards(&PlayerOne_Cards, TRUE);
  162.    ReadCards(&PlayerTwo_Cards, FALSE);
  163.    
  164.    /* Repeats until PlayRound returns FALSE indicating a game over */
  165.    for (int I = 0; PlayRound(I); I++);
  166.    
  167.    return 0;
  168. }