-1

I have a program that I have been working on all day. The program freezes more times then it doesn't freeze....when it doesn't freeze it works fine and looks like this... http://picpaste.com/Multidimensional_Array-KfdKSmoE.bmp

When it does hang up upon opening it will look something like this... http://picpaste.com/Multidimensional_Array_hung-Jcmz0rQP.bmp

// Chapter 8 Programming Project #9

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

#define SIZE 10
#define PATH_SIZE 25
#define ROW_SIZE ((int) (sizeof(board) / sizeof(board[0])))

int main(void)
{
    char board[SIZE][SIZE] = {};
    // 0 = Up, 1 = Down, 2 = Left, 3 = Right
    unsigned short i = 0, x, y;
    // Generate a random number
    srand((unsigned) time(NULL));
    int dir = rand() % 4;
    // Set all positions of board to '.'
    for (x = 0; x < ROW_SIZE; x++) {
        for (y = 0; y < ROW_SIZE; y++)
            board[x][y] = '.';
    }
    x = 0;
    y = 0;
    board[0][0] = 'A';
    // Generate the path
    while (i != PATH_SIZE) {
        for (i = 0; i < PATH_SIZE;) {
            // Check the direction and replace that char
            switch (dir) {
                case 0: if ((y - 1) >= 0 && (y - 1) < ROW_SIZE
                            && board[x][y - 1] == '.') {
                    board[x][--y] = i + 'B';
                    ++i;
                } break;
                case 1: if ((y + 1) >= 0 &&(y + 1) < ROW_SIZE
                            && board[x][y + 1] == '.') {
                    board[x][++y] = i + 'B';
                    ++i;
                } break;
                case 2: if ((x - 1) >= 0 && (x - 1) < ROW_SIZE
                            && board[x - 1][y] == '.') {
                    board[--x][y] = i + 'B';
                    ++i;
                } break;
                case 3: if ((x + 1) >= 0 && (x + 1) < ROW_SIZE
                            && board[x + 1][y] == '.') {
                    board[++x][y] = i + 'B';
                    ++i;
                } break;
            }
        // Reset the random direction
        dir = rand() % 4;
        }
    }
    // Print the board
    for (x = 0; x < ROW_SIZE; x++) {
        for (y = 0; y < ROW_SIZE; y++)
            printf("%c ", board[x][y]);
        printf("\n");
    }

    return 0;
}
Tom Fenech
  • 72,334
  • 12
  • 107
  • 141
John Conner
  • 233
  • 1
  • 4
  • 18
  • 2
    This is a very sad story. Please read http://ericlippert.com/category/debugging/ – hivert Mar 11 '14 at 09:33
  • Your functional logic is flawed. You never adjust y or x in the cases where the spot is already filled. They can gravitate to a spot that is "surrounded" by a filled slot, and then they will never move and thus never leave their permanent home. That it works "sometimes" is literally random chance. The aroma of Y in an XY problem is almost overpowering. *What is it you're trying to do* ? – WhozCraig Mar 11 '14 at 09:33
  • To infinite loop if you've been a dead end. – BLUEPIXY Mar 11 '14 at 09:34
  • If you want an example of what I'm talking about, consider the initial starting point of x=y=0. It should be marked Now imagine the following sequence of rolls. 3 1 2 0. Where are you on the board? Back at 0.0 with the only two spots you can move to already filled. You will never move to them, and thus never move, and thus never increment `i` and never leave your loop. – WhozCraig Mar 11 '14 at 09:38
  • 1
    There are occasions when none of 'if's in the four cases in your switch statement hold..so your variable i never gets incremented, so you are looping infinitely. Do your for loops properly and you'll avoid this kind of mistake. – user1666959 Mar 11 '14 at 09:38
  • @user1666959 `int x = y % 4` will always generate something where x has range 0-3. – Asthor Mar 11 '14 at 09:43
  • Read my answer again: I didnt say the switch doesnt have a default...you are only incrementing i when the 'if' condition holds in one of the cases. Extend your 'if's in the switch with an else branch and print out "i is not incremented"...you will see why you loop. – user1666959 Mar 11 '14 at 10:01
  • @user1666959 That doesn't solve his issue, he doesn't want to increment the i if he doesn't move. Then he could get a 1 step path even if there were options available. His issue is getting to spots where he can't move and at that point not breaking the loop (or checking so he can't ever get in a spot where he doesn't get stuck but thats a bit more code). – Asthor Mar 11 '14 at 10:07
  • http://pastebin.com/nwnZP1ET is a semi-fixed version that keeps it from getting stuck in a corner but it still freezes about once ever 12 times I run the program...I honestly don't understand why it still freezes...although only once ever 6-12 times the app is ran – John Conner Mar 11 '14 at 10:08
  • @user3404748 Please do look at the debug post.Just printing the board after each loop of the for loop will probably get you a good hint on why it is getting into an forever loop. Print as much as you can. – Asthor Mar 11 '14 at 10:15
  • Alright thanks Asthor, I overlooked that...I'll check into that now – John Conner Mar 11 '14 at 10:17

