0

Question: What causes this error?!


Terminal Output when running those 2 commands, Always stuck to almost solving them, then Illegal move

  • ./fifteen 3 < ~cs50/pset3/3x3.txt

  • ./fifteen 4 < ~cs50/pset3/4x4.txt


 1 Pos(0,0)  2 Pos(0,1)  3 Pos(0,2)  4 Pos(0,3) 
 5 Pos(1,0)  6 Pos(1,1)  7 Pos(1,2)  8 Pos(1,3) 
 9 Pos(2,0) 10 Pos(2,1) 11 Pos(2,2) 12 Pos(2,3) 
13 Pos(3,0) 14 Pos(3,1) 15 Pos(3,2)  0 Pos(3,3) 
Tile to move: 



X = 3,Y = 3, tileX = 0, tileY = 4198936, Tile = 2147483647
Illegal move.

kazaky999:~/workspace/pset3/fifteen $ check50 2015.fall.pset3.fifteen fifteen.c

:) fifteen.c exists
:) fifteen.c compiles
:( init initializes 3x3 board correctly
   \ expected log.txt to exist
:( init initializes 4x4 board correctly
   \ expected log.txt to exist
:| 3x3 board, move blank up twice
   \ can't check until a frown turns upside down
:| 3x3 board, move blank left twice
   \ can't check until a frown turns upside down
:| 3x3 board, move blank left then right
   \ can't check until a frown turns upside down
:| 3x3 board, move blank up then down
   \ can't check until a frown turns upside down
:| 3x3 board, move up-up-left-down-down-left-up-up-right-down-down-right
 .....

my fifteen.c implementaion


    /***************************************************************************
 * fifteen.c
 *
 * Computer Science 50
 * Problem Set 3
 *
 * Implements The 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;

// subtractor
int sub = 0;


// prototypes
void clear(void);
void greet(void);
void init(void);
void draw(void);
bool move(int tile);
bool won(void);
void findPos(int* x, int* y, int* tileX, int* tileY, int tile);

int main(int argc, char *argv[])
{
    // greet user with instructions
    greet();

    // 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 %d x %d and %d x %d, inclusive.\n",
         DIM_MIN, DIM_MIN, DIM_MAX, DIM_MAX);
        return 2;
    }

    // initialize the board
    init();

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

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

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

        // prompt for move
        printf("Tile to move: ");
        int tile = GetInt();

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

        // sleep thread for animation's sake
        usleep(500000);
    }

    // that's all folks
    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 THE 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)
{
    // Nested Loop to fill 2D board [i][j] (row i, col j) array in Descending values تنازلي  
    for (int j = 0; j < d; j++)
    {    
            int i = (d*d)-1;
            for (int z = 0; z <= d-1 ;i--,z++)
             {        
                board[j][z]= (i)-sub; 
                printf("%2d Pos(%d,%d) ", board[j][z],j,z);              
             }
             // increment the quantity we will subtract   
             sub = sub + d;
             printf("\n");
     }

    // if dimention number is even we have to swipe 1 & 2 if odd no swapping
     if(d%2 == 0)
     {
     int temp = board[d-1][d-2];
     board[d-1][d-2] = board[d-1][d-3];
     board[d-1][d-3] = temp;
    // printf("\n %2d  %2d \n", board[d-1][d-3], board[d-1][d-2]);              
     }        

    // Change 0 for dash -
    // TODO
}


/* 
 * Prints the board in its current state.
 */

void
draw(void)
{
    // TODO
    // for each row
    //  for each value in the row
    //      print value and space
    //  print new line
    // order in draw function must mirror the order in init function

    // printf ("%2d", board[i][j])
    // Nested Loop to fill 2D board [i][j] (row i, col j) array in Descending values تنازلي  
    for (int j = 0; j < d; j++)
    {    
            int i = (d*d)-1;
            for (int z = 0; z <= d-1 ;i--,z++)
             {        
                printf("%2d Pos(%d,%d) ", board[j][z],j,z);              
             }
             printf("\n");
     }

}


/* 
 * If tile borders empty space, moves tile and returns true, else
 * returns false. 
 */

bool
move(int tile)
{
    // function to get space position
    int x, y;

    // Search for the tile position in Array
    int tileX, tileY;

    findPos(&x, &y, &tileX, &tileY, tile);

    // Log Helper: Print Current positions
    printf("X = %d,Y = %d, tileX = %d, tileY = %d, Tile = %d",x,y,tileX,tileY,tile);

    // Edit the board array only if the move is legal
    // & the tile is in ajacent place
    if ((x == tileX && y == tileY+1) || (x == tileX && y == tileY-1) 
        || (x == tileX+1 && y == tileY) || (x == tileX-1 && y == tileY)){

    // Edit that (wipe) position
    int temp = board[x][y];
    board[x][y] = board[tileX][tileY];
    board[tileX][tileY] = temp;
    return true;    
    } 
    return false;
}


/*
 * Returns true if game is won (i.e., board is in winning configuration), 
 * else false.
 */

bool
won(void)
{
    // TODO
    // if the tiles are in correct order
    // iterate over the board in nested loop and check the values
    // If we go from top to bottom every number must be greater than lower
    // or you could use a counter variable
    // return true if check is right
    int count = 0;
    for (int j = 0; j < d; j++)
    {    
            int i = (d*d)-1;
            for (int z = 0; z <= d-1 ;i--,z++)
             {        
                if(!board[j][z]== count)
                return false;
             }

             count = count + 1;
     }


    return true;
}

void findPos(int* x, int* y, int* tileX, int* tileY, int tile) {

// iterate over array
    for (int j = 0; j < d; j++)
    {    
            int i = (d*d)-1;
            for (int z = 0; z <= d-1 ;i--,z++)
             {        

                // use linear search

                 if( board[j][z] == 0){
                    // return position
                    *x = j;
                    *y = z;
                }
                else if( board[j][z] == tile){
                    // return position
                    *tileX = j;
                    *tileY = z;
                }

             }
             printf("\n");
     }

}
1

The problem is indeed in won(). Because of all the changes you made to main, I replaced it with the original version (which doesn't need any changes) so that I could isolate the problems.

The won() function has 3 problems. First, it checks the tiles by comparing to the value stored in count. Unfortunately, you initialized it at 0 when it should start at 1.

Next, count is incremented outside of the inner for loop. This means that, assuming it started at 1, it would compare both the first and the second tiles to 1. This guarantees a return false every time.

Third, once the first two problems are fixed, when it gets to board[d-1][d-1] it needs to deal with that tile being 0. If you compare this tile (bottom right) to check, it will fail because it is supposed to be 0, not d*d.

Fix these issues and it should work, assuming all else is fixed (including main).

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

0

I think the problem might be in won(). Your won function doesn't return true when the board is sorted correctly, because you don't check for 0 in the last place.

The weird numbers in your printout may happen because the log.txt file has ended. Therefore GetInt() can't read an integer and ends up returning MAX_INT (that's the value you see printed out in "tile"). Then, when your function tries to find "tile", it doesn't, and since your tileX and tileY were never initialized, they're not assigned anything in your function, and have garbage values.

You must log in to answer this question.

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