Работа со структурами C - PullRequest
0 голосов
/ 16 мая 2018

Я разрабатываю код для небольшого игрового устройства, которое я разработал. Я полностью застрял, пытаясь построить то, что в конечном счете представляет собой График расположения карт.

У меня есть 2 структуры:

typedef struct point {
    int x;
    int y;
} point;


typedef struct location {
    const point portal_in;
    const point portal_out;

    const byte *map;
    const byte width;
    const byte height;

    struct location *portals[8];

    point player;

    struct location *return_to;
} location;

Каждое местоположение имеет список других местоположений, на которые оно ссылается, а также местоположение, на которое оно ссылается.

Я пытался настроить места следующим образом:

location build_locations()
{
    location village = { 
        .portal_in={15, 14}, 
        .portal_out={0, 0}, 
        .map=&VILLAGE[0],
        .width=32,
        .height=16,
        .player={15, 14}, 
        .return_to=0 
    };
    location loc = { 
        .portal_in={8, 7}, 
        .portal_out={11, 10}, 
        .map=&HOUSE[0],
        .width=8,
        .height=8,
        .player={0, 0}, 
        .return_to=&village
    };

    village.portals[0] = &loc;

    return village;
}

это вызывается в моей main() функции:

location current_location = build_locations();

И это работает, вплоть до точки - я могу нарисовать карту village и переместить игрока вокруг нее:

display_map(&current_location);

display_player(&current_location);

и так далее. Проблема возникает, когда я хочу поменяться на новое место.

Если я попытаюсь переназначить current_location, я получу ошибку компилятора с жалобой на assignment to read only variable:

current_location = current_location.portals[0];

Это, пожалуй, самый сложный код, который я написал на C, так что я знаю, что я не в своей тарелке, когда речь идет о структурах и указателях, но я пытаюсь учиться, и я прошел долгий путь уже.

Есть ли лучший способ сделать то, что я пытаюсь сделать? Или я что-то упустил очевидное?

Спасибо

EDIT:

Это самый минимальный пример, который я могу придумать:

typedef unsigned char byte;

static const byte VILLAGE[] = {
      0,   0,   0,   0,  175, 181, 181, 181, 181, 181, 181, 175,   0,   0,   0,   0,
      /// And so on - indices of tiles defined elsewhere but irrelevant here
};

static const byte HOUSE[] = {
      0,   0,   0,   0,  175, 181, 181, 181, 181, 181, 181, 175,   0,   0,   0,   0,
      /// And so on - indices of tiles defined elsewhere but irrelevant here
};

typedef struct point {
    int x;
    int y;
} point;


typedef struct location {
    const point portal_in;
    const point portal_out;

    const byte *map;
    const byte width;
    const byte height;

    struct location *portals[8];

    point player;

    struct location *return_to;
} location; 

location build_locations()
{
    location village = { 
        .portal_in={15, 14}, 
        .portal_out={0, 0}, 
        .map=&VILLAGE[0],
        .width=32,
        .height=16,
        .player={15, 14}, 
        .return_to=0 
    };
    location loc = { 
        .portal_in={8, 7}, 
        .portal_out={11, 10}, 
        .map=&HOUSE[0],
        .width=8,
        .height=8,
        .player={0, 0}, 
        .return_to=&village
    };

    village.portals[0] = &loc;

    return village;
}

int main(void)
{
    location current_location = build_locations();

    if (current_location.player.x == 5 && current_location.player.y == 4)
    {
        current_location = current_location.portals[0];
    }
}

1 Ответ

0 голосов
/ 16 мая 2018

Проблема времени выполнения:

Проблема проста. village и loc находятся в стеке.

при возврате вы получаете копию village, но нет копии для loc. поэтому loc будет выпущен после возвращения. Вы можете использовать такой код для решения вашей проблемы:

village.portals[0] = calloc(1, sizeof(*(village.portals[0])));
memcpy(&village.portals[0], &loc, sizeof(loc)); //->or just assign village.portals[0] directly

Обновление:

Проблема компиляции

Да, комментарии к current_location тоже верны. Вы можете решить это так:

current_location = *(current_location.portals[0]);

или полностью используйте указатели для доступа к данным.

Но просто помните, что проблема времени выполнения, о которой я упоминал, очень важна, и ее очень трудно отследить позже.

Обновление 2:

Я только что заметил, что в вашей структуре const членов. вот почему вы получаете эти read-only ошибки, если вы используете только назначение. Вы можете решить эту проблему, удалив эти const s из структуры location или сделать это следующим образом:

memcpy(&current_location, current_location.portals[0], sizeof(current_location));

но я не предлагаю такой подход, для предотвращения этой проблемы лучше использовать указатели .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...