Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Sprawdzanie poprawności pliku Mapy

Ostatnio zmodyfikowano dzisiaj: 3h » 18 min
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
Sprawdzanie poprawności pliku Mapy
» 2024-10-19 14:32:16
Witam. Stworzyłem własny format map.
Mapa składa się z chunków 16x16 pól oraz GameObjectów, które są opisane przez 4 wartości: typ, nazwa, pozycja y, pozycja x.
Wiem, że aby sprawdzić czy pola chunka są poprawnie opisane wystarczy sprawdzić czy rozmiar std::vector < int > tiles wynosi 16x16. Ale jak wczytać te pola ? Mam również pytanie jak sprawdzić poprawność zapisu GameObjectu oraz jak sprawdzić czy następna wartość tilesa nie jest przypadkiem GameObjectem ?

Chunk y=0 x=5
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Nature "natures/tree9" y=160 x=1440
Nature "natures/tree9" y=192 x=1472
Nature "natures/tree9" y=224 x=1504
P-181713
pekfos
» 2024-10-19 15:53:56
Zależy jak bardzo chcesz być precyzyjny w sprawdzaniu poprawności pliku. Na przykład "Chunk" na początku pliku pewnie jest zbędne, więc możesz je zignorować, albo wczytać i sprawdzić czy jest równe "Chunk".

Wiem, że aby sprawdzić czy pola chunka są poprawnie opisane wystarczy sprawdzić czy rozmiar std::vector < int > tiles wynosi 16x16. Ale jak wczytać te pola ?
Możesz wczytać (unsigned) int 256 razy operatorem >>. Ale wtedy separatorem między liczbami będą dowolne białe znaki i wszystkie liczby można podać ciągiem w jednej linii. Jeśli chcesz wymagać by to było 16 linii, po 16 liczb oddzielonych pojedynczą spacją, to możesz wczytać ten fragment pliku jako linie tekstu i parsować liczby ręcznie z użyciem strtoul().

Mam również pytanie jak sprawdzić poprawność zapisu GameObjectu
Musi się dać sparsować, a potem należałoby sprawdzić czy wartości mają sens. Na pewno czy współrzędne należą do tego fragmentu mapy. Sparsować możesz to choćby i wyrażeniem regularnym.
https://regex-vis.com/?r=Nature+%22%28%5B%5E%22%5D%29%22+y%3D%28%5B0-9%5D%29+x%3D%28%5B0-9%5D%29 (coś jest nie tak z formatowaniem tego linku)
Albo ręcznie znak po znaku. Jeśli cudzysłowy są tylko dla ozdoby, to możesz to najpierw rozbić na 4 słowa oddzielone białymi znakami, a potem usunąć "dekoracje" jak "", y=, itp. Ale zakładam że dopuszczasz białe znaki między cudzysłowami i trzeba je zachować.
C/C++
#include <iostream>
#include <string>
#include <regex>

