Jump to content
  • Advertisement
Sign in to follow this  
guesst

dynamicly allocating a 2D array

This topic is 3625 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm not a newby, but this has me feeling like one. As long as I have an array with hard coded values I'm fine, but the moment I try to dynamically allocate my array the thing goes tits up. I'm trying to translate the old DOS game "Robotfindskitten" to PDCurses (I know it's been done, but it doesn't work for me), and I get the whole thing to work until I change the line: int screen[80][24]; to int screen[COLS][LINES]; at which point I get the error: error: variable-size type declared outside of any function Okay, so I move the screen variable declaration inside the main function and pass by reference to the only function that needs it. Looks good except for when I run it. Now I'm getting a segfault at the line screen[c][c2] = EMPTY; below: for (c = 0; c <= COLS; c++) { for (c2 = 0; c2 <= LINES; c2++) { screen[c][c2] = EMPTY; } } ...when c=0 and c2=11. What? I feel like I've delt with this before, but I can't figure out how I fixed it. It used to be that you could declare an int** and use that to pass a 2D array, but that seems to be disabled now. What is going on?

Share this post


Link to post
Share on other sites
Advertisement
Here's the code that's segfaulting:

/*robotfindskitten v1600000.150 source code.
*
*Copyright (C) 1997,1999 Leonard Richardson leonardr@segfault.org
*
*
*Note that this is not the source for the compiled program that comes
*with this package (v1600000.200). I don't know where the source for
*that is. I don't even know to what extent this code will compile and
*run, as I no longer use DOS. As far as I'm concerned, this code has
*historical value only.
*
*If you want this to work like the compiled version, look at the binary
*and add the other 50 messages to the array. Also take a look at the problem
*near the end where it says "Here's where the problem is." I don't know
*what the problem is, but if I said there was one, there probably was one.
*/

#include <curses.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define EMPTY -1
#define ROBOT 0
#define KITTEN 1
#define MAXMESSAGES 1000

void instructions();
void draw_robot();
void draw_kitten();
void process_input(int input, int screen[COLS][LINES]);

typedef struct object
{
int x;
int y;
int color;
int character;
} OBJECT;

OBJECT robot;
OBJECT kitten;
OBJECT empty;
OBJECT bogus[MAXMESSAGES];
int bogus_messages[MAXMESSAGES];
char messages[MAXMESSAGES][80];
int used_messages[MAXMESSAGES];
int numbogus;
int nummessages;

