Waldbrandsimulation
-
Hi Leute,
bin Anfänger in C und möchte gerne einen Waldbrand simulieren und komme da auch ganz gut voran, nur hab ich eine kleine Frage.
Der Wald wird als quadratisches Feld der Kantenlänge n dargestellt, zufällig bepflanzt und anschließend die gesamte linke Spalte (sofern Bäume vorhanden) angezündet. Von dort aus soll sich das Feuer nun auf die direkten Nachbarn ausbreiten (Nachbarn der Stelle [i][j] sind [i-1][j], [i+1][j], [i][j-1] und [i][j+1]).
Dazu habe ich folgende Unterfunktion geschrieben:
char zeitschritt(char wald[n][n]) { int i,j; for(i=0; i<n; i++) { for(j=0; j<n; j++) { if((wald[i-1][j]=='*' || wald[i+1][j]=='*' || wald[i][j-1]=='*' || wald[i][j+1]=='*') && wald[i][j]=='T') {wald[i][j]='*';} displayausgabe(wald); sleep(750); printf("\n\n"); } } return 0; }
'T' beschreibt hierbei, dass das Feld bepflanzt ist, '*', dass der Baum brennt.
Das Problem ist nun, dass der Wald der Reihe nach abbrennt, d.h. Zeile für Zeile durchgeht und nacheinander die Bäume abbrennt. Was also nicht funktioniert ist, dass auch Nachbarfelder aus anderen Zeilen direkt mit angezündet werden. Das liegt sicherlich an den Zählschleifen, da diese ja nacheinander das gesamte Feld durchgehen, aber iwie komm ich da jetzt nicht drauf wie ich das anders zum Laufen bringe.
Daher würde ich mich über einen kleinen Denkanstoß freuen!
Grüße
informer
-
Hmm, das ist doch nicht so schwer.
Also, wenn Nachbarn der Stelle
[i][j]-> [i+1][j]
-> [i-1][j]
-> [i][j+1]
-> [i][j-1]sind und du
im Moment prüfst, ob diese Nachbarn von [i][j] bereist brennen.
Wenn eines davon brennt und [i][j] bepflanzt ist, dann wird es angezündet.
Ich würde es von der Logik anders aufziehen.
Ich würde sagen, prüfe alle Felder ob sie bereits brennen, wenn ein brenndes Feld gefunden wird, dann zünde das Nachbarfeld an, sofern es nicht schon brennt.
(also erstmal markieren, damit es nicht schon als Brand erkannt wird)int i,j; for (i=0;i<n;i++) { for (j=0;j<n;j++) { if (wald[i][j] == '*') { if ((i > 0) && (wald[i-1][j]=='T') wald[i-1][j] = 'x'; if ((i < n-1) && (wald[i+1][j]=='T') wald[i+1][j] = 'x'; if ((j > 0) && (wald[i][j-1]=='T') wald[i][j-1] = 'x'; if ((j < n-1) && (wald[i][j+1]=='T') wald[i][j+1] = 'x'; } /* x markiert die Felder fürs nächste Feuer, denn wenn es direkt gezündelt wird, brennen die Nachbarfelder sofort.*/ } } for (i=0;i<n;i++) { for (j=0;j<n;j++) { if (wald[i][j] == 'x') wald[i][j] = '*'; } } /* Nun wird gezündelt.*/
Habe das Ganze nun mal in einen Code gepackt, der auch läuft, aber dort arbeite ich mit globalen Variablen und er ist total hingesaut.
Aber er zeigt, daß er von der Feuerlogik richtig arbeitet.Das erste Feuer ist oben links.
Es funktioniert aber auch mit mehreren Feuern an beliebiger Stelle.#include <stdio.h> int n=10; void zeitschritt(); void ausgabe(); char wald[10][10]={"*TTTTTTTT","TTTTTTTTT","TTTTTTTTT","TTTTTTTTT","TTTTTTTTT","TTTTTTTTT","TTTTTTTTT","TTTTT*TTT","TTTTTTTTT","TTTTTTTTT"}; int main(void) { ausgabe(); for (int a=0;a<10;a++) { zeitschritt(); ausgabe(); } } void zeitschritt() { int i,j; for (i=0;i<n;i++) { for (j=0;j<n;j++) { if (wald[i][j] == '*') { if ((i > 0) && (wald[i-1][j]=='T')) wald[i-1][j] = 'x'; if ((i < n-1) && (wald[i+1][j]=='T')) wald[i+1][j] = 'x'; if ((j > 0) && (wald[i][j-1]=='T')) wald[i][j-1] = 'x'; if ((j < n-1) && (wald[i][j+1]=='T')) wald[i][j+1] = 'x'; } /* x markiert die Felder fürs nächste Feuer, denn wenn es direkt gezündelt wird, brennen die Nachbarfelder sofort.*/ } } for (i=0;i<n;i++) { for (j=0;j<n;j++) { if (wald[i][j] == 'x') wald[i][j] = '*'; } } } void ausgabe() { int i,j; for (i=0;i<n;i++) { for (j=0;j<n;j++) { printf("%c",wald[i][j]); } printf("\n"); } getchar(); }
Enter gibt einen weiteren Zeitschritt aus.
Gruß,
DC
-
Wow, vielen Dank jetzt versteh ichs.
Mal abgesehen davon, dass ich logisch auch nicht ganz korrekt rangegangen bin, ist es vor allem die vorrübergehende Zuweisung mit 'x' die das ganze natürlich einfacher gestaltet, da ich stets Probleme mit dem frühzeitigen Entzünden hatte.
Nochmals vielen Dank!
Tolles Forum!
-
Man könnte das noch erweitern in dem man noch äussere Facktoren wie Wind oder Luftfeuchtigkeit einbauen...
-
Ja, und vielleicht natürliche Hindernisse, wie Felsen oder Seen.
Dann an den Rändern noch Wohngebiete.Dann setzt man ein Feuer iregndwo im Wald und schaut sich an, ob das Feuer in Richtung Wohngebiet marschiert oder nicht.
Da sind wirklich vielseitige Möglichkeiten gegeben.
Gruß,
DC
-
Der Sinn von Simulationen ist es, die reale Wirklichkeit in einem berechenbaren Modell zuverlässig abzubilden. So etwas ist keine Programmierfrage mehr und hat somit mit C nichts zu tun. Der Wald brennt sobald darin ein Feuer anfängt und sich ausbreiten kann. Zu berücksichtigende Faktoren gibt es wohl viele und können dennoch nicht alle im Modell erfasst sein.
-
Nachdem das mit dem Waldbrand schon ganz gut klappt, könnte man sich auch an Atombomben ranmachen!
-
Halli hallo Leute
Ich muss das gleiche machen.
Das mit dem zeitschritt habe ich bei mir schon eingebaut.
Ich habe das problem das mein programm den wald complet mit T's voll macht und ich weiss net warum.Eine weitere frage ist wie gekomme ich die schleife zum anhalten wenn alles abgebrand ist?
#include <stdio.h> #include <windows.h> #include <stdlib.h> #include <time.h> #define DIM 10 int start(); int menu(); char belegung(char wald[DIM][DIM],float p); char randanzuenden(char wald[DIM][DIM]); char ausgabe(char wald[DIM][DIM]); char zeitschritt(char wald[DIM][DIM],int b); double zufall(long int *start); float brenndauer(int g); int main() { /*int b,a=0,i,c,j; double p; char wald[DIM][DIM]; float g; */ Neu:; printf("Hallo und Herzlich Wilkommen bei zuendeln fuer Anfaenger \n\n"); //printf("Wie viel m^2 willst du nieder brennen?\n"); // scanf("%d",&k); start(); return 0; } int start() { int b,a=0,i,j; double p; char wald[DIM][DIM]; //float g; b=menu(); if ((b>0) &&(b<4)) { switch(b) { case 1 : printf("Gib Bitte die Bewaldung der Flaeche in Prozent ein.\n"); scanf("%f",&p); p=p/100; belegung(wald,p); ausgabe(wald); randanzuenden(wald); ausgabe(wald); zeitschritt(wald,b); start(); break; case 2 : for(a=0;a<11;a++) { p=a/10.0;//a muss gespeichert werden for(i=0;i<31;i++) { belegung(wald,p); randanzuenden(wald); zeitschritt(wald,b);//g muss ausgelesenwerden float brenndauer(int &g); //ausageb ueber x graph } } start(); break; case 3: return 0; } } else { start(); } return 0; } int menu() { int m; printf("\n\tMenue\n"); printf("\t=====\n\n"); printf("Einen Waldbrandsimulieren 1\n"); printf("Fuer eine Waldbrandstatistik 2\n"); printf("Zum Beenden 3\n\n"); printf("Ihre Wahl: "); scanf("%d",&m); return m; } char belegung(char wald[DIM][DIM],float p) { int i,j; float z; long int start; start=time(NULL); for (i=0;i<DIM;i++) for(j=0;j<DIM;j++) { z=zufall(&start); if (z<p) wald[i][j]='T'; else wald[i][j]=' '; } return 0; } char randanzuenden(char wald[DIM][DIM]) { int i; for (i=0;i<DIM;i++) if (wald[i][0]=='T') wald[i][0]='*'; return 0; } char ausgabe (char wald[DIM][DIM]) { int i,j; printf("\n\n"); for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { printf("%c ",wald[i][j]); } printf("\n"); } Sleep(950); return 0; } char zeitschritt(char wald[DIM][DIM],int b) { int i,j,c,g=0; for (c=0;c<100;c++) { for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] == '*') { if ((i > 0) && (wald[i-1][j]=='T')) wald[i-1][j] = 'x'; if ((i < DIM-1) && (wald[i+1][j]=='T')) wald[i+1][j] = 'x'; if ((j > 0) && (wald[i][j-1]=='T')) wald[i][j-1] = 'x'; if ((j < DIM-1) && (wald[i][j+1]=='T')) wald[i][j+1] = 'x'; } /* x markiert die Felder fürs nächste Feuer, denn wenn es direkt gezündelt wird, brennen die Nachbarfelder sofort.*/ } } for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] == '*') { if ((i > 0) && (wald[i-1][j]=='*' ||' ')) wald[i][j] = 'y'; if ((i < DIM-1) && (wald[i+1][j]=='*'||' ')) wald[i][j] = 'y'; if ((j > 0) && (wald[i][j-1]=='*'||' ')) wald[i][j] = 'y'; if ((j < DIM-1) && (wald[i][j+1]=='*'||' ')) wald[i][j] = 'y'; } /* y markiert díe felder für nächtse Rauchen*/ } } for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] == '!') { if ((i > 0) && (wald[i-1][j]=='*'||' '|| '!')) wald[i][j] = 'z'; if ((i < DIM-1) && (wald[i+1][j]=='*'||' '|| '!')) wald[i][j] = 'z'; if ((j > 0) && (wald[i][j-1]=='*'||' '|| '!')) wald[i][j] = 'z'; if ((j < DIM-1) && (wald[i][j+1]=='*'||' '|| '!')) wald[i][j] = 'z'; } /* z markiert díe felder für nächtse abgebrant*/ } } /*for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] == '.') { if ((i > 0) && (wald[i-1][j]==' '|| '.'||'*'||'T')) wald[i][j] = 's'; if ((i < DIM-1) && (wald[i+1][j]==' '|| '.'||'*'||'T')) wald[i][j] = 's'; if ((j > 0) && (wald[i][j-1]==' '|| '.'||'*'||'T')) wald[i][j] = 's'; if ((j < DIM-1) && (wald[i][j+1]==' '|| '.'||'*'||'T')) wald[i][j] = 's'; } /* z markiert díe felder für nächtse abgebrant } }*/ for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] == 'x') wald[i][j] = '*'; } } for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] == 'y') wald[i][j] = '!'; } } for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] == 'z') wald[i][j] = '.'; } } /*for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] == 's') wald[i][j] = '.'; c=100; } }*/ g++; /*for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] !=' '||'.') c=20; } }*/ if(b==1) ausgabe(wald); } return 0; } double zufall(long int *start) { double zufall; *start=(*start*7141+54773) %253177; zufall=*start/253177.0; return zufall; }
Gruß Drufus
-
kompilierbarer code bitte..
besonders: was soll das in Zeile 75 sein?
-
hoffe der code geht, mit dev c kann ich es kompielieren und ausführen.
case 2 einfach nicht beachten das ist noch andere teilaufgabe.
#include <stdio.h> #include <windows.h> #include <stdlib.h> #include <time.h> #define DIM 10 int start(); int menu(); char belegung(char wald[DIM][DIM],float p); char randanzuenden(char wald[DIM][DIM]); char ausgabe(char wald[DIM][DIM]); char zeitschritt(char wald[DIM][DIM],int b); double zufall(long int *start); int main() { Neu:; printf("Hallo und Herzlich Wilkommen bei zuendeln fuer Anfaenger \n\n"); start(); return 0; } int start() { int b,a=0,i,j; double p; char wald[DIM][DIM]; b=menu(); if ((b>0) &&(b<4)) { switch(b) { case 1 : printf("Gib Bitte die Bewaldung der Flaeche in Prozent ein.\n"); scanf("%f",&p); p=p/100; belegung(wald,p); ausgabe(wald); randanzuenden(wald); ausgabe(wald); zeitschritt(wald,b); start(); break; case 2 : start(); break; case 3: return 0; } } else { start(); } return 0; } int menu() { int m; printf("\n\tMenue\n"); printf("\t=====\n\n"); printf("Einen Waldbrandsimulieren 1\n"); printf("Fuer eine Waldbrandstatistik 2\n"); printf("Zum Beenden 3\n\n"); printf("Ihre Wahl: "); scanf("%d",&m); return m; } char belegung(char wald[DIM][DIM],float p) { int i,j; float z; long int start; start=time(NULL); for (i=0;i<DIM;i++) for(j=0;j<DIM;j++) { z=zufall(&start); if (z<p) wald[i][j]='T'; else wald[i][j]=' '; } return 0; } char randanzuenden(char wald[DIM][DIM]) { int i; for (i=0;i<DIM;i++) if (wald[i][0]=='T') wald[i][0]='*'; return 0; } char ausgabe (char wald[DIM][DIM]) { int i,j; printf("\n\n"); for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { printf("%c ",wald[i][j]); } printf("\n"); } Sleep(950); return 0; } char zeitschritt(char wald[DIM][DIM],int b) { int i,j,c,g=0; for (c=0;c<100;c++) { for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] == '*') { if ((i > 0) && (wald[i-1][j]=='T')) wald[i-1][j] = 'x'; if ((i < DIM-1) && (wald[i+1][j]=='T')) wald[i+1][j] = 'x'; if ((j > 0) && (wald[i][j-1]=='T')) wald[i][j-1] = 'x'; if ((j < DIM-1) && (wald[i][j+1]=='T')) wald[i][j+1] = 'x'; } } } for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] == '*') { if ((i > 0) && (wald[i-1][j]=='*' ||' ')) wald[i][j] = 'y'; if ((i < DIM-1) && (wald[i+1][j]=='*'||' ')) wald[i][j] = 'y'; if ((j > 0) && (wald[i][j-1]=='*'||' ')) wald[i][j] = 'y'; if ((j < DIM-1) && (wald[i][j+1]=='*'||' ')) wald[i][j] = 'y'; } } } for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] == '!') { if ((i > 0) && (wald[i-1][j]=='*'||' '|| '!')) wald[i][j] = 'z'; if ((i < DIM-1) && (wald[i+1][j]=='*'||' '|| '!')) wald[i][j] = 'z'; if ((j > 0) && (wald[i][j-1]=='*'||' '|| '!')) wald[i][j] = 'z'; if ((j < DIM-1) && (wald[i][j+1]=='*'||' '|| '!')) wald[i][j] = 'z'; } } } for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] == 'x') wald[i][j] = '*'; } } for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] == 'y') wald[i][j] = '!'; } } for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { if (wald[i][j] == 'z') wald[i][j] = '.'; } } g++; if(b==1) ausgabe(wald); } return 0; } double zufall(long int *start) { double zufall; *start=(*start*7141+54773) %253177; zufall=*start/253177.0; return zufall; }
-
Wer soll das noch alles lesen?
Hier mal mein Pseudocode:if(wald brennt)
{
if(handy dabei) 112 rufen;
schnell abhauen;
}
else kein problem;
-
Um Festzustellen, ob der ganze Wand abgebrannt ist, könntest du in einer Variable die Anzahl brennender Felder Speichern. Am Anfang enthält sie die Anzahl der zu Beginn brennenden Felder. Wenn ein neues Feld angezündet wird, wird der Wert der Variablen einfach inkrementiert. Nach jedem Durchlauf schaust du dann nach, ob die Anzahl der brennenden Felder (in der Variablen gespeichert) gleich der Gesamtzahl der Felder ist. Sollte das der Fall sein, ist der Wald abgebrannt.
MfG, Jochen
-
Wieso Simulieren, wenn du es in echt machen kannst ?
-
USR32 schrieb:
Wieso Simulieren, wenn du es in echt machen kannst ?
Er traut sich wohl nicht und eine weitere Variable Brandstifter soll es in der Simulatation nicht geben. Dann kämen noch die Variablen Kriminialinspektor und Knast hinzu!
-
wie schreibe ich das, dass er die brennenden felder speichert?
-
Drufus schrieb:
wie schreibe ich das, dass er die brennenden felder speichert?
Er hat einen Laptop im Wald. Darauf befindet sich sein Programm zur Simulation des Waldbrandes. In einem Array int brennt[...] kann er für einige Felder im Wald abspeichern, wo es brennt und wo nicht. Brennt es aber gerade dort, wo er seinen Laptop hingelegt hat, ist die Simulation ohnehin erledigt!
-
Drufus schrieb:
wie schreibe ich das, dass er die brennenden felder speichert?
Du stellst dich mit einem GPS-Gerät auf den brennenden Baum und sendest die Koordinaten zu deinem Computer, der die Koordinaten dann in einem 2d-Array speichert.
-
Drufus schrieb:
wie schreibe ich das, dass er die brennenden felder speichert?
So zum Beispiel:
int Feld[20][20]; int AnzahlBrennend = 0; for(int n=0;n<20;n++) for(int i=0;i<20;i++) Feld[i][n] = 0; // Brennt nicht // Feld anzünden: Feld[x][y] = 1; // Brennt AnzahlBrennend++; if(AnzahlBrennend==20*20){/*Alles brennt*/} //Ausgabe: for(int n=0;n<20;n++) { for(int i=0;i<20;i++) printf("%d",Feld[i][n]); printf("/n"); }
Keine Garantie für Richtigkeit, hab es nicht getestet.
So als kleiner Denkanstoß. Den "Feuer-Ausbreitungs-Algorithmus" musst du aber selber schreiben.MfG, Jochen