int main()
{
   
std::regex nature( R"r(Nature "([^"]+)" y=([0-9]+) x=([0-9]+))r" );
   
   
std::string lines[ ] = {
       
R"(Nature "natures/tree9" y=160 x=1440)",
       
R"(Nature "natures/tree9" y=192 x=1472)",
       
R"(Nature "natures/tree9" y=224 x=1504)",
       
R"(Nature "natures/tree9" y=224 x=1504)",
       
R"(Nature "natures/tree9" x=1504 y=224)",
       
R"(Nature natures/tree9 y=224 x=1504)",
       
R"(Nature "natures/tree9" y=224 x=1504 )",
   
};
   
   
for( auto & line: lines )
   
{
       
std::smatch sm;
       
if( std::regex_match( line, sm, nature ) )
       
{
           
std::cout << "Name: " << sm[ 1 ] << ", y: " << sm[ 2 ] << ", x: " << sm[ 3 ] << '\n';
       
}
       
else
           
 std::cout << "Parse error\n";
       
   
}
}
P-181714
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-20 12:15:09
Czyli w sumie pola wczytywać również mogę przy użyciu std::regex_match do osiągnięcia wartości regex_match różne od liczby. A jeszcze mam pytanie. Co dokładnie oznacza ten zapis ?

C/C++
std::regex nature( R"r(Nature "([^"]+)" y=([0-9]+) x=([0-9]+))r" );
P-181716
pekfos
» 2024-10-20 12:38:52
W sensie jaki zapis? R"r(? Trzeba tu zadbać o jednoznaczne zakończenie raw stringa, inaczej nie zadziała:
C/C++
std::regex nature( R"(Nature "([^"]+)" y =([ 0 - 9 ] + ) x =([ 0 - 9 ] + ) ) " );
"
C/C++
std::regex nature( R"cokolwiek(Nature "([^"]+)" y=([0-9]+) x=([0-9]+))cokolwiek" );
Jeśli chodziło o znaczenie tego konkretnego wyrażenia regularnego, to najlepiej sam poczytaj o tym jak działają. Jest sporo narzędzi online gdzie możesz poeksperymentować, np https://regex101.com/r/Uxluph/1.
P-181717
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-20 12:46:30
Raczej chodziło mi o ten zapis
"([^"]+)"


Dobra już wiem. Ten zapis oznacza, że pobiera wszystkie znaki i neguje cudzysłów ". Czyli dokładniej
() - wyrażenie
[]+ - pobierz wszystkie znaki
^" - neguj cudzysłów

i to wyrażenie z
"natures/tree9"
 da nam
natures/tree9


Aby poprawnie regex'ować wartości, które akurat ja potrzebuję należy użyć
([A-Za-z]+) "([^"]+)" y=([0-9]+) x=([0-9]+)
 

Wtedy:
-pierwsze wyrażenie to ciąg znaków A-Z, a-z
-drugie wyrażenie to wartość pomiędzy cudzysłowami
-trzecie wyrażenie to liczba po "y="
-czwarte wyrażenie to liczba po "x="
P-181718
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-20 13:28:21
Jeszcze mam pytanie jak wczytać pola przed tym regexem z naciskiem na to, że zapis pól może być niekompletny lub nadkompletny tzn. że poniższy przypadek nie powinien w ogóle wczytać pól ?

Chunk y=0 x=5
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0  
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
P-181719
pekfos
» 2024-10-20 14:03:46
Linię z "Chunk" możesz też zrobić regexem, natomiast resztę bym zrobił przez strtoul(). Masz tam same liczby, a ich faktyczne parsowanie jest tu problemem, nie ich wyizolowanie. Samo [0-9]+ nie znaczy że masz poprawną liczbę, bo może być za długa by zmieścić się do docelowego typu liczbowego.
P-181720
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-20 14:13:44
to zwykłe inty przecież, nie wiem po co pchać tu insugned long. Nie wiem tylko jak sprawdzić czy faktycznie jest 16x16 wartości i jak następnie wczytać te tilesy (int'y) do tablicy

C/C++
std::istringstream lineStream( line );
lineStream >> objectType;

if( objectType == "Chunk" ) {
   
   
// load Chunk
   
std::regex chunk_regex( R"(Chunk y=([0-9]+) x=([0-9]+))" );
   
std::smatch chunk_match;
   
   
if( std::regex_search( line, chunk_match, chunk_regex ) ) {
       
int chunk_y = std::stoi( chunk_match[ 1 ] );
       
int chunk_x = std::stoi( chunk_match[ 2 ] );
       
       
// get chunk
       
chunk = getChunk( chunk_x, chunk_y );
       
       
if( chunk == nullptr ) {
           
chunk = new Chunk( chunk_x, chunk_y );
           
chunks.push_back( chunk );
       
}
       
       
// predefine tiles
       
std::vector < int > tiles;
       
for( int i = 0; i < 256; i++ )
           
 tiles.push_back( - 1 );
       
       
       
// load tiles
       
        // jak wczytać tilesy ?
        //
        //
       
        // set the tiles
       
if( tiles.size() == 256 ) {
           
for( int i = 0; i < tiles.size(); i++ ) {
               
chunk->terrain->edit( i % 16, i / 16, tiles[ i ] );
           
}
        }
       
       
    }
   
}
P-181721
« 1 » 2 3
  Strona 1 z 3 Następna strona