int main(int argc, char *argv[])
{
int screen[COLS][LINES];
int supplied_number; /*Number of bogus OBJECTs, supplied on command line. */
int c, c2;
FILE *fp;
/* Do general start-of-program stuff. */

nummessages = 0;
fp = fopen ("messages.txt", "r");
if (fp == NULL)
{
strcpy (messages[nummessages++], "This is not a kitten.");
strcpy (messages[nummessages++], "That's just an old tin can.");
strcpy (messages[nummessages++], "It's an altar to the horse god.");
strcpy (messages[nummessages++], "A mere collection of pixels.");
strcpy (messages[nummessages++], "TA box of fumigation pellets.");
strcpy (messages[nummessages++], "More grist for the mill.");
strcpy (messages[nummessages++], "It's a square.");
strcpy (messages[nummessages++], "Run away! Run away!");
strcpy (messages[nummessages++], "The rothe hits! The rothe hits!");
strcpy (messages[nummessages++], "This place is called Antarctica. There is no kitten here.");
strcpy (messages[nummessages++], "It's a copy of \"Zen and The Art of Robot Maintenance\".");
strcpy (messages[nummessages++], "\"Yes!\" says the bit.");
strcpy (messages[nummessages++], "\"No!\" says the bit.");
strcpy (messages[nummessages++], "A robot comedian. You feel amused.");
strcpy (messages[nummessages++], "A forgotten telephone switchboard.");
strcpy (messages[nummessages++], "It's a desperate' plug for Cymon's Games, http://www.cymonsgames.com/");
strcpy (messages[nummessages++], "The letters O and R.");
strcpy (messages[nummessages++], "\"Blup, blup, blup\" says the mud pot.");
strcpy (messages[nummessages++], "Another rabbit? That's three today!");
strcpy (messages[nummessages++], "Thar's Mobius Dick, the convoluted whale. Arrr!");
strcpy (messages[nummessages++], "This object here appears to be Louis Farrakhan's bow tie.");
strcpy (messages[nummessages++], "...thingy???");
strcpy (messages[nummessages++], "Pumpkin pie spice.");
strcpy (messages[nummessages++], "Chewing gum and baling wire.");
strcpy (messages[nummessages++], "It's the crusty exoskeleton of an arthropod!");
}
else
{
while (fgets (messages[nummessages++], 78, fp))
messages[nummessages - 1][strlen(messages[nummessages - 1]) - 1] = 0;
}
srand(time(NULL));
initscr ();
raw (); noecho(); curs_set(0); nonl(); keypad(stdscr,1);
start_color();
init_pair(0, COLOR_WHITE & A_BOLD, 0); /* for text */
init_pair(1, COLOR_WHITE, 0); /* for robot */
for (c = 2; c < COLORS; c++) init_pair(c, c, COLOR_BLACK);
empty.x = -1;
empty.y = -1;
empty.color = 0;
empty.character = ' ';

if (argc == 1)
{
numbogus = 20;
} else {
supplied_number = atoi(argv[1]);
if (supplied_number < 0 || supplied_number > nummessages)
{
printw ("Error: run-time parameter must be between 0 and %d.", nummessages);
endwin (); exit(0);
} else {
numbogus = supplied_number;
}
}
// screen = malloc(COLS * sizeof (int*));
// for (c = 0; c < COLS; c++) screen[c] = malloc(sizeof (int));

/* Now we have the filling in of the various arrays.
* Create an array to represent the screen so that we can make sure all
* the OBJECTs go on different squares. */
for (c = 0; c <= COLS; c++)
{
for (c2 = 0; c2 <= LINES; c2++)
{
screen[c][c2] = EMPTY;
}
}
/* Create an array to ensure we don't get duplicate messages. */
for (c = 0; c < nummessages; c++)
{
used_messages[c] = 0;
bogus_messages[c] = 0;
bogus[c] = empty;
}

/* Now we initialize the various game OBJECTs.
* Assign a position to the player. */
robot.x = rand() % COLS;
robot.y = rand() % (LINES - 3) + 3;
robot.character = '#';
robot.color = 1;
screen[robot.x][robot.y] = ROBOT;

/* Assign the kitten a unique position. */
do
{
kitten.x = rand() % COLS;
kitten.y = rand() % (LINES - 3) + 3;
} while (screen[kitten.x][kitten.y] != EMPTY);

/* Assign the kitten a character and a color. */
do
{
kitten.character = rand() % 254 + 1;
} while (kitten.character == '#' || kitten.character == ' ');
kitten.color = rand() % (COLORS - 2) + 2;
screen[kitten.x][kitten.y] = KITTEN;

/* Now, initialize non-kitten OBJECTs. */
for (c = 0; c < numbogus; c++)
{
/* Assign a unique position. */
do
{
bogus[c].x = rand() % COLS;
bogus[c].y = rand() % (LINES - 3) + 3;
} while (screen[bogus[c].x][bogus[c].y] != EMPTY);
screen[bogus[c].x][bogus[c].y] = c+2;

/* Assign a character. */
do
{
bogus[c].character = rand() % 254 + 1;
} while (bogus[c].character == '#' || bogus[c].character == ' ');
bogus[c].color = rand() % (COLORS - 2) + 2;;

/* Assign a unique message. */
int index = 0;
do
{
index = rand() % nummessages;
} while (used_messages[index] != 0);
bogus_messages[c] = index;
used_messages[index] = 1;
}

/* Print instructions. */
clear();
instructions();
clear();

/* Put stuff on the screen. */
attrset (COLOR_PAIR(0));
move(0,0);
attron (A_BOLD);
printw ("robotfindskitten v22-july-2008");
move(2,0);
for (c = 0; c < COLS; c++) addch ('_');
attroff (A_BOLD);
move(kitten.y,kitten.x);
draw_kitten();

move (3,0);
for (c = 0; c < numbogus; c++)
{
move(bogus[c].y,bogus[c].x);
attrset (COLOR_PAIR(bogus[c].color));
addch(bogus[c].character|A_ALTCHARSET);
}

move(robot.y,robot.x);
draw_robot();
int old_x = robot.x;
int old_y = robot.y;

/* Now the fun begins. */

int input;
input = getch();
while (tolower(input) != 'q')
{
process_input(input, screen);
/* Redraw robot, where avaliable */
if (!(old_x == robot.x && old_y == robot.y))
{
move(old_y,old_x);
addch(' ');
move(robot.y,robot.x);
draw_robot();
screen[old_x][old_y] = EMPTY;
screen[robot.x][robot.y] = ROBOT;
old_x = robot.x;
old_y = robot.y;
}
input = getch();
}
endwin ();
return 0;
}

