0

I am in move function of game fifteen pset3. I want to use a variable blank_i to show the position of blank. I have declared it globally (outside the while loop). But the compiler tell me that this variable is UNDECLARED in move function and the "blank_i" I have declared outside while loop is UNUSED.

I can't understand.

Please help me. This is my code.

#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);
void swap(int a, int b);
bool legal(void);
void find(int tile);

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

   int blank_i = d-1;
   int blank_j = 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)
{

    //fill 2d array board with values
    int temp=d*d-1;
    for (int i=0; i<d; i++)
    {
        for (int j=0; j<d; j++)
        {
            board[i][j]=temp;
            temp = temp -1;
        }
    }

    //switch the position of number 1 and 2
    if ((d*d-1)%2 != 0)
    {
        swap(board[d-1][d-2], board[d-1][d-3]);
    }
}

/**
 * Prints the board in its current state.
 */
void draw(void)
{
    // TODO
    for (int i=0; i<d; i++)
    {
        for (int j=0; j<d; j++)
        {
            if (board[i][j] == 0)
            {
                printf(" [ ] ");
            }
            else
                printf(" [%i] ", board[i][j]);
        }
        printf("\n");
    }
}

/**
 * If tile borders empty space, moves tile and returns true, else
 * returns false. 
 */
bool move(int tile)
{
    int tile_i, tile_j;
    //find the tile
    find(tile);

    if (legal())
    {
        int temp_i = tile_i;
        int temp_j = tile_j;
        int temp = board[tile_i][tile_j];
        board[tile_i][tile_j] = board[blank_i][blank_j];
        board[blank_i][blank_j] = temp;
        blank_i = temp_i;
        blank_j = temp_j;
        return true;
    }
    else
        return false;
}

void swap ( int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
}

void find(int tile)
{
    for (int j = 0; j < d; j++)
        {
            if (board[i][j] == tile)
            {
                tile_i = i;
                tile_j = j;
            } 
        }
}

bool legal(void)
{
    if (tile_i > 0 && board[tile_i - 1][tile_j] == 0) 
        return true;
    }
    else if (tile_i <= d-2 && board[tile_i + 1][tile_j] == 0)
    {
        return true;
    }
    else if (tile_j > 0 && board[tile_i][tile_j - 1] == 0) 
    {
        return true;
    }
    else if (tile_j <= d-2 && board[tile_i][tile_j + 1] == 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}
/**
 * Returns true if game is won (i.e., board is in winning configuration), 
 * else false.
 */
bool won(void)
{
    // TODO
    return false;
}

2 Answers 2

1

Actually, you have not defined blank_i as a global variable. It is a local variable, local to main().

A global variable is one that is declared outside of, and before, main and all functions. Here's an example of a simple program with a global that demonstrates the structure:

#include <stdio.h>
int blank_i;

int main()
{
   int x = 1;
   blank_i = 4;
   x = x + blank_i;
}

THis is an overly simplistic example, but in this, blank_i is global, while x is local to main. A common error is to believe that a var that is declared outside a loop, or any other set of curly braces, is global, even though it is still inside of main(). That is not the case. To be global, it has to be outside of everything.

A number of the errors you are seeing all stem from this. You get unused variable errors because a locally declared var inside of main isn't used again in main. Later, that var name, believed to be global, is used in a function, but wasn't declared in that function, so it generates an undeclared variable error, and so on.

You might benefit from a review of class material and a google search for content that explains global variables in c.

Having said that, I'll add this: The use of global variables is generally a bad practice. While there are times when it is exactly the right thing to do, it should only be used as a last resort. Using globals can lead to errors from misuse of the variables (used one way in one function and another way in another), the creation of shadow variables with the same name, and a host of other issues that commonly arise. I don't say that you should never use global vars (there are those that would), but you should have a really good reason for doing so.

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

1

One other issue you'll have to deal with later is your use of swap in this line: swap(board[d-1][d-2], board[d-1][d-3]);

When you pass those values into that function, you're passing copies of those values, not the values themselves. In effect, you're only swapping them in swap, not in init.

To fix this issue, you can either remove the abstraction created by using the function swap and perform that action within init or use pointers to pass the addresses of your respective variables to swap (i.e. pass by reference rather than pass by value).

To understand this idea more, review Week 4 notes starting here: http://cdn.cs50.net/2015/fall/lectures/4/m/notes4m/notes4m.html#swap

While this is not directly what you're asking about, it does relate to how you are using variables in general and will definitely force you to review concepts that are essential to psets moving forward.

1
  • Thank you very much, I have deal with this issue after that. Commented Feb 22, 2016 at 14:28

You must log in to answer this question.

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