0
bool won(void)
{
    int counter = 1; // sets counter to 1 (as the [0][0] will start from 1 upwards to d*d-1.)

    for (int i = 0; i < d; i++) // goes over the board to make sure everything is at the value it should be.
    {
        for (int j = 0; j < d; j++)
        {
            if (counter == (d * d) - 1) // && board[d-1][d-1] == 0) // Basically, makes sure the all but one of the tiles are the same. If the last tile is 0 and the rest are the same = victory.
            {
                return true;
            }

            if (board[i][j] == counter) // checks vs the counter then increases counter by 1 for the next round. 
            {
                counter++;
            }
        }
    }

    return false;

Let's say this is a 3x3 board.

In my mind the way I hoped it would work: 1) Counter is at 1, checks with boards [0][0] which should be 1, if it is, increment counter and proceed to [0][1], if its 2=2, proceed further and so on.

I thought it would stop only if the counter finds 8 matches which would only be possible in a an ascending manner.

However, the 3x3 'wins' if the board is at: 1 2 3 4 5 6 _ 7 8

So my solution was to also check whether the last tile is 0 (currently I left it past //. But this just feels wrong and potentially buggy in the real world.

My question is, why on earth does it stop when the counter hits 6? Even though it's checking if the counter is equal to 8 (d*d-1 = 3x3-1)

I'm at a complete loss and have no idea what is wrong with this.

1 Answer 1

0

The logic of the code above is this: Ignoring the 0 tile, if all the other tiles are in order, then the game is won. The 0 could appear anywhere, as long as the others are in sequence.

Although it seems clumsy, verifying that the 0 tile is last would correct it. In fact, you could check that first, before anything else, as it is probably the most common condition of a not-won game.

Also, if 0 appears at any time in the looping, before the last tile, you could immediately return false as the game is not yet won.

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

[EDIT] It isn't "stopping at 6." The won() function is checking the entire array. If all of the non-zero numbers are in order, the won function will return true, no matter where the 0 is in the array. If any of the non-zeros are out of sequence, won() returns false. It isn't quitting early, it simply isn't checking all the conditions required for the win, specifically that 0 is the last array entry.

Want proof? Play with the following code. You should run it with size 3:

#include <stdio.h>
#include <cs50.h>


bool won(void);

void draw(void);

// constants
#define DIM_MIN 3
#define DIM_MAX 9


// dimensions
int d;

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


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;
    }

    bool zip = false;
    int count = 1;
    for(int i=0;i<d;i++)
    {
        for(int j=0;j<d;j++)
        {
            board[i][j] = count++;
            if (board[i][j] == 6 && !zip)
            {
                board[i][j] = 0;
                count--;
                zip=true;
            }
        }
    }

//    board[2][1]=8;
//    board[2][2]=7;

    draw();
    if(won()) printf("YAY, won!\n"); else printf("BOO! lost\n");

}


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

}


/**
 * Returns true if game is won (i.e., board is in winning configuration), 
 * else false.
 */
bool won(void)
{
    int counter = 1; // sets counter to 1 (as the [0][0] will start from 1 upwards to d*d-1.)

    for (int i = 0; i < d; i++) // goes over the board to make sure everything is at the value it should be.
    {
        for (int j = 0; j < d; j++)
        {
            if (counter == (d * d) - 1) // && board[d-1][d-1] == 0) // Basically, makes sure the all but one of the tiles are the same. If the last tile is 0 and the rest are the same = victory.
            {
                printf("won at %i\n",counter);
                return true;
            }

            if (board[i][j] == counter) // checks vs the counter then increases counter by 1 for the next round. 
            {
                counter++;
            }
        }
    }

    return false;
}
2
  • Thanks Cliff, but that doesn't necessarily answer my question as to why the game wins if the counter hits 6 (as per my original post. I did, however, leave out the "is the last tile 0?" check in the comments, as I felt like there was a better way of doing it and that it did, in fact, feel a bit cheap. I was mostly just super curious what the heck was I doing wrong - I did actually submit this assignment with won() checking for 0's position. Cheers for the answer though!
    – Zzeda
    Sep 5, 2016 at 5:16
  • See answer edit.
    – Cliff B
    Sep 5, 2016 at 5:40

You must log in to answer this question.

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