My code for fifteen.c works and solves the test inputs of the 3x3.txt file and the 4x4.txt file. However the check50 fails for the following.
:) fifteen.c exists :) fifteen.c compiles :( init initializes 3x3 board correctly \ expected "5" character 1 of line 2, not "0" :( init initializes 4x4 board correctly \ expected file to be of length 38, not 36
What I have found is that the log.txt file is not matching the my actual board array and that is why check50 is saying my 3x3 doesn't initialize correctly. Here is my code.
Can someone please help me understand why log.txt is not matching my board array?
/**
* fifteen.c
*
* Implements Game of Fifteen (generalized to d x d).
*
* Usage: fifteen d
*
* whereby the board's dimensions are to be d x d,
* where d must be in [DIM_MIN,DIM_MAX]
*
* Note that usleep is obsolete, but it offers more granularity than
* sleep and is simpler to use than nanosleep; `man usleep` for more.
*/
#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];
// Zero (space) location
int zero[2];
// dimensions
int d;
// Functions for Game Play
void clear(void);
void greet(void);
void init(int d, int board[d][d], int zero[2]);
void draw(int d, int board[d][d]);
bool move(int tile, int d, int board[d][d], int zero[2]);
bool won(int d, int board[d][d]);
// Functions to find zero
void zerofind(int d, int board[d][d], int zero[2]);
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;
}
// greet user with instructions
greet();
// initialize the board
init(d, board, zero);
// accept moves until game is won
while (true)
{
// clear the screen
clear();
// draw the current state of the board
draw(d, board);
// 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(d, board))
{
printf("\e[7;4;32;47mCongratulations! You Solved the Puzzle! \e[0m\n");
break;
}
// prompt for move
printf("Tile to move: ");
int tile = get_int();
// log move (for testing)
fprintf(file, "%i\n", tile);
fflush(file);
// move if possible, else report illegality
if (!move(tile, d, board, zero) || tile == 0)
{
printf("\nIllegal move.\n");
usleep(250000); //0.25sec pause
}
// sleep thread for animation's sake
usleep(250000); //0.25sec pause
}
// 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); //2sec pause
}
/**
* Initializes the game's board with tiles numbered 1 through d*d - 1
*/
void init(int d, int board[d][d], int zero[2])
{
// Identifying largest number
int x = d * d - 1;
// Identifying Zero (space) location
zero[0] = d - 1;
zero[1] = d - 1;
// Assigning values to board
for (int i = 0; i < d; i++)
{
for (int j = 0; j < d; j++)
{
board[i][j] = x;
x--;
}
}
// If d is even, switch 1 and 2 to make game solvable
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(int d, int board[d][d])
{
for (int i = 0; i < d; i++)
{
for (int j = 0; j < d; j++)
{
if (board[i][j] == 0)
{
printf("|__");
} else
{
printf("|\e[4m%2i\e[0m", board[i][j]);
}
}
printf("|\n");
}
}
/**
* If tile borders empty space, moves tile and returns true, else
* returns false.
*/
bool move(int tile, int d, int board[d][d], int zero[2])
{
// Finds zero
zerofind(d, board, zero);
// Checks tiles around zero
// Checking space above
if (board[zero[0] - 1][zero[1]] == tile)
{
board[zero[0]][zero[1]] = board[zero[0] - 1][zero[1]];
board[zero[0] - 1][zero[1]] = 0;
return true;
}
// Checking space below
if (board[zero[0] + 1][zero[1]] == tile)
{
board[zero[0]][zero[1]] = board[zero[0] + 1][zero[1]];
board[zero[0] + 1][zero[1]] = 0;
return true;
}
// Checking space right
if (board[zero[0]][zero[1] + 1] == tile)
{
board[zero[0]][zero[1]] = board[zero[0]][zero[1] + 1];
board[zero[0]][zero[1] + 1] = 0;
return true;
}
// Checking space left
if (board[zero[0]][zero[1] - 1] == tile)
{
board[zero[0]][zero[1]] = board[zero[0]][zero[1] - 1];
board[zero[0]][zero[1] - 1] = 0;
return true;
}
// Not Found
return false;
}
/**
* Returns true if game is won (i.e., board is in winning configuration),
* else false.
*/
bool won(int d, int board[d][d])
{
if (board[d - 1][d - 1] != 0)
{
return false;
}
int e = 1;
// Evaluates each element to make sure they are in ascending order.
for (int i = 0; i < d; i++)
{
for (int j = 0; j < d; j++)
{
if (board[i][j] == e)
{
e++;
}
}
}
if (e == d * d)
{
return true;
}
else
{
return false;
}
}
/**
* identifying location of the Zero or Space
*/
void zerofind(int d, int board[d][d], int zero[2])
{
for (int i = 0; i < d; i++)
{
for (int j = 0; j < d; j++)
{
if (board[i][j] == 0)
{
zero[0] = i;
zero[1] = j;
}
}
}
}