2 Answers2

2

This will hang when there are no possible directions to move. Taking a simple example of your board with 4 by 4. Initially the board would be like

....
....
....
....

Initial position marked

A...
....
....
....

I make the first move, say I move RIGHT

AB..
....
....
....

I make the next move, say I move DOWN

AB..
.C..
....
....

I make the next move, say I move DOWN

AB..
.C..
.D..
....

I make the next move, say I move LEFT

AB..
.C..
ED..
....

I make the next move, say I move UP

AB..
FC..
ED..
....

And I am stuck, and I do not have any possible locations to move. Now a few more additions would fix your problem.

  1. Add a method to calculate the list of possible moving directions
  2. If no more moves are possible, exit the program

Hint

void calc_poss_dirs()
{
        int dir;

        poss_dir.count = 0;

        for (dir = UP; dir <= RIGHT; dir++) {
                if (can_move(dir)) {
                        poss_dir.dirs[poss_dir.count] = dir;
                        poss_dir.count++;
                }
        }
}
int can_move(int dir)
{
        int x = cur_x;
        int y = cur_y;

        if (dir == UP)
                x--;
        else if (dir == DOWN)
                x++;
        else if (dir == LEFT)
                y--;
        else
                y++;

        if (!in_area(x, y))
                return 0;

        if (visited(x, y))
                return 0;

        return 1;
}
Sakthi Kumar
  • 3,047
  • 15
  • 28
  • Alright thanks I will see what I can do, I actually had something to that effect before but somewhere along the line removed it for who knows why anyway http://pastebin.com/nwnZP1ET is a modified version I got working but it still freezes about once every 12 times I run it – John Conner Mar 11 '14 at 10:05
0

Thanks Sakthi Kumar your input was invaluable as was the rest of all you who helped I appreciate it, the working code is below :)

    // Chapter 8 Programming Project #9

    #include <stdio.h>
    #include <stdbool.h>
    #include <stdlib.h>
    #include <time.h>

    #define SIZE 10
    #define PATH_SIZE 25
    #define ROW_SIZE ((int) (sizeof(board) / sizeof(board[0])))

    int main(void)
    {
        char board[SIZE][SIZE];
        // 0 = Up, 1 = Down, 2 = Left, 3 = Right
        unsigned short i = 0, x, y;
        // Generate a random number
        srand((unsigned) time(NULL));
        int dir = rand() % 4;
        // Set all positions of board to '.'
        for (x = 0; x < ROW_SIZE; x++) {
            for (y = 0; y < ROW_SIZE; y++)
                board[x][y] = '.';
        }
        x = 0;
        y = 0;
        board[0][0] = 'A';
        // Generate the path
        for (i = 0; i < PATH_SIZE;) {
                // Check that the last character has not been cornered
            if ((board[x][y - 1] != '.' || y - 1 < 0) &&
                (board[x][y + 1] != '.' || y + 1 > ROW_SIZE) &&
                (board[x - 1][y] != '.' || x - 1 < 0) &&
                (board[x + 1][y] != '.' || x + 1 > ROW_SIZE))
                break;
            // Check the direction and replace that char
            switch (dir) {
                case 0: if ((y - 1) >= 0
                            && board[x][y - 1] == '.') {
                            board[x][--y] = i + 'B';
                            ++i;
                        } break;
                case 1: if ((y + 1) < ROW_SIZE
                            && board[x][y + 1] == '.') {
                            board[x][++y] = i + 'B';
                            ++i;
                        } break;
                case 2: if ((x - 1) >= 0
                            && board[x - 1][y] == '.') {
                            board[--x][y] = i + 'B';
                            ++i;
                        } break;
                case 3: if ((x + 1) < ROW_SIZE
                            && board[x + 1][y] == '.') {
                            board[++x][y] = i + 'B';
                            ++i;
                        } break;
                default: if (board[x][y] == '.')
                             board[x][y] = i + 'B';
                             break;
            }
        // Reset the random directions
        dir = rand() % 4;
        }
        // Print the board
        for (x = 0; x < ROW_SIZE; x++) {
            for (y = 0; y < ROW_SIZE; y++)
                printf("%4c ", board[x][y]);
            printf("\n");
        }

        return 0;
    }
John Conner
  • 233
  • 1
  • 4
  • 18