#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    8
    Rep Power
    0

    Question Regarding Two-Dimensional Arrays in Functions


    So, I have a question regarding two-dimensional arrays and changing their content inside of functions. I am currently making a program that will generate a random 2-dimensional array (which we've learned in my intro class is an array of pointers), populate the cells with either a blank space, a gold piece, or a pit, and there will be a player occupying one of the cells that the user will be able to move around and either pick up gold pieces or fall into pits. I have a good chunk of the program completed thus far, and I am currently making a function that will move the player's location upward one cell (I'm not worrying about collecting any pieces or falling in pits yet, I'm just trying to move the player piece). Problem is, I'm having trouble with the syntax of using 2-dimensional arrays in functions. I'll show what my program looks like so far; the main things I need help with are the prototype for the movePlayerUp function, the syntax for calling that function in the main function, and then the function movePlayerUp itself. I've been playing around with a few things, but I keep getting a "Segmentation fault (core dumped)" error when I compile. I'm in an intro C programming course using a gcc compiler connected to a Linux server, so while I appreciate any feedback I may receive, please keep answers simple. Thanks for any help you have to offer, it is much appreciated.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    
    /*Structure for player's character info.*/
    struct playerInfo
    {
            char name[25];
            int lives;
            int goldCollected;
            int xLocation;
            int yLocation;
    };
    
    /*Function prototypes*/
    void initializePlayer(struct playerInfo * character);
    void printPlayer(struct playerInfo character);
    void printBoard(char **gameBoard, int gameBoardSize);
    char gatherMoveInput();
    void movePlayerUp(char ***gameBoard, int gameBoardSize);
    
    /*Main function*/
    int main(void)
    {
            printf("A 20 x 20 game\n");
            printf("board will be randomly generated, which will be\n");
            printf("populated with blank rooms, rooms with gold, and\n");
            printf("rooms with a pit. Gold has a .10 chance of appearing\n");
            printf("and pits have a .20 chance of appearing, with blank\n");
            printf("spaces being the default. The player will be prompted\n");
            printf("to name their character and the character will be placed\n");
            printf("at the bottom-left corner of the game board. The player's\n");
            printf("life count will be randomly generated and will be a\n");
            printf("value between 1 and 50, and their gold amount will\n");
            printf("start out at zero. The program will print the player's\n");
            printf("character starting info and the game board that was\n");
            printf("generated. To save space on the game board, the player\n");
            printf("will be represented by 'X', gold will be represented\n");
            printf("by 'G', and pits will be represented by 'P'.\n");
    
            /*Seeding the random number generator with time.*/
            srand(time(NULL));
    
            /*Declaring the structure and calling the initialize function.*/
            struct playerInfo character;
            initializePlayer(&character);
    
            /*Variable declarations.*/
            int gameBoardSize=20;
            char **gameBoard;
    
            /*Keep getting a "segmentation fault, core dump" error that
            I wasn't able to fix, so I am allocating memory for my game
            board in main and will be filling its room contents here as
            well.*/
    
            int i,j,k;
    
            /*Here, we are dynamically allocating memory for our 2d array,
            the game board, of size 20x20 with the use of calloc.*/
            gameBoard = calloc(gameBoardSize, sizeof(char *));
            for(i=0; i<gameBoardSize; ++i)
                    gameBoard[i] = calloc(gameBoardSize, sizeof(char));
    
            int percentChanceGold;
            int percentChancePit;
    
            /*Filling the game board with either a blank space, gold, or a
            pit. The chances of having gold in a room is 10% while the chance
            of having a pit is 20%. Since a room cannot have both gold and
            a pit, if the number generator has a result as such, the placement
            of gold takes priority of a pit.*/
            for(j=0; j<gameBoardSize; ++j)
                    for(k=0; k<gameBoardSize; ++k)
                    {
                            if(j==(gameBoardSize-1)&&k==0)
                            {
                                    gameBoard[j][k]='X';
                            }
                            else
                            {
                                    percentChanceGold=rand()%101;
                                    percentChancePit=rand()%101;
    
                                    if(percentChanceGold>=90&&percentChancePit<80)
                                    {
                                            gameBoard[j][k]='G';
                                    }
                                    else if(percentChanceGold<90&&percentChancePit>=80)
                                    {
                                            gameBoard[j][k]='P';
                                    }
                                    else if(percentChanceGold>=90&&percentChancePit>=80)
                                    {
                                            gameBoard[j][k]='G';
                                    }
                                    else
                                    {
                                            gameBoard[j][k]='_';
                                    }
                            }
                    }
    
            printPlayer(character);
            printBoard(gameBoard,gameBoardSize);
    
            printf("\nNow, the program will ask you for a character input.\n");
            printf("To move your character up, type a 'k' or 'K'.\n");
            printf("To move your character down, type a 'j' or 'J'.\n");
            printf("To move your character left, type a 'h' or 'H'.\n");
            printf("To move your character right, type a 'l' or 'L'\n");
            printf("If you wish to exit the program, enter a 'q' or 'Q'\n");
            printf("As your character moves, the coordinate position will\n");
            printf("change. If you pass over a gold piece, it will be collected\n");
            printf("and added to your total gold count. If you move over a pit,\n");
            printf("your life will decrease by 10, and if your life count reaches\n");
            printf("zero, the program exits.\n");
    
            /*Entering infinite loop*/
            for( ; ; )
            {
                    /*Calling on a function which will prompt the user for a
                    character input value. The program specifies we return this
                    input back to the main, which will then be read and the
                    program execution will be determined based on what the user
                    inputted in the function prompt.*/
                    char inputInMain = gatherMoveInput();
                    printf("\nYou requested the character '%c'\n", inputInMain);
    
                    /*If the user enters a 'q' or 'Q' character, the program will
                    return their info through the use of the printPlayer() function,
                    and the infinite loop will break (ending the program for good).*/
                    if(inputInMain=='q'||inputInMain=='Q')
                    {
                            printf("\nYou've elected to end the program!\n");
                            printf("Your character's final info is:");
                            printPlayer(character);
                            printf("\n\n");
                            break;
                    }
    
                    /*The user want their character to go up on the board by entering
                    a 'k' or 'K' character.*/
                    else if(inputInMain=='k'||inputInMain=='K')
                    {
                            printf("\nYour character has moved up one space.\n");
                            movePlayerUp(&gameBoard,gameBoardSize);
                            printPlayer(character);
                           printPlayer(character);
                            printBoard(gameBoard,gameBoardSize);
                    }
    
                    /*The user want their character to go down  on the board by entering
                    a 'j' or 'J' character.*/
                    else if(inputInMain=='j'||inputInMain=='J')
                    {
                            printf("\nYour character has moved down one space.\n");
                            printPlayer(character);
                            printBoard(gameBoard,gameBoardSize);
                    }
    
                    /*The user want their character to go left on the board by entering
                    a 'h' or 'H' character.*/
                    else if(inputInMain=='h'||inputInMain=='H')
                    {
                            printf("\nYour character has moved left one space.\n");
                            printPlayer(character);
                            printBoard(gameBoard,gameBoardSize);
                    }
    
                    /*The user want their character to go right on the board by entering
                    a 'l' or 'l' character.*/
                    else if(inputInMain=='l'||inputInMain=='L')
                    {
                            printf("\nYour character has moved right one space.\n");
                            printPlayer(character);
                            printBoard(gameBoard,gameBoardSize);
                    }
    
                    /*The user has inputted an invalid character, do nothing.*/
                    else
                    {
                            printf("\nYour entry was invalid, nothing will happen.\n");
                    }
    
            }
            return 0;
    }
    void movePlayerUp(char ***gameBoard, int gameBoardSize)
    {
            int j,k;
            int *previousRowLocation;
            int *previousColumnLocation;
    
            for(j=0; j<gameBoardSize; ++j)
                    {
                            for(k=0; k<gameBoardSize; ++k)
                            {
                                    if(*gameBoard[j][k]=='X')
                                    {
                                            previousRowLocation=&j;
                                            previousColumnLocation=&k;
                                            break;
                                    }
                                    break;
                            }
                            break;
                    }
    
            *gameBoard[*previousRowLocation][*previousColumnLocation]='_';
            *gameBoard[(*previousRowLocation-1)][*previousColumnLocation]='X';
    }
    
    /*Simple function that prompts user for character input and returns that
    input to the main function to be evaluated.*/
    char gatherMoveInput()
    {
            char moveInput;
            printf("\nPlease enter a single character to indicate a move.\n");
            printf("Remember, you can always enter 'q' or 'Q' to quit.\n");
            scanf(" %c", &moveInput);
            return moveInput;
    }
    /*Function that initializes player information.*/
    void initializePlayer(struct playerInfo * character)
    {
            srand(time(NULL));
    
            printf("\nWhat would you like your character's name to be?\n");
            printf("We'll stay on a first name basis, just enter first name.\n");
            scanf("%s",(*character).name);
            (*character).goldCollected=0;
            (*character).xLocation=0;
            (*character).yLocation=0;
            (*character).lives=rand()%50+1;
    }
    
    /*Function that prints player's data.*/
    void printPlayer(struct playerInfo character)
    {
            int i;
    
            printf("\n\nYour character's name is: %s",character.name);
            printf("\nThe amount of gold you've collected so far is: %d", character.goldCollected);
            printf("\nThe amount of lives you have left is: %d", character.lives);
            printf("\nYour player is located at coordinates (%d,%d)", character.xLocation, character.yLocation);
    }
    
    /*Function that prints the game board for the user.*/
    void printBoard(char **gameBoard, int gameBoardSize)
    {
            int m,n;
    
            /*The use of '____' and '|' isn't necessary, but I find that it helps clean up
            the output a bit and lets the user better see the game board and room contents.*/
            printf("\n_________________________________________________________________________________________________________________________\n");
            for(m=0; m<gameBoardSize; ++m)
            {
                    for(n=0; n<gameBoardSize; ++n)
                            printf("|__%c__", gameBoard[m][n]);
                    printf("|\n");
            }
            printf("\n");
    }
  2. #2
  3. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,931
    Rep Power
    481
    Using the debugger:

    $ # compile with symbols
    $ gcc -Wall -g -o the_program the_program.c
    $ # start gdb
    $ gdb the_program
    ...set a breakpoint
    (gdb) b movePlayerUp
    ...run
    (gdb) r
    ...step a few times
    (gdb) s
    (gdb) s
    (gdb) s
    (gdb) p (*gameBoard)[0][0]
    $1 = 95 '_'
    ...quit
    (gdb) q


    We learn that the character is underscore.
    We broke out of the loops before initializing either of
    previousRowLocation or previousColumnLocation
    We expect dramatic failure.


    I'll eat pie and ice cream now, let someone else explain
    • order of operation: operator precedence
      (*gameBoard)[i][j] is not the same as
      *gameBoard[i][j]
    • Un-necessary indirections
      Code:
      void movePlayerUp(char**gameBoard, int gameBoardSize) {
        /* something like this */
        int j,k;
        int previousRowLocation;
        int previousColumnLocation;
        int finished = 0;
        for(j=0; (! finished) && (j<gameBoardSize); ++j) {
          for(k=0; (! finished) && (k<gameBoardSize); ++k) {
            if(gameBoard[j][k]=='X') {
      	previousRowLocation=j;
      	previousColumnLocation=k;
      	finished = 1;
            }
          }
        }
        gameBoard[previousRowLocation][previousColumnLocation]='_';
        gameBoard[previousRowLocation-1][previousColumnLocation]='X';
      }
    • Restoring pit if the prior location was a pit;
    • Making sure that previousRowLocation - 1 remains in the array bounds

    You are doing well, BiColorLobster.
    Last edited by b49P23TIvg; December 1st, 2013 at 08:51 PM.
    [code]Code tags[/code] are essential for python code and Makefiles!

IMN logo majestic logo threadwatch logo seochat tools logo