CS50

Problem set 3

This one is more complicated than the previous ones, signaling that CS50 is not as simple as I thought T.T. There are 5 files we need to make changes (not create): find.c, generate.c, helpers.c, fifteen.c, and question.txt.

And again, if you are taking the course and still working on this pset, be aware that copying my code for your submission is considered unreasonable academic dishonesty. Please be reminded of this term at the beginning of every problem set in CS50.

Else, help me point out any problem (even smallest) with my code. I find it quite long and not really smart. Thanks in advance!

Let’s start with find.c

#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>

#include "helpers.h"

// maximum amount of hay
const int MAX = 65536;

int main(int argc, string argv[])
{
 // ensure proper usage
 if (argc != 2)
 {
 printf("Usage: ./find needle\n");
 return -1;
 }

// remember needle
 int needle = atoi(argv[1]);

// fill haystack
 int size;
 int haystack[MAX];
 for (size = 0; size < MAX; size++)
 {
 // wait for hay until EOF
 printf("\nhaystack[%i] = ", size);
 int straw = GetInt();
 if (straw == INT_MAX)
 {
 break;
 }
 
 // add hay to stack
 haystack[size] = straw;
 }
 printf("\n");

// sort the haystack
 sort(haystack, size);

// try to find needle in haystack
 if (search(needle, haystack, size))
 {
 printf("\nFound needle in haystack!\n\n");
 return 0;
 }
 else
 {
 printf("\nDidn't find needle in haystack.\n\n");
 return 1;
 }
}

Now, this is generate.c:

#define _XOPEN_SOURCE

#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// constant
#define LIMIT 65536

int main(int argc, string argv[])
{
 // ask user for one or two command-line argument(s)
 if (argc != 2 && argc != 3)
 {
 printf("Usage: generate n [s]\n");
 return 1;
 }

// convert the first command-line argument to an integer (n - the number of integers will be generated)
 int n = atoi(argv[1]);

// convert the second command-line argument (if exists) to the seed (an integer)
 if (argc == 3)
 {
 srand48((long int) atoi(argv[2]));
 }
 else
 {
 srand48((long int) time(NULL));
 }

// generate n integers within the declared limit and with existing seed
 for (int i = 0; i < n; i++)
 {
 printf("%i\n", (int) (drand48() * LIMIT));
 }

// success
 return 0;
}

Next is helpers.c, which took most of the time spent on this pset.

#include <cs50.h>

#include "helpers.h"

#include <stdio.h>
 #include <cs50.h>
 
bool search(int value, int values[], int n) 
{ 
 int first = 0;
 int last = n-1;
 int c = 0;

while (last>=first)
 {
 if ((last-first==0)||(last-first==1))
 {
 if ((value == values[first])||(value == values[last]))
 {
 c = 1;
 break;
 }
 else
 {
 c = 0;
 break;
 }
 }
 else
 {
 int mid = first+((last-first)/2);
 if (value == values[mid])
 {
 c = 1;
 break;
 }
 else
 {
 if (value < values[mid])
 {
 last = mid - 1;
 
 }
 else
 {
 first = mid + 1;
 }
 }
 }
 }

if (c==0)
 return false;
 else
 return true;
}

/**
 * Sorts array of n values.
 */
void sort(int values[], int n)
{
 for (int k=0; k<n; k++)
 {
 for (int i = 0; i < n-1; i++)
 {
 if (values[i] > values[i+1])
 {
 int a = values[i];
 values[i] = values[i+1];
 values[i+1] = a;
 }
 }
 }
}

And finally, this is fifteen.c:

#define _XOPEN_SOURCE 500

#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// constants
#define DIM_MIN 3
#define DIM_MAX 9

// board
int board[DIM_MAX][DIM_MAX];

// dimensions
int d;

//global variables
int x;
int y;

// prototypes
void clear(void);
void greet(void);
void init(void);
void draw(void);
bool move(int tile);
bool won(void);

