Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!
Das Game of Life ist eine Simulation primitiven "Lebens" innerhalb einer 2D-Welt. Die Welt ist in unserem Fall quadratisch und besteht aus NxN Feldern (N liegt garantiert zwischen 1 und 256). Ein Feld kann entweder eine lebendige Zelle beinhalten oder leer sein. Die Simulation ist "rundenbasiert": in jeder Iteration wird die nächste Generation der Zellen berechnet. Dabei wird anhand folgender Regeln entschieden, was mit jedem Feld geschieht:
Hat ein leeres Feld genau 3 Zellen als Nachbarn, so entsteht auf diesem Feld eine neue Zelle.
Hat eine Zelle weniger als 2 Zellen als Nachbarn, so stirbt sie an Vereinsamung, und das Feld wird leer.
Hat eine Zelle mehr als 3 Nachbarzellen, so stirbt sie an Überbevölkerung, und das Feld wird leer.
Ansonsten bleibt das Feld unverändert.
Jedes Feld in der Spielwelt hat genau 8 Nachbarfelder: links oben, oben, rechts oben, links, rechts, links unten, unten und rechts unten. Das gilt auch für die Felder am Rand. Alles, was das Spielfeld auf der einen Seite verlässt, kommt auf der anderen Seite wieder herein. Man kann sich die 2D-Welt also so vorstellen, als sei sie über einen Torus (Donut) gespannt. Bei einer 1x1-Welt hat das einzige existierende Feld sich selbst 8x als Nachbar. Ist auf dem Feld eine Zelle, so stirbt sie an Überbevölkerung durch sich selbst (klingt komisch, ist aber so).
Eure Aufgabe ist es, eine Funktion zu programmieren, die für eine gegebene Spielwelt die nächste Generation berechnet - also die oben genannten Regeln für jedes Feld anwendet. Die Funktion erhält als Parameter die Größe der Welt world_size (= N, nicht N²), ein Eingabe- und ein Ausgabe-Array. Die nächste Generation der Spielwelt muss in dieses Ausgabe-Array geschrieben werden. Ein- und Ausgabespeicherbereich überlappen sich nicht.
Die Felder sind zeilenweise von oben nach unten und innerhalb der Zeilen von links nach rechts in den Arrays angeordnet. true steht für eine lebendige Zelle, false für ein leeres Feld. Wenn die aktuelle Spielwelt also wie folgt aussieht, ...
Bei diesem Wettbewerb kommt es nicht auf die Geschwindigkeit an, sondern auf die Anzahl der benötigten Token! Einen Token-Counter findet ihr hier.
Die Benutzung der Standardbibliothek ist verboten!
Weiterhin ist es nicht erlaubt, über die Grenzen der Arrays hinweg zu lesen bzw. zu schreiben (könnte zu Abstürzen führen).
Code, dessen Verhalten undefiniert ist, wird disqualifiziert. Passt also auf, dass ihr nicht zu viel kürzt!
Übrigens lohnt es sich, eine Visualisierung einzubauen, denn das Game of Life ist sehr interessant zu beobachten. Es gibt eine Vielzahl von "Lebewesen", die je nach Spielregeln entstehen können.
Ich frage einfach mal wie "Kürze des Codes" definiert wird. Kommt es auf die Zeilen an, oder auf die Zeichen...?
Weil afaik lassen sich Projekte auch compilen, wenn sie komplett in eine Zeile geschrieben wurden. Das ist jetzt der Code von dir, hier auf der Seite lässt sich das schlecht anzeigen, hab es aber nochmal bei nopaste hochgeladen.
Quellcode
1
#include <iostream>#include <cstdlib> const int MAX_WORLD_SIZE = 256;const int NUM_TESTS = 500;void my_game_of_life(int world_size, const bool* p_world_in, bool* p_world_out){int x = 42;}void correct_game_of_life(int world_size, const bool* p_world_in, bool* p_world_out){struct Helper{static int coords_to_index(int x, int y, int world_size){while(x < 0) x += world_size;while(x >= world_size) x -= world_size;while(y < 0) y += world_size;while(y >= world_size) y -= world_size;return y * world_size + x;}};for(int x = 0; x < world_size; ++x){for(int y = 0; y < world_size; ++y){const unsigned int num_neighbors = p_world_in[Helper::coords_to_index(x - 1, y - 1, world_size)] +p_world_in[Helper::coords_to_index(x, y - 1, world_size)] +p_world_in[Helper::coords_to_index(x + 1, y - 1, world_size)] +p_world_in[Helper::coords_to_index(x - 1, y, world_size)] +p_world_in[Helper::coords_to_index(x + 1, y, world_size)] +p_world_in[Helper::coords_to_index(x - 1, y + 1, world_size)] +p_world_in[Helper::coords_to_index(x, y + 1, world_size)] +p_world_in[Helper::coords_to_index(x + 1, y + 1, world_size)];const unsigned int index = Helper::coords_to_index(x, y, world_size);if(num_neighbors == 3){p_world_out[index] = true;}else if(num_neighbors < 2 || num_neighbors > 3){p_world_out[index] = false;}else{p_world_out[index] = p_world_in[index];}}}}int main(){std::cout << "Teste ..." << std::endl;for(int i = 0; i < NUM_TESTS; ++i){const int world_size = 1 + rand() % MAX_WORLD_SIZE;bool world_in[MAX_WORLD_SIZE * MAX_WORLD_SIZE];bool my_world_out[MAX_WORLD_SIZE * MAX_WORLD_SIZE];bool correct_world_out[MAX_WORLD_SIZE * MAX_WORLD_SIZE];for(int i = 0; i < world_size * world_size; ++i) world_in[i] = rand() % 3 == 0;my_game_of_life(world_size, world_in, my_world_out);correct_game_of_life(world_size, world_in, correct_world_out);for(int i = 0; i < world_size * world_size; ++i){if(my_world_out[i] < correct_world_out[i]){std::cout << "Fehler in Test Nr. " << (i + 1) << "!" << std::endl;goto end;}}}std::cout << "Die Implementierung scheint korrekt zu sein!" << std::endl;end:return 0;}
http://rafb.net/p/rD2rbg63.html
Dies ist jetzt einfach nur der Vorgegebene Code von dir David.
EDIT: Hätte ich doch einfach mal kurz in die Regeln geschaut -_-
...die Anzahl der Token wird gezählt -.-
find den Code wie oben trotzdem schön
Nein, da das Verwenden der Standardbibliothek nicht erlaubt ist (steht in der Aufgabenbeschreibung). Ich bin mir ziemlich sicher, dass du diese Funktion überhaupt nicht brauchst. world_size ist nicht die Anzahl der Felder, sondern N. Die Welt hat N² Felder.