Lyxpudox

pset 3 - Game of Fifteen

Jul 13th, 2016
26
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * fifteen.c
  3.  *
  4.  * Computer Science 50
  5.  * Problem Set 3
  6.  *
  7.  * Implements Game of Fifteen (generalized to d x d).
  8.  *
  9.  * Usage: fifteen d
  10.  *
  11.  * whereby the board's dimensions are to be d x d,
  12.  * where d must be in [DIM_MIN,DIM_MAX]
  13.  *
  14.  * Note that usleep is obsolete, but it offers more granularity than
  15.  * sleep and is simpler to use than nanosleep; `man usleep` for more.
  16.  */
  17.  
  18. #define _XOPEN_SOURCE 500
  19.  
  20. #include <cs50.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <unistd.h>
  24.  
  25. // constants
  26. #define DIM_MIN 3
  27. #define DIM_MAX 9
  28.  
  29. // board
  30. int board[DIM_MAX][DIM_MAX];
  31.  
  32. // dimensions
  33. int d;
  34.  
  35. // prototypes
  36. void clear(void);
  37. void greet(void);
  38. void init(void);
  39. void draw(void);
  40. bool move(int tile);
  41. bool won(void);
  42.  
  43. int main(int argc, string argv[])
  44. {
  45.     // ensure proper usage
  46.     if (argc != 2)
  47.     {
  48.         printf("Usage: fifteen d\n");
  49.         return 1;
  50.     }
  51.  
  52.     // ensure valid dimensions
  53.     d = atoi(argv[1]);
  54.     if (d < DIM_MIN || d > DIM_MAX)
  55.     {
  56.         printf("Board must be between %i x %i and %i x %i, inclusive.\n",
  57.             DIM_MIN, DIM_MIN, DIM_MAX, DIM_MAX);
  58.         return 2;
  59.     }
  60.  
  61.     // open log
  62.     FILE* file = fopen("log.txt", "w");
  63.     if (file == NULL)
  64.     {
  65.         return 3;
  66.     }
  67.  
  68.     // greet user with instructions
  69.     greet();
  70.  
  71.     // initialize the board
  72.     init();
  73.  
  74.     // accept moves until game is won
  75.     while (true)
  76.     {
  77.         // clear the screen
  78.         clear();
  79.  
  80.         // draw the current state of the board
  81.         draw();
  82.  
  83.         // log the current state of the board (for testing)
  84.         for (int i = 0; i < d; i++)
  85.         {
  86.             for (int j = 0; j < d; j++)
  87.             {
  88.                 fprintf(file, "%i", board[i][j]);
  89.                 if (j < d - 1)
  90.                 {
  91.                     fprintf(file, "|");
  92.                 }
  93.             }
  94.             fprintf(file, "\n");
  95.         }
  96.         fflush(file);
  97.  
  98.         // check for win
  99.         if (won())
  100.         {
  101.             printf("ftw!\n");
  102.             break;
  103.         }
  104.  
  105.         // prompt for move
  106.         printf("Tile to move: ");
  107.         int tile = GetInt();
  108.        
  109.         // quit if user inputs 0 (for testing)
  110.         if (tile == 0)
  111.         {
  112.             break;
  113.         }
  114.  
  115.         // log move (for testing)
  116.         fprintf(file, "%i\n", tile);
  117.         fflush(file);
  118.  
  119.         // move if possible, else report illegality
  120.         if (!move(tile))
  121.         {
  122.             printf("\nIllegal move.\n");
  123.             usleep(500000);
  124.         }
  125.  
  126.         // sleep thread for animation's sake
  127.         usleep(500000);
  128.     }
  129.    
  130.     // close log
  131.     fclose(file);
  132.  
  133.     // success
  134.     return 0;
  135. }
  136.  
  137. /**
  138.  * Clears screen using ANSI escape sequences.
  139.  */
  140. void clear(void)
  141. {
  142.     printf("\033[2J");
  143.     printf("\033[%d;%dH", 0, 0);
  144. }
  145.  
  146. /**
  147.  * Greets player.
  148.  */
  149. void greet(void)
  150. {
  151.     clear();
  152.     printf("WELCOME TO GAME OF FIFTEEN\n");
  153.     usleep(2000000);
  154. }
  155.  
  156. /**
  157.  * Initializes the game's board with tiles numbered 1 through d*d - 1
  158.  * (i.e., fills 2D array with values but does not actually print them).  
  159.  */
  160. void init(void)
  161. {
  162.     int count = d * d - 1;
  163.    
  164.     for (int x = 0; x < d; x++) {
  165.        
  166.         for (int y = 0; y < d; y++) {
  167.            
  168.             board[x][y] = count;
  169.             printf("x: %i, y: %i, %i\n", x, y, board[x][y]);
  170.            
  171.             count--;
  172.            
  173.         }
  174.     }
  175.    
  176.     if (d % 2 == 0) {
  177.         int temp = board[d-1][d-3];
  178.         board[d-1][d-3] = board[d-1][d-2];
  179.         board[d-1][d-2] = temp;
  180.     }
  181.    
  182.     printf("\n");
  183.    
  184. }
  185.  
  186. /**
  187.  * Prints the board in its current state.
  188.  */
  189. void draw(void)
  190. {  
  191.     for (int x = 0; x < d; x++) {
  192.         for (int y = 0; y < d; y++) {
  193.             if(board[x][y] != 0) {
  194.                 printf("%*i", 3, board[x][y]);
  195.             } else {
  196.                 printf("%*s", 3, "_");
  197.             }
  198.         }
  199.         printf("\n");
  200.     }
  201. }
  202.  
  203. /**
  204.  * If tile borders empty space, moves tile and returns true, else
  205.  * returns false.
  206.  */
  207. bool move(int tile)
  208. {  
  209.     for (int x = 0; x < d; x++) {
  210.         for (int y = 0; y < d; y++) {
  211.             if(board[x][y] == tile) {
  212.                 if (board[x][y+1] == 0 && y+1 <= d-1) { // right of tile
  213.                     int temp = board[x][y];
  214.                     board[x][y] = board[x][y+1];
  215.                     board[x][y+1] = temp;
  216.                    
  217.                     return true;
  218.                 } else if (board[x][y-1] == 0 && y-1 <= d-1) { // left of tile
  219.                     int temp = board[x][y];
  220.                     board[x][y] = board[x][y-1];
  221.                     board[x][y-1] = temp;
  222.                    
  223.                     return true;                    
  224.                 } else if (board[x-1][y] == 0 && x-1 <= d-1) { // up of tile
  225.                     int temp = board[x][y];
  226.                     board[x][y] = board[x-1][y];
  227.                     board[x-1][y] = temp;
  228.                    
  229.                     return true;              
  230.                 } else if (board[x+1][y] == 0 && x+1 <= d-1) { // bottom of tile
  231.                     int temp = board[x][y];
  232.                     board[x][y] = board[x+1][y];
  233.                     board[x+1][y] = temp;
  234.                    
  235.                     return true;                    
  236.                 }
  237.             }
  238.         }
  239.     }
  240.    
  241.     return false;
  242. }
  243.  
  244. /**
  245.  * Returns true if game is won (i.e., board is in winning configuration),
  246.  * else false.
  247.  */
  248. bool won(void)
  249. {
  250.     int expectedValue = 1;
  251.    
  252.     for (int x = 0; x < d; x++) {
  253.         for (int y = 0; y < d; y++) {
  254.             if(board[x][y] > expectedValue) {
  255.                 return false;
  256.             }
  257.             expectedValue++;
  258.         }
  259.     }
  260.    
  261.     return true;
  262. }
RAW Paste Data