Aktuelle Array Position
-
@bamb4s
Um eine Fehlerquelle komplett auszumerzen (Zugriff auf ungültige Arrayelemente) solltest du dir zwei Funktionen bauen: Eine, die den Wert eines Arrayelements zurückgibt und eine, die den Wert eines Arrayelements setzt. Wenn du in diesen beiden Funktionen eine Gültigkeitsprüfung der Indizes vor dem Arrayzugriff durchführst kannst du nicht mehr auf ungültige Arrayelemente zugreifen.
char tree_state( std::size_t x, std::size_t y ) { if( x < DimX && y < DimY ) return Wald[x][y]; else return 0; } void set_tree_state( std::size_t x, std::size_t y, char NewState ) { if( x < DimX && y < DimY ) { Wald[x][y] = NewState; } }
-
DocShoe schrieb:
lol?
Wieso lol? Vielleicht habe ich die Aufgabe auch falsch verstanden, aber wenn Bäume nur eine Runde brennen, ist dies in Relation zur Gesamtfläche sehr wenig. Außerdem weiß man so auch, wann man ferig ist. Das sieht bei den geposteten Codes eher nicht so aus.
Ich werde das mal testen...
-
Wenn man zwischen brennend und abgebrannt unterscheiden muss, muss man den floodfill doch ein wenig anpassen.
Stack 1 enthält brennende Bäume (am Anfang drei - rot), diese suchen sich Nachbarn (im Link unten acht, also auch diagonal) zum Entzünden. Werden welche gefunden, werden die Punkte auf Stack 2 gepusht.
Eine „Runde” ist dann beendet, wenn Stack 1 komplett abgebaut wurde. Der Inhalt von Stack 2 wird kopiert (die entzündeten sind nun die brenndenden Bäume) und die Koordinaten entsprechend markiert (gelb).
Anschließend wird ein Bild gemacht.Das gif ist leider etwas groß geworden (~2MB). Es sind drei Runden mit gleichen Startpunkten aber einer unterschiedlichen Anzahl an Bäumen (Karte 120*80).
-
Wenn kein Baum mehr brennt ist man fertig, das kriegt man auch ohne Stack raus.
-
DocShoe schrieb:
@bamb4s
Um eine Fehlerquelle komplett auszumerzen (Zugriff auf ungültige Arrayelemente) solltest du dir zwei Funktionen bauen: Eine, die den Wert eines Arrayelements zurückgibt und eine, die den Wert eines Arrayelements setzt. Wenn du in diesen beiden Funktionen eine Gültigkeitsprüfung der Indizes vor dem Arrayzugriff durchführst kannst du nicht mehr auf ungültige Arrayelemente zugreifen.
char tree_state( std::size_t x, std::size_t y ) { if( x < DimX && y < DimY ) return Wald[x][y]; else return 0; } void set_tree_state( std::size_t x, std::size_t y, char NewState ) { if( x < DimX && y < DimY ) { Wald[x][y] = NewState; } }
Ich muss zugeben das ich mich noch nicht wirklich mit class beschäftigt habe. Eigentlich sollte da für die Übung auch nicht nötig sein. Trotzdem versuche ich das mal mit einzupacken, denn ich glaub ich hab ein bisschen Blut geleckt fürs Programmieren
-
Ich wollte nochmal danke an alle für die Hilfe sagen! Hier auch das fertige Programm
Testat bestanden!
#include <stdlib.h> #include <iostream> using namespace std; int rand(); //Randomizer für den Wald void meldung(char a, int b); //Funktion für Textausgabe int wald1(int a[20][30],int b); //Funktion zur Walderstellung int brand1(int a[20][30], int b); //Brand mit nur einem Baum int brand2(int a[20][30], int b); //Brand erste Reihe int schritt(int a[20][30], int b, int c, char d); //Schrittschleife für Simulation int simulation(int a[20][30], char d); //Simulation Waldbrand void ausgabe(int a[20][30]); //Übersetzung des int Arrays in char Array int auswahl; //Steuert die Menüführung int feuer; //Wie wird der Wald angezündet int startwert; //Initialisierung von int rand(); double dichte = 1; //Initialisierung der Var für die Dichte des Waldes int i, k; //Zähler für die Arrayschleife int main() { //Abfrage der Sprache mit Schleife char Sprache; int wald[20][30]; cout << endl << " Please select your language // Bitte Sprache auswaehlen" << endl << endl; cout << " 'e' = English" << endl << " 'd' = Deutsch" << endl << endl; cout << " Press 'e' or 'd' // Druecken Sie 'e' oder 'd'" << endl; cin >> Sprache; cout << endl; //Schleife zur Abfrage ob "e" oder "d" eingegeben wurde while ((Sprache != 'e'&&Sprache != 'd')) { cout << " Wrong input! Please retry // Falsche Eingabe! Bitte wiederholen" << endl; cin >> Sprache; } //Ausgabe des Menüs in vertikaler Ausrichtung (Geht auch in einer Funktion) meldung(Sprache, 1); meldung(Sprache, 2); meldung(Sprache, 3); meldung(Sprache, 4); cout << endl; do{ cin >> auswahl; switch(auswahl){ case 1: //Startwert für Randomizer meldung(Sprache, 9); cin >> startwert; meldung(Sprache, 5); cin >> dichte; cout << endl; //Dichte wird abgefragt while (dichte>1 || dichte<0) { meldung(Sprache, 6); cin >> dichte; cout << endl; } wald1(wald, startwert); ausgabe(wald); meldung(Sprache, 7); break; case 2: meldung(Sprache, 8); cin >> feuer; //Schleife um falsche Eingabe zu verhindern while (feuer != 1 && feuer != 2) { meldung(Sprache, 6); cin >> feuer; } //Zuweisung der Variablen für Unterprogramm if (feuer == 1) { brand1(wald, startwert); ausgabe(wald); feuer =1; } else { brand2(wald, startwert); ausgabe(wald); feuer =2; } cout << endl; meldung(Sprache, 7); break; case 3: schritt(wald, startwert, feuer, Sprache); cout << endl; meldung(Sprache, 7); break; case 4: break; } if(auswahl==4){ break; } } while(auswahl >0 || auswahl<4); } //Meldungen zweisprachig void meldung(char a, int b) { if (a == 'e') //Englisch { switch(b) { case 1: cout << "\t1: New forest" << endl; break; case 2: cout << "\t2: Set fire" << endl; break; case 3: cout << "\t3: Simulate fire" << endl; break; case 4: cout << "\t4: Exit program" << endl; break; case 5: cout << "\tSet forest density 0-1" << endl << endl; break; case 6: cout << "\tInvalid Input" << endl << "\tTry again" << endl; break; case 7: cout << " 1:New forest 2: Set fire 3:Simulate fire 4:Exit program" << endl; break; case 8: cout << " Set the first tree with (1) on fire. Press (2) to set the first line on fire" << endl; break; case 9: cout << "\tSet starting value for randomizer " << endl; break; case 10: cout << "\tPress (1) to Continue, any other key to stop" << endl; break; case 11: cout << "\tInvalid Input! Press (1)-(4)" << endl; } } else //Deutsch { switch(b) { case 1: cout << "\t1: Neuer Wald" << endl; break; case 2: cout << "\t2: Feuer legen" << endl; break; case 3: cout << "\t3: Feuer simulieren" << endl; break; case 4: cout << "\t4: Programm beenden" << endl; break; case 5: cout << "\tDichte des Waldes von 0-1 eingeben" << endl << endl; break; case 6: cout << "\tUngueltige Eingabe" << endl << "\tErneute eingeben" << endl; break; case 7: cout << " 1:Neuer Wald 2:Feuer legen 3:Feuer simulieren 4:Programm beenden" << endl; break; case 8: cout << " Ersten Baum mit (1) anzuenden. Druecke (2) um die erste Reihe in brand zu setuen" << endl; break; case 9: cout << "\tStartwert fuer Zufallsfunktion eingeben" << endl; break; case 10: cout << "\tUm fortzufahren (1) druecken, zum abbrechen beliebige Taste druecken" << endl; break; case 11: cout << "\tFalsche Eingabe! Druecke (1)-(4)" << endl; break; } } } //Unterprogramm für Wald Erstellung int wald1(int a[20][30],int b){ srand(b); // Schleife fuer Zeilen, Y-Achse for (i = 0; i<20; i++) { // Schleife fuer Spalten, X-Achse for (k = 0; k<30; k++) { //Code für zufällig generierten Wald if (((dichte * 10) - 1) < (rand() % 10)) a[i][k] = 0; else a[i][k] = 3; } } return **a; } //Unerprogramm um den ersten Baum anzuzünden int brand1(int a[20][30], int b){ srand(b); wald1(a,b); int gefunden = 0; for(i=0;i<20;i++){ for(k=0;k<30;k++){ if (a[i][k] == 3 && gefunden == 0) { a[i][k] = 2; gefunden = 1; } } } return **a; } //Unterprogramm um die erste REIHE anzuzünden int brand2(int a[20][30], int b){ srand(b); wald1(a, b); for(i=0;i<20;i++){ for(k=0;k<30;k++){ if (a[0][k] == 3) { a[0][k] = 2; } } } return **a; } //Unterprogramm für Schritte in Simulation int schritt(int a[20][30], int b, int c, char d){ srand(b); //Simulation für brennende Reihe if (c==2) { brand2(a, b); cout << endl; simulation(a, d); } //Int für Abfrage um zu wissen ob schon ein Baum angezündet worden ist} if (c==1) { brand1(a, b); cout << endl; simulation(a,d); } } // Unterprogramm simulation int simulation(int a[20][30], char d){ int Wald2[20][30] = { 0 }; //Array zur Übergabe int weiter = 1; while (weiter == 1) { for (i = 0; i<20; i++) { for (k = 0; k<1; k++) { if (a[i][k] == 2)a[i][k] = 1; if (a[i][k] == 1&&a[i + 1][k] == 3 || a[i][k] == 1&&a[i - 1][k] == 3 || a[i][k] == 1&&a[i][k + 1] == 3 || a[i][k] == 1&&a[i][k - 1] == 3) { if (a[i + 1][k] == 3)Wald2[i + 1][k] = 2; if (a[i - 1][k] == 3)Wald2[i - 1][k] = 2; if (a[i][k + 1] == 3)Wald2[i][k + 1] = 2; } } } for (i = 0; i<20; i++) { for (k = 1; k<30; k++) { if (a[i][k] == 2)a[i][k] = 1; if (a[i][k] == 1&&a[i + 1][k] == 3 || a[i][k] == 1&&a[i - 1][k] == 3 || a[i][k] == 1&&a[i][k + 1] == 3 || a[i][k] == 1&&a[i][k - 1] == 3) { if (a[i + 1][k] == 3)Wald2[i + 1][k] = 2; if (a[i - 1][k] == 3)Wald2[i - 1][k] = 2; if (a[i][k + 1] == 3)Wald2[i][k + 1] = 2; if (a[i][k - 1] == 3)Wald2[i][k - 1] = 2; } } } for (i = 0; i<20; i++) { for (k = 0; k<30; k++) { if (Wald2[i][k] == 2)a[i][k] = 2; if (Wald2[i][k] == 2)Wald2[i][k] = 1; } } ausgabe(a); meldung(d, 10); cin >> weiter; } return **a; } //Übersetzung void ausgabe(int a[20][30]){ char ubersetzung[20][30]= {0}; for(i=0;i<20;i++){ for(k=0;k<30;k++){ if(a[i][k]==3)ubersetzung[i][k]='X'; if(a[i][k]==2)ubersetzung[i][k]='+'; if(a[i][k]==1)ubersetzung[i][k]='.'; if(a[i][k]==0)ubersetzung[i][k]=' '; cout << ubersetzung[i][k] << " "; } cout << endl; } }
Das return **a; hab ich nicht ganz verstanden, weil return 0; auch geht, aber der Prof hat nichts gesagt. Vielleicht hat er es auch garnicht gesehen.
Ich dachte erst das wäre nötig um Arrays aus der Funktion zurück zu geben, aber scheinbar ist das nicht so ^^
-
Puhh was soll man dazu sagen, außer bitte nicht nachmachen.
Hab keine Stelle gefunden, wo der return Wert weiterverarbeitet wird. Der einzig sinnvolle return Wert ist dann void.
An welcher Uni/FH bist du und welches Fach studierst du?
-
Ich hab das noch für mich in return 0; geändert. Das Programm läuft aber eigentlich ordentlich durch.
Ich studiere Maschinenbau ab der Uni in Erlangen. Also kein Informatik oder so So genau hat der Prof auch nicht geschaut, da das Programm lief.
-
So wird das aber nichts mit dem Nachwuchs, wenn an Unis immer noch "C mit cin/cout" als C++ "gelehrt" wird!
-
Aus Interesse: Warum lehrt man es dann überhaupt, wenn man es später eh nicht richtig anwenden soll?
Wenn nur für den Überblick, wäre Java oder Phyton nicht die bessere Wahl? Oder ein BASIC-Dialekt?
-
lemon03 schrieb:
Aus Interesse: Warum lehrt man es dann überhaupt, wenn man es später eh nicht richtig anwenden soll?
Wenn nur für den Überblick, wäre Java oder Phyton nicht die bessere Wahl? Oder ein BASIC-Dialekt?
Weil Maschinen meist mit C++ programmiert sind und der Ingenieur in der Lage sein soll nachzuvollziehen was der Programmierer in seinem Programm gemacht hat.
Der Programmierer weis in der Regel zwar für was sein Programm genutzt wird, aber kennt die technischen Hintergründe nicht immer. So zumindest unser Prof.https://imgur.com/a/sIMGBZC : Programmiersprachen bei der Programmierung von Embedded Prozessoren
https://imgur.com/a/E1jdvYb : Beispiel Airbag
Ich würde es auch gut finden, es einmal richtig zu lernen, aber ich denke hier geht es weniger um die Syntax und mehr um die Abläufe an sich. Bei laut Modulhandbuch 28Std. Seminatischer Unterricht, 24 Stunden Übungen und 38Std. Vor- Nachbearbeitung (Summe 90Std.) Kann der Umfang allerdings auch nicht so hoch ausfallen.
-
Aha, danke
Ich denke aber, Maschinen werden eher in C programmiert. Aus Speicherplatzgründen oder so.
Für die Abläufe extra C++ falsch lernen finde ich nicht richtig. Da sollte man dann doch besser eine höher-levelige (:D) Sprache wählen.