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

Sprawdzanie poprawności pliku Mapy

Ostatnio zmodyfikowano 2024-10-23 17:05
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-20 14:26:15
Na razie mam coś takiego ale to statyczne wczytywanie a nie dynamiczne

C/C++
// Load tiles
for( int y = 0; y < 16; y++ ) {
   
std::string tileLine;
   
if( !std::getline( file, tileLine ) ) {
       
break; // If no more lines, break
   
}
   
   
std::istringstream tileStream( tileLine );
   
int value;
   
   
for( int x = 0; x < 16; x++ ) {
       
tileStream >> tiles[ y * 16 + x ];
   
}
}
P-181722
pekfos
» 2024-10-20 14:26:55
Nie wiem tylko jak sprawdzić czy faktycznie jest 16x16 wartości i jak następnie wczytać te tilesy (int'y) do tablicy
Powinieneś mieć 16 linii pasujących do formatu 16 liczb oddzielonych spacjami, więc w pętli wczytaj linie i sparsuj linie.

to zwykłe inty przecież, nie wiem po co pchać tu insugned long.
Kwestia preferencji. Wersje dla C działają na long, a wziąłem unsigned ponieważ oczekujesz tu tylko nieujemnych liczb, ale możesz ujemne odrzucić potem ifem. Pamiętaj że stoi() wyrzuca wyjątek w przypadku błędu więc dobrze by było go jakkolwiek obsłużyć.

C/C++
std::vector < int > tiles;
for( int i = 0; i < 256; i++ )
   
 tiles.push_back( - 1 );
Zasadniczo jest konstruktor wektora który to robi
C/C++
std::vector < int > tiles( 256, - 1 );

C/C++
tiles[ y * 16 + x ] = 0; // Default to 0 if no value is present
Wtedy nie prościej było wypełnić wektor na start zerami? Chyba chcesz w tej pętli wczytać do 16 liczb do tablicy i wywalić błąd jeżeli coś zostanie w strumieniu.
P-181723
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-20 14:38:21
chwila, chwila. Bo skopiowałem bezmyślnie z ChatGpt.

Teraz mam taki kod:

C/C++
// predefine tiles
std::vector < int > tiles;

// Load tiles
for( int y = 0; y < 16; y++ ) {
   
   
std::string tileLine;
   
   
if( !std::getline( file, tileLine ) ) {
       
break; // If no more lines, break
   
}
   
   
std::istringstream tileStream( tileLine );
   
int value;
   
   
for( int x = 0; x < 16; x++ ) {
       
tileStream >> value;
       
tiles.push_back( value );
   
}
}
P-181724
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-20 14:43:38
Dobra, chyba mam zaraz będę testował:

C/C++
// predefine tiles
std::vector < int > tiles( 256, 0 );

// Load tiles
int y = 0;

while( y < 16 && std::getline( file, line ) && line[ 0 ] >= '0' && line[ 0 ] <= '9' ) {
   
// y>=16 no load tiles
   
std::istringstream tileStream( line );
   
int value;
   
int x = 0;
   
while( tileStream >> value && x < 16 ) {
       
tiles[ y * 16 + x ] = value;
       
x += 1;
   
}
   
   
y += 1;
}

// set the tiles if correct datas
for( int i = 0; i < tiles.size(); i++ ) {
   
chunk->terrain->edit( i % 16, i / 16, tiles[ i ] );
}

Czy można jakoś przemieszczać się getlinem po liniach ?
P-181725
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-20 16:57:34
Można przy pomocy file.tellg() oraz file.seekg(). I z tym sposobem udało mi się zrobić sprawdzanie poprawności danych. Tutaj Kod :

C/C++
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 );
       
}
       
       
// check the correct of datas
       
std::streampos pos = file.tellg(); // Zapisanie pozycji linii
       
bool correct_data = true;
       
string _line;
       
int y = 0;
       
int x;
       
       
while( std::getline( file, _line ) && _line[ 0 ] >= '0' && _line[ 0 ] <= '9' ) {
           
           
std::istringstream iss( _line );
           
int val;
           
x = 0;
           
           
while( iss >> val )
               
 x += 1;
           
           
if( x != 16 ) {
               
//cout << x << "\n";
               
correct_data = false;
           
}
           
           
y += 1;
       
};
       
       
if( y != 16 ) {
           
//cout << y << "\n";
           
correct_data = false;
       
}
       
       
// predefine tiles
       
std::vector < int > tiles( 256, 0 );
       
       
if( correct_data == true ) {
           
file.seekg( pos ); // wczytanie pozycji linii
           
            // load tiles
           
int y = 0;
           
while( y < 16 && std::getline( file, line ) ) {
               
               
std::istringstream tileStream( line );
               
int value;
               
int x = 0;
               
               
while( tileStream >> value ) {
                   
tiles[ y * 16 + x ] = value;
                   
x += 1;
               
}
               
               
y += 1;
           
}
           
           
// set the tiles
           
for( int i = 0; i < tiles.size(); i++ )
               
 chunk->terrain->edit( i % 16, i / 16, tiles[ i ] );
           
       
}
       
       
    }
   
}
P-181726
pekfos
» 2024-10-20 21:53:21
Po co ten podział? Byłoby prościej jakbyś sprawdzał poprawność w czasie parsowania. Nie byłoby potrzeby wczytywać danych 2 razy i cofać się w pliku.
P-181727
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-21 09:34:02
Ponieważ, gdyby dane były niepoprawne, wtedy program nie wczytywałby ich. To zamierzałem właśnie osiagnąć.
P-181728
pekfos
» 2024-10-21 15:33:54
Przecież musisz je wczytać by to wiedzieć. To jest trochę bez sensu by najpierw jedna implementacja przetworzyła dane na niby, by potem druga implementacja mogła przetworzyć te dane i wypruć wynik już bez żadnych hamulców, bo "wszystkie możliwe błędy zostały wyłapane wcześniej". Wczytaj dane do tymczasowej lokalizacji i na koniec zdecyduj czy chcesz je zaaplikować. I tak to tak robisz gdy wczytujesz dane za drugim razem, powinno być tak:
C/C++
if( correct_data == true ) {
   
// set the tiles
   
for( int i = 0; i < tiles.size(); i++ )
       
 chunk->terrain->edit( i % 16, i / 16, tiles[ i ] );
   
}
Albo w ogóle nie powinno być tego w tym miejscu, bo na razie wiesz tylko czy ta macierz 16x16 jest poprawna. Dalsza część pliku może być błędna. Idealnie taki plik jest wczytywany w całości albo wcale. Od momentu gdy zdecydujesz się zaaplikować dane, do momentu poprawnego zakończenia, przerwanie z powodu błędu zostawia błędny stan. W tym przedziale powinno się dziać jak najmniej, najlepiej tylko przeniesienie nowych struktur danych w miejsce starych. Na pewno nie powinno być tam całej logiki realnego parsowania danych.
P-181729
1 « 2 » 3
Poprzednia strona Strona 2 z 3 Następna strona