int main(int argc, string argv[])
{
 // ensure proper usage
 if (argc != 2)
 {
 printf("Usage: fifteen d\n");
 return 1;
 }

// ensure valid dimensions
 d = atoi(argv[1]);
 if (d < DIM_MIN || d > DIM_MAX)
 {
 printf("Board must be between %i x %i and %i x %i, inclusive.\n",
 DIM_MIN, DIM_MIN, DIM_MAX, DIM_MAX);
 return 2;
 }

// open log
 FILE* file = fopen("log.txt", "w");
 if (file == NULL)
 {
 return 3;
 }
 else
 {
 //initially set board[x][y] to be blankspace
 x = (d - 1);
 y = (d - 1);
 }


 // greet user with instructions
 greet();

// initialize the board
 init();

// accept moves until game is won
 while (true)
 {
 // clear the screen
 clear();

// draw the current state of the board
 draw();

// log the current state of the board (for testing)
 for (int i = 0; i < d; i++)
 {
 for (int j = 0; j < d; j++)
 {
 fprintf(file, "%i", board[i][j]);
 if (j < d - 1)
 {
 fprintf(file, "|");
 }
 }
 fprintf(file, "\n");
 }
 fflush(file);

// check for win
 if (won())
 {
 printf("ftw!\n");
 break;
 }

// prompt for move
 printf("Tile to move: ");
 int tile = GetInt();
 
 // quit if user inputs 0 (for testing)
 if (tile == 0)
 {
 break;
 }

// log move (for testing)
 fprintf(file, "%i\n", tile);
 fflush(file);

// move if possible, else report illegality
 if (!move(tile))
 {
 printf("\nIllegal move.\n");
 usleep(500000);
 }

// sleep thread for animation's sake
 usleep(500000);
 }
 
 // close log
 fclose(file);

// success
 return 0;
}

/**
 * Clears screen using ANSI escape sequences.
 */
void clear(void)
{
 printf("\033[2J");
 printf("\033[%d;%dH", 0, 0);
}

/**
 * Greets player.
 */
void greet(void)
{
 clear();
 printf("WELCOME TO GAME OF FIFTEEN\n");
 usleep(2000000);
}

/**
 * Initializes the game's board with tiles numbered 1 through d*d - 1
 * (i.e., fills 2D array with values but does not actually print them). 
 */
void init(void)
{
 int size = d*d;
 //loop to number each row of board
 for (int i=0; i<d; i++)
 {
 //loop to number each column of one row
 for (int j=0; j<d; j++)
 {
 board[i][j] = size - 1;
 size--;
 }
 }
 //swap 1 and 2 in case the dimension is even
 if (d%2==0)
 {
 board[d-1][d-2] = 2;
 board[d-1][d-3] = 1;
 }
}

/**
 * Prints the board in its current state.
 */
void draw(void)
{
 // print the board 
 for (int i=0; i<d; i++)
 {
 for (int j=0; j<d; j++)
 {
 //replace "0" with "_"
 if (board[i][j]==0)
 {
 printf(" _ ");
 }
 //print the rest of the board
 else
 printf("%2d ", board[i][j]);
 }
 printf("\n");
 }
}

/**
 * If tile borders empty space, moves tile and returns true, else
 * returns false. 
 */
bool move(int tile)
{
 // search board for user tile
 // iterate through rows to find tile
 for (int i = 0; i < d; i++) 
 {
 // iterate through columns to find tile
 for (int j = 0; j < d; j++) 
 {
 // if tile exists on the board
 if(tile == board[i][j]) 
 {
 // initialize variable for 0 
 int blankspace = 0; 
 
 // test if tile is adjacent to blankspace
 if (((x == (i - 1)) && (j == y)) || ((x == (i + 1)) && (j == y)) ||
 ((i == x) && (y == (j - 1))) || ((i == x) && (y == (j + 1))))
 {

// swap tile with blankspace if tile is adjacent to blankspace
 board[x][y] = tile;
 board[i][j] = blankspace;
 x=i;
 y=j;

return true;
 } 
 } 
 }
 }
 return false;
}


/**
 * Returns true if game is won (i.e., board is in winning configuration), 
 * else false.
 */
bool won(void)
{
 //declare a counting variable
 int c=0;
 // check if all numbers are in correct order
 for (int i = 0; i < d; i++)
 {
 for (int j = 0; j < d-1; j++)
 {
 //make sure the board displays consecutive numbers and blankspace is at the end of the board
 if ((board[i][j]==board[i][j+1]-1)&&(board[d-1][d-1]==0))
 {
 c=c+1;
 }
 }
 }
 if (c==d*(d-1)-1)
 {
 return true;
 }
 else
 {
 return false; 
 }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s