LINUX.ORG.RU

[C] Проблемы с самопальным итератором.

 


0

0

Доброго времени суток, all.

На днях начал писать мини-движок для игры в шашки/шахматы/нарды/... (в-общем, любые игры, использующие поле). Всё бы ничего, дело продвигалось, но возникла проблема, самостоятельно которую решить у меня так и не получилось. 

Код:

// Объявляем свою структуру для игровых объектов со ссылками на предыдущий и следующий

typedef struct CGameObject* GameObjectPtr;

typedef struct CGameObject
{
    int x;
    int y;
    GameObjectPtr prev;
    GameObjectPtr next;
} GameObject;

// ----------------------------------

// Сравниваем x и y двух объектов. При совпадении, возвращаем указатель на первый
static GameObjectPtr comparexy(GameObjectPtr go, GameObjectPtr goxy)
{
    if((go->x == goxy->x) && (go->y == goxy->y))
    {
        return go;
    }
    return NULL;
}

// Собственно, итератор с callback-функцией, принимающей два параметра - текущий объект и дополнительный.
GameObjectPtr iterate(GameObjectPtr begin, GameObjectPtr callback(GameObjectPtr, GameObjectPtr), GameObjectPtr additional)
{
    GameObjectPtr gocur = begin, goret = NULL;
    while(gocur->next != NULL)
    {
        gocur = gocur->next;
        if((goret = callback(gocur, additional)) != NULL)
        {
            return goret;
        }
    }
    return NULL;
}

// Функция поиска объекта по его x и y
GameObjectPtr gofindbyxy(GameObjectPtr begin, int x, int y)
{
    GameObjectPtr gonew = goalloc(NULL);
    gonew->x = x;
    gonew->y = y;
    return iterate(begin, comparexy, gonew);
}

При вызове gofindbyxy(begin, 1, 1); объекта, который существует он просто не находит. :(
Не знаю, где собака порылась, не могу найти ошибку, если надо могу привести код аллокатора и деструктора.

---
С Уважением,

>// Собственно, итератор с callback-функцией, принимающей два параметра >- текущий объект и дополнительный.
>GameObjectPtr iterate(GameObjectPtr begin, GameObjectPtr >callback(GameObjectPtr, GameObjectPtr), GameObjectPtr additional)
>{
>    GameObjectPtr gocur = begin, goret = NULL;
>    while(gocur->next != NULL)
>    {
>        gocur = gocur->next;
>        if((goret = callback(gocur, additional)) != NULL)
>        {
>            return goret;
>        }
>    }
>    return NULL;
>}

По моему объект begin никогда не пройдет через сравнение, может все-таки так:

     while((gocur->next != NULL) && (gocur != NULL))
................
        if((goret = callback(gocur, additional)) != NULL)
        {
            return goret;
        }
        gocur = gocur->next;

koTuk
()

> GameObjectPtr gofindbyxy(GameObjectPtr begin, int x, int y)
> {
>     GameObjectPtr gonew = goalloc(NULL);
>     gonew->x = x;
>     gonew->y = y;
>     return iterate(begin, comparexy, gonew);
> }

А gonew нигде не надо регистрировать? Как он попадает в один список с begin?

Jini ★★
()
Ответ на: комментарий от koTuk

> По моему объект begin никогда не пройдет через сравнение

Это так специально задумано. Есть один корневой объект, который характеризует всю цепочку, причём он нигде не задействован (то есть просто аллоцируется, вызывается при необходимости в качестве begin и в конце программы убивается).

---
С Уважением,

BuG2BuG
() автор топика
Ответ на: комментарий от Jini

> А gonew нигде не надо регистрировать? Как он попадает в один список с begin?

Дык он же в этой строчке

> GameObjectPtr gonew = goalloc(NULL);

выделяется, являясь корневым объектом. А нужен лишь как дополнительный аргумент для сравнения координат.

---
С Уважением,

BuG2BuG
() автор топика
Ответ на: комментарий от BuG2BuG

Натолкнуло на мысль. Проверил, открыл в себе человека, которому нужно руки оторвать. 
Проблема спряталась совсем в другом месте, конкретнее в функции main.
Я, оказывается, вызывал функцию поиска уже после освобождения памяти. xD

Вот так было:

#include <stdio.h>

#include "gametypes.h"
#include "logic.h"
#include "ui.h"

int main(int argc, char** argv)
{
    GameObjectPtr x;
    initializeall();
    // iterate(gowhite,printxy, NULL);

    iterate(gowhite, freeprev, NULL);

    if((x = gofindbyxy(gowhite, 1, 1)) != NULL)
    {
        printxy(x, NULL);
    }
    else
    {
        printf("NULL\n");
    }


    // createui(argc, argv);
    return 0;
}

, где freeprev описывалась как:

GameObjectPtr freeprev(GameObjectPtr go, ...)
{
    gofree(go->prev);
    return NULL;
}

, где gofree - деструктор.

Переставил iterate(gowhite, freeprev, NULL); вниз и всё сразу заработало "на ура".

Извините, я только начинаю писать что-то серьёзнее хеллоуворлдов и олимпиадных задачек.

Всем огромное спасибо за помощь.

---
С Уважением,

BuG2BuG
() автор топика
Ответ на: комментарий от BuG2BuG

s/хеллоуворлдов и олимпиадных задачек/хеллоуворлдов, олимпиадных задачек и систем управления сервоприводами беспилотных летательных аппаратов/ Fixed. =^_~=

---
С Уважением,

BuG2BuG
() автор топика
Ответ на: комментарий от BuG2BuG

/me ушёл уменьшать ЧСВ, а то и до ФГМ недалеко.

---
С Уважением,

BuG2BuG
() автор топика
Ответ на: комментарий от anonymous

> Вам стоит почитать про linked list и / или double linked list.

Спасибо, принял к сведению. На досуге обязательно займусь.

---
С Уважением,

BuG2BuG
() автор топика
Ответ на: комментарий от anonymous

> Вам стоит почитать про linked list и / или double linked list.

Почитал. Узнал много нового. Занимаюсь велосипедостроительством, ибо всё уже написано в GLib: http://library.gnome.org/devel/glib/stable/glib-Doubly-Linked-Lists.html

---
С Уважением,

BuG2BuG
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.