• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Wczytywanie mapy i elementów z pliku

0 głosów
522 wizyt
pytanie zadane 6 listopada 2020 w C i C++ przez Xarcane Początkujący (440 p.)
zamknięte 6 listopada 2020 przez Xarcane

Zastanawiam się nad wczytywaniem jednostek z pliku do programu,obecna konstrukcja mi się nie podoba,myślę że da się to zrobić lepiej a ja to za bardzo zagmatwałem, i takie wczytywanie powoduje duże ryzyko wystąpienia błędów, możecie coś poradzić'? Oto mój kod:

Plik txt.

Load=[Creature][PositionX][PositionY]
[Slime][100][100]
[Slime][200][200]
[Slime][300][300]

Plik File Manager

enum LoadState { ATTRIBUTES, CONTENTS };

int state;

void FileManager::LoadContent(const char* filename, std::vector<std::vector<std::string>>& attributes,
    std::vector<std::vector<std::string>>& contents)
{
    attributes.clear();
    contents.clear();

    std::ifstream openfile(filename);
    if (openfile.is_open())
    {
        while (!openfile.eof())
        {
            std::string line;

            std::getline(openfile, line);

            line.erase(std::remove(line.begin(), line.end(), ' '), line.end());

            if (line.find("Load=") != std::string::npos)
            {
                state = ATTRIBUTES;
                line.erase(0, line.find('=') + 1);
                tempAttributes.clear();
            }
            else
            {
                state = CONTENTS;
                tempContents.clear();
            }

            line.erase(std::remove(line.begin(), line.end(), '['), line.end());

            std::stringstream str(line);
            while (str)
            {
                std::getline(str, line, ']');
                if (line != "")
                {
                    if (state == ATTRIBUTES)
                        tempAttributes.push_back(line);
                    else
                        tempContents.push_back(line);
                }
            }

            if (state == CONTENTS && tempContents.size() > 0)
            {
                attributes.push_back(tempAttributes);
                contents.push_back(tempContents);
            }
        }
    }
    else
    {
    }
}

Fragment kodu gdzie wczytuje dane do programu:

characterType.insert(std::make_pair("Slime", Character::Slime));
file.LoadContent("level0.txt", attributes, contents);

    for (int i = 0; i < attributes.size(); i++)
    {
        for (int j = 0; j < attributes[i].size(); j++)
        {
            std::string att = attributes[i][j];
            std::string con = contents[i][j];

            if (att == "Creature")
            {
                std::map<std::string, Character::Type>::iterator it = characterType.begin();
                while (it != characterType.end())
                {
                    if (it->first == contents[i][j])
                    {   
                        std::unique_ptr<Character> enemy(new Character(it->second, mTextures));
                        mSceneLayers[Upper]->attachChild(std::move(enemy));
                    }
                    it++;
                }
            }
        }
    }
}

W tym fragmencie nie przypisuje pozycji jednostce. Mógłbym zrobić tak że: If att == PositionX then etity[entity.size()-1].position.x = contents[i][j]. Ale co jak powstaną potem inne elementy entity,nie tylko potwory ale tez kafelki. To wszystko dałoby się "JAKOŚ" zrobić ale to strasznie potem jest namieszane. Nie wiem czy obrałem zły sposób wczytywania tego wszystkiego czy coś, ale prosiłbym o jakiś wzorzec,pomysł. Plik txt będzie wyglądał tak:

Load=[Creature][PositionX][PositionY]
[Slime][100][100]
[Slime][200][200]
[Slime][300][300]

Load=[Tile][PositionX][PositionY][Move]
[Dirt][100][100][0]
[Stone][100][100][1]

Staram się to jakoś rozwiązać ale ciągle mnie to niesatysfakcjonujące,ktoś może mi dać jakiś pomysł,artykuł, cokolwiek? 

komentarz zamknięcia: Rozwiązane

1 odpowiedź

+1 głos
odpowiedź 6 listopada 2020 przez tangarr Mędrzec (155,140 p.)
wybrane 6 listopada 2020 przez Xarcane
 
Najlepsza

Niezależnie od wybranego formatu danych w pliku zawsze może się pojawić błąd. Powinieneś dodać sprawdzanie formatu/struktury wczytywanych danych. W razie jakiegokolwiek problemu (za mało pól w linii, za dużo pól w linii, błąd w parsowaniu wartości, niepoprawne użycie nawiasów, niezamknięcie nawiasu, itp) powinieneś przerywać wczytywanie i zwracać błąd (możesz użyć wyjątków do tego).

Jeżeli chcesz zrobić elastyczny format danych to możesz się zainteresować jakimiś popularnymi formatami danych (np XML, JSON). Możesz sam napisać do nich parser (trudniejsze) lub użyć gotowej biblioteki.

Przykładowy plik JSON zawierający twoją mapę:

{
    "Creatures": [
         {"Type":"Slime", "x":100, "y":100},
         {"Type":"Slime", "x":100, "y":200},
         {"Type":"Slime", "x":100, "y":300}
     ],
     "Tiles":[
         {"Type":"Dirt", "x":100, "y":100, "Move":0}
     ]
}
komentarz 6 listopada 2020 przez Xarcane Początkujący (440 p.)
A jaką biblioteke do parsowania polecasz?
komentarz 6 listopada 2020 przez tangarr Mędrzec (155,140 p.)
Zazwyczaj używam parsera z biblioteki Qt. Jednak dodawanie takiego kombajnu do swojego programu tylko ze względu na jedną funkcjonalność wydaje się strzelaniem z armaty do wróbli.

RapidJSON wydaje się ciekawą alternatywą https://rapidjson.org/index.html

Podobne pytania

0 głosów
0 odpowiedzi 142 wizyt
pytanie zadane 6 marca 2017 w Inne języki przez Pulsar Nowicjusz (120 p.)
0 głosów
5 odpowiedzi 1,372 wizyt
pytanie zadane 28 kwietnia 2016 w C i C++ przez Munvik Dyskutant (9,350 p.)
0 głosów
1 odpowiedź 659 wizyt
pytanie zadane 7 maja 2015 w C i C++ przez molaki Obywatel (1,700 p.)

93,742 zapytań

142,678 odpowiedzi

323,297 komentarzy

63,328 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...