/* Given the keyboard input, interprets it. */
void process_input(int input, int screen[COLS][LINES])
{
int check_x = robot.x;
int check_y = robot.y;
int c;

switch (input)
{
case KEY_UP:
check_y--;
break;
case KEY_DOWN:
check_y++;
break;
case KEY_LEFT:
check_x--;
break;
case KEY_RIGHT:
check_x++;
break;
case 0:
break;
default: /* invalid command */
move(1,0);
attrset (COLOR_PAIR(0));
printw("Invalid command: Use direction keys or Press 'Q'."); clrtoeol ();
return;
}

/* Check for going off the edge of the screen. */
if (check_y < 3 || check_y > LINES - 1 || check_x < 0 || check_x > COLS - 1)
{
return;
}

/* Check for collision */
if (screen[check_x][check_y] != EMPTY)
{
switch (screen[check_x][check_y])
{
case ROBOT:
/* We didn't move. */
break;
case KITTEN: /* Found it! */
move(1,0); clrtoeol ();

/* The grand cinema scene. */
for (c = 0; c <=3; c++)
{
move(1, COLS / 2 - 5 + c);
addch(' ');
move(1,COLS / 2 + 4 - c);
addch(' ');
move(1,COLS / 2 - 4 + c);
if (input == KEY_LEFT || input == KEY_UP)
draw_kitten();
else
draw_robot();
move(1,COLS / 2 + 3 - c);
if (input == KEY_LEFT || input == KEY_UP)
draw_robot();
else
draw_kitten();
refresh (); napms (600);
}
/* They're in love! */
move(0,COLS / 2 - 1);
attrset (COLOR_PAIR(COLOR_RED));
addch(3|A_ALTCHARSET);
addch(3|A_ALTCHARSET);
move(0,0);
refresh(); napms (1200);
attrset (COLOR_PAIR(0));
printw ("You found kitten! Way to go, robot!\n");
getch ();
endwin (); exit(0);
break;
default:
move(1,0);
attron (A_BOLD);
printw (messages[bogus_messages[screen[check_x][check_y]-2]]); clrtoeol ();
attroff (A_BOLD);
break;
}
move(2,0);
return;
}
/* Otherwise, move the robot. */
robot.x = check_x;
robot.y = check_y;
}

void instructions()
{
attrset (COLOR_PAIR(0)|A_BOLD);
move(0,0);
printw ("robotfindskitten v22-June-2008\n"
"Originally by the illustrious Leonard Richardson 1997\n"
"Written especially for the Nerth Pork robotfindskitten contest\n"
"ReWritten in PDCurses by Joseph Larson\n"
"especially for Cymon's Games 2008 HTTP://WWW.CYMONSGAMES.COM\n\n"
" In this game, you are robot (");
draw_robot();
attrset (COLOR_PAIR(0)|A_BOLD);
printw ("). Your job is to find kitten. This task\n"
"is complicated by the existance of various things which are not kitten.\n"
"Robot must touch items to determine if they are kitten or not. The game\n"
"ends when robotfindskitten. Alternatively, you may end the game by hitting\n"
"the Esc key. See the documentation for more information.\n\n"
" Press any key to start.\n");
getch();

}

void draw_robot() /* Draws robot at current position */
{
attrset (COLOR_PAIR(robot.color));
addch(robot.character);
}

void draw_kitten() /* Draws kitten at current position */
{
attrset (COLOR_PAIR(kitten.color));
addch(kitten.character|A_ALTCHARSET);
}

Share this post


Link to post
Share on other sites
Hi,

Did you allocate the memory first? Something like this.
int** screen;

screen* = new int*[COLS];
for(int i=0;i<COLS;i++){
screen = new int[LINES];;
}

You get a segmentation fault if you try to access memory which you
did not allocate so it's probably that you did not allocate the
memory first.

Share this post


Link to post
Share on other sites
Quote:

It used to be that you could declare an int** and use that to pass a 2D array, but that seems to be disabled now. What is going on?

You can have an int** and treat it like a 2D array, but you still need to allocate it. It looks like your code is written such that the easier method isn't the quickest solution. That solution is to use a 1D array and access it with 2D semantics, e.g:

int array[width * height];

// accessing element at (x,y)
array[x + y * width];

It saves you a lot of trouble because you can more easily dynamically allocate the array, via malloc(), on one line.

To initialize a 2D array dynamically, you must use a loop:

int i = 0;
int** array = malloc(sizeof(int*) * width);
for(i = 0; i < width; ++i) {
array = malloc(sizeof(int) * height);
}

or equivalent.

You appear to be using C. If you are not using C, and in fact are using C++, you should in fact use std::vector for this.

Share this post


Link to post
Share on other sites
I tried that at one point (You can see the code commented out in the full listing above) but for some reason it didn't work, tho whether it was for the same reason or not i don't know. I think i gave up on that thread before my desperate cry for help. I'll try it like that again tomorrow. me tired tonight. too tired to push shift key.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!