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 |
|
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ć. #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"; } } |
|
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 ? std::regex nature( R"r(Nature "([^"]+)" y=([0-9]+) x=([0-9]+))r" );
|
|
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: std::regex nature( R"(Nature "([^"]+)" y =([ 0 - 9 ] + ) x =([ 0 - 9 ] + ) ) " ); " 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. |
|
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=" |
|
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
|
|
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. |
|
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 std::istringstream lineStream( line ); lineStream >> objectType;
if( objectType == "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 ] ); chunk = getChunk( chunk_x, chunk_y ); if( chunk == nullptr ) { chunk = new Chunk( chunk_x, chunk_y ); chunks.push_back( chunk ); } std::vector < int > tiles; for( int i = 0; i < 256; i++ ) tiles.push_back( - 1 ); if( tiles.size() == 256 ) { for( int i = 0; i < tiles.size(); i++ ) { chunk->terrain->edit( i % 16, i / 16, tiles[ i ] ); } } } }
|
|
« 1 » 2 3 |