Note: I've found the issue that's causing it to stop working half way and corrected it (error in the move up code) so I now know it's that I've got the order of the array in reverse, so I'm taking out the bits of this post that are no longer relevant (hope that's the right thing to do!)....Here's the remaining part of my original post: I already had some help on this and really thought I'd cracked it, (though I've no idea if the 'won' function works yet). It does let me play it but I've tried running check50 and it says it's not even passing 'init initialises 3x3 board correctly'. I can now see my problem is that I'm not getting the positions of the elements to match the locations of the elements (e.g. board[0][0] reads as [2][2] when I'm tracking the tile and the blank, so I've written all the 'move' code to fit with the reverse positioning. Could this be the init problem? I've tried using ++ and -- in the loops and whichever way I do it it's reversed. I hope this makes sense, I would so appreciate if anyone can help - I'm seriously questioning my abilities to do any of this right now!!! Thank you....
/*
fifteen.c
Computer Science 50
Problem Set 3
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
#define TEST_DIM 9
// board
int board[DIM_MAX][DIM_MAX];
int array2[TEST_DIM][TEST_DIM];
int blank_row;
int blank_col;
int tile_row;
int tile_col;
// dimensions
int d;
// 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;
}
// 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 dd - 1
(i.e., fills 2D array with values but does not actually print them).
*/
void init(void)
//initiate the board to hold between 3 and 9 spaces on each side of the board
{
for (int i = (d-1); i >= 0; i--)
{
for (int j = (d-1); j >= 0; j--)
{
//populate the board with numbers from d-1 to 0 (zero being the blank space)
board[i][j] = (i * d) + j;
//calculate if d is an odd number, and if so swap 2 & 1
if ( d % 2 == 0 )
{
board[0][1] = 2;
board [0][2] = 1;
}
}
}
}
/*
Prints the board in its current state.
*/
void draw(void)
{
//repeat initialisation loop and print results
for (int i = (d-1); i >= 0; i--)
{
for (int j = (d-1); j >= 0; j--)
{
if (board[i][j] == 0)
{
blank_row = i;
blank_col = j;
printf(" _");
printf("%i and %i", i,j);
}
else
{
printf( "%4d", board[i][j]);
}
}
printf("\n\n");
}
}
/*
If tile borders empty space, moves tile and returns true, else
returns false.
*/
bool move(int tile)
{ //declare temp int
int temp;
// Search for position of tile
for (int i = (d-1); i >= 0; i--)
{
for (int j = (d-1); j >= 0; j--)
{
if (board[i][j] == tile)
{
tile = board[i][j];
tile_row = i;
tile_col = j;
printf("%i and %i", i,j);
}
}
}
//check if it can move left
if (tile_col < d-1 && tile_col+1 == blank_col && tile_row == blank_row)
{
temp = board[tile_row][tile_col];
board[tile_row][tile_col] = board[blank_row][blank_col];
board[blank_row][blank_col] = temp;
}
//check if it can move up
if (tile_row < d-1 && tile_row+1 == blank_col && tile_col == blank_col)
{
temp = board[tile_row][tile_col];
board[tile_row][tile_col] = board[blank_row][blank_col];
board[blank_row][blank_col] = temp;
}
//check if it can move right and if so, move
if (tile_col > 0 && tile_col-1 == blank_col && tile_row == blank_row)
{
temp = board[tile_row][tile_col];
board[tile_row][tile_col] = board[blank_row][blank_col];
board[blank_row][blank_col] = temp;
}
//check if it can move down and if so, move
if (tile_row > 0 && tile_row-1 == blank_row && tile_col == blank_col)
{
temp = board[tile_row][tile_col];
board[tile_row][tile_col] = board[blank_row][blank_col];
board[blank_row][blank_col] = temp;
}
return true;
}
/*
Returns true if game is won (i.e., board is in winning configuration),
else false.
*/
bool won(void)
{
for (int i = 0; i < d-1; i++)
{
for (int j = 0; j < d-1; j++)
{
//populate the board with numbers from d-1 to 0
array2[i][j] = (i * d) + j;
}
}
for(int row = 0; row < d; row++)
{
for(int column = 0; column < d; column++)
{
if(board[row][column] > array2[row+1][column+1])
{
return false;
}
}
}
return true;
}