0

I've been trying to figure out the "move" function for a whole day and I can't pass this problem. When I try to move an element that is in a different line everything is fine but when I try to move an element that is in a different row it just disappears and my codes for both lines and rows are identical. Any tips?

The whole code:

/**
 * 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

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

// 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 d*d - 1
 * (i.e., fills 2D array with values but does not actually print them).  
 */
void init(void)
{
    for(int i = 0; i < d; i++)
    {
        for(int j = 0; j < d; j++)
        {
            board[i][j] = d * d - (d * i + j) - 1;
        }
    }

    if(d % 2 == 0)
    {
        int swap = board[d - 1][d - 2];
        board[d - 1][d - 2] = board[d - 1][d - 3];
        board[d - 1][d - 3] = swap;
    }
}

/**
 * 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("%c", board[i][j] - 2);
            }
            else
            {
                printf("%2d", board[i][j]);
                printf(" ");
            }
        }
        printf("\n");
    }
}

/**
 * If tile borders empty space, moves tile and returns true, else
 * returns false. 
 */
bool move(int tile)
{
    if(tile < d * d && tile > 0)
    {
        for(int i = 0; i < d; i++)
        {
            for(int j = 0; j < d; j++)
            {
                if(board[i][j] == tile)
                {
                    if(board[i - 1][j] == 0 && i - 1 > -1)
                    {
                        int swap = board[i][j];
                        board[i][j] = board[i - 1][j];
                        board[i - 1][j] = swap;
                        return true;
                    }
                    else if(board[i + 1][j] == 0 && i + 1 < d)
                    {
                        int swap = board[i][j];
                        board[i][j] = board[i + 1][j];
                        board[i + 1][j] = swap;
                        return true;
                    }
                    else if(board[i][j - 1] == 0 && j - 1 > -1)
                    {
                        int swap = board[i][j];
                        board[i][j] = board[i][j - 1];
                        board[i][j - 1] = swap;
                        return true;
                    }
                    else if(board[i][j + 1] == 0 && j + 1 < d)
                    {
                        int swap = board[i][j];
                        board[i][j] = board[i][j + 1];
                        board[i][j + 1] = swap;
                        return true;
                    }
                }
            }
        }
    }

    return false;
}

/**
 * Returns true if game is won (i.e., board is in winning configuration), 
 * else false.
 */
bool won(void)
{
    // TODO
    return false;
}
1

The problem is with your if statements. In certain cases, you are trying to access array values that don't exist. Let's say the value at board[0][0] is 5. Will your first if statement be true?

if (board[i - 1][j] == 0)

If so, you need to find a way to make sure that i - 1 will be a value that is in your array.

10
  • No, I don't think it's that. I changed my code to fic the problem but still the same thing occurs. Here is the code: if(board[i - 1][j] == 0 && i - 1 > -1) else if(board[i + 1][j] == 0 && i + 1 < d) else if(board[i][j - 1] == 0 && j - 1 > -1) else if(board[i][j + 1] == 0 && j + 1 < d) – Petar Petrov Aug 14 '16 at 21:29
  • I editted my last comment, that's just the fixed parts. I also editted my original post, so I hope it becomes even clearer. – Petar Petrov Aug 14 '16 at 21:33
  • Are you sure your other function are correct? When I pasted your code into mine it worked correctly. What exactly is the bug you have in your code? – Ben Aug 14 '16 at 21:42
  • Well for example I input d=3, so the board is drawn. Then I input 1 and the tile doesn't move at all. If I input 3 however(the tile that is over the 0) it moves the way it is supposed to. You can check the first post in this topic to see the whole code of the function and that way be sure that everything else is the same. – Petar Petrov Aug 14 '16 at 21:47
  • Does it say illegal move when you input 1? – Ben Aug 14 '16 at 21:53
0

You assign the value of board [i] [j] == tile to board [i - 1] [j] if proper condition is met, but we swap indexes own array such that if board [i] [ j] = tile and a tile is adjacent zero say board [p] [q], we must swap as you do in your program but also keep track of the board zero by i = p, and j = q.

EDIT: Long ago I did fifteen, and can not remember, I will try to explain: Suppose board [i] [j] is the tile you move ie board [i] [j] = tile, where tile is a valid integer, we can only move about adjacent tiles, if we stop to think, what it is what we compare? . The variables i and j are two numbers any array that forms the board and can only move to a free space, which has its own coordinates within the board, well all that you already know. As I raise the solution is as follows; we compare i and j with the coordinates of the blank tile, with the coordinates themselves, not with the corresponding value. If board [i] [j] = 1 (for example) and board [p] [q] = 0 can think of conditions must comply and q i, j and p (sounds like an IF condition). Swapped board array values, but assign i to p, and j to q The way to address this is by using two global variables, which will serve us to know at all times where this blank tile. This is how I did and I'm afraid not know any other way, it may be helpful or may serve to confuse more, anyway if it does not simply forget it

3
  • I didn't quite understand what you're trying to explain. Can you try one more time? – Petar Petrov Aug 14 '16 at 19:50
  • You can read the edition, I hope you help – MARS Aug 14 '16 at 21:48
  • I don't think that would work in my code. – Petar Petrov Aug 14 '16 at 22:14

You must log in to answer this question.

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