0

the code runs fine when i check it with the provided 3x3.txt file but does not pass check50. the error is

:( 3x3 board, from start try to move tile 2, 4, 5, 6, 7, 8 \ expected "5" character 1 of line 14, not "0" :( 3x3 board, move blank up (tile 3), then try tile 2 \ expected "0" character 5 of line 10, not "2"

here is my code

#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 X 0
#define Y 1

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

// dimensions
int d;

// blanktile position
int blankPos[2];

// 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();

    // blank tile initial postion
    blankPos[X] = d - 1;
    blankPos[Y] = d - 1;

    // 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 n = (d * d) - 1;
    for(int i = 0; i < d; i++) {
        for(int j = 0; j < d; j++) {
            board[i][j] = n;
            n--;
        }
    }

    // swap last two digits if board has odd number of tiles
    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)
{
    for(int i = 0; i < d; i++) {
        for(int j = 0; j < d; j++) {
            if(board[i][j] != 0)
                printf(" %2d |", board[i][j]);
            else
                printf("  _  ");
        }
        printf("\n");
    }
}

/**
 * If tile borders empty space, moves tile and returns true, else
 * returns false. 
 */
bool move(int tile)
{
    int tilePos[2];


    //find tile position            
    for(int i = 0; i < d; i++)
        for(int j = 0; j < d; j++)
            if(board[i][j] == tile) {
                tilePos[X] = i;
                tilePos[Y] = j;
            }

    // check if the blank position and tile position are adjacent 
    bool xMove = (abs(blankPos[X] - tilePos[X]) == 1); 
    bool yMove = (abs(blankPos[Y] - tilePos[Y]) == 1); 

    // if move is not diognal then proceed 
    if(xMove != yMove) {
        board[blankPos[X]][blankPos[Y]] = tile;
        board[tilePos[X]][tilePos[Y]] = 0;

        // record new blank position coordinates
        blankPos[X] = tilePos[X];
        blankPos[Y] = tilePos[Y];
        return true;
    }

    return false;
}

/**
 * Returns true if game is won (i.e., board is in winning configuration), 
 * else false.
 */
bool won(void)
{
    int prev = -1;

    if(board[d - 1][d - 1] != 0)
        return false;

    for(int i = 0; i < d; i++)
        for(int j = 0; j < d; j++) { 
            if(board[i][j] < prev && board[i][j] != 0) 
                return false;

            prev = board[i][j];
        }

    return true;
}
0

Your move() function is flawed. It will allow a swap between the blank in the lower right corner and the tile that is one row up and all the way to the left, or one row left and all the way up. You need to test whether the blank tile in the lower right can be swapped with any tile on the board.

The logic seems to test whether the blank and target tiles are not in positions that can't be swapped. Wouldn't it be simpler to test that the blank tile is in a valid position to swap? In other words, check if the blank is directly above, below, left, or right of the target?

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

| improve this answer | |

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .