Objektkoordinaten 2d Array
-
...
-
danke anti-freak und danke swordfish für die erwiterung.

Allerdings funktioniert das bei mir nicht mit nullptr und mit null auch nicht nur wenn ich 0 benutze. Ich verstehe die zeile auch nicht 100%
std::srand( std::time( nullptr ) );könnte jemand ein paar erklärende worte abgeben? Habe eben mal gegooglet zu 0 null und nullptr und ich weiss das es was mit zeigern zu tun hat ich blicke aber nicht ganz durch.
-
Photon schrieb:
Allerdings funktioniert das bei mir nicht mit nullptr und mit null auch nicht nur wenn ich 0 benutze. Ich verstehe die zeile auch nicht 100%
std::srand( std::time( nullptr ) );"Funktioniert nicht" ist keine Fehlerbeschreibung.
Bei uns funktioniert das.
Merk Dir diese Seite: http://en.cppreference.com/w/.
Dort wirst Du wahrscheinlich häufig vorbeischauen, wenn Du C++ lernst.Dort steht z.B. fuer
time()Defined in header <ctime>
time_t time( std::time_t *time );
Returns the current calendar time encoded as a std::time_t object.
Hast Du den Header <ctime> inkludiert?
Sonst: wie ist die Fehlermeldung?
-
...
-
Swordfish schrieb:
nullptr(C++11),NULLbzw.(void *) 0ist der Null Pointer.Nein,
nullptr(C++11),NULLaka0bzw.0List der Null Pointer.(void*)0ist in C++ nicht der Nullpointer (funktioniert nicht für Memberpointer).
-
So habe ich es genau gemacht:
#include <iostream> #include <cstdlib> #include <ctime> using namespace std; struct hero {int dmg, def, hp;}; hero h_generator() { int arr[3]; for(int i = 0; i<3;i++){ arr[i] = rand() % 10 + 1;} hero randy = {arr[0],arr[1],arr[2]}; return randy; } hero showdown (hero a, hero b) { b.dmg -= a.def; if(b.dmg<0){b.dmg=0;} a.hp -= b.dmg; return a; } hero print_value(hero temp) { cout << "dmg: " << temp.dmg << " def: " << temp.def << " hp: " << temp.hp << endl << endl; } int main() { srand(time(nullptr)); hero red = h_generator(); hero blue = h_generator(); hero store = red; cout << "red: \n"; print_value(red); cout << "blue: \n"; print_value(blue); cout << "\nSHOWDOWN!!!\n" << endl; red = showdown(red,blue); blue = showdown(blue,store); cout << "red: \n"; print_value(red); cout << "blue: \n"; print_value(blue); }Also die beteffende zeile ist eine funktion die eine funktion aufruft die den wert auf den der 0 pointer zeigt behandelt?!
std::srand( std::time( nullptr ) );Soweit ich es verstanden habe sind structs wie klassen nur das alle sachen public sind. An welchen stellen macht es sinn richtige klassen anzulegen? Gibt es klassen die als "parameter"(ist das der richtige ausdruck?) structs besitzen?
-
Photon schrieb:
So habe ich es genau gemacht:
Und was funktioniert daran nicht?
Du wirst nicht um den Kauf eines C++-Buches herumkommen, wenn Du es ernsthaft meinst mit dem Lernen - ein Forum ist kein Ersatz für ein Buch
und die mir bekannten Online Quellen auch nicht.
Hier im Forum gibt es immer mal wieder Threads in denen nach Büchern gefragt wird, und in denen Empfehlungen ausgesprochen werden.Zum Thema Funktionen:
hero print_value(hero temp); hero showdown (hero a, hero b);Weisst Du, was das
herovor dem Funktionsnamen bedeutet?Kennst Du Übergabe per Wert/Übergabe per Referenz?
Wenn ja: welche Konsequenz hat dieses Wissen fürshowdown()?
Wenn nein: lies es nach.
-
Photon schrieb:
Soweit ich es verstanden habe sind structs wie klassen nur das alle sachen public sind. An welchen stellen macht es sinn richtige klassen anzulegen? Gibt es klassen die als "parameter"(ist das der richtige ausdruck?) structs besitzen?
Und Klassen können Memberfunktionen haben. Dein Code mit Klassen:
#include <cstdlib> #include <ctime> using namespace std; class hero { int dmg, def, hp; // private public: // öffentlich, alles sichtbar hero() // deine Funktion h_generator, erzeugt einen hero (an alle anderen: verzichte auf initiliste und so) { int arr[3]; for(int i = 0; i<3;i++) arr[i] = rand() % 10 + 1; dmg = arr[0]: def = arr[1]; hp = arr[2]; } void shutdown(hero other) // aktuelle objekt veränderbar in Memberfunktion { other.dmg -= other.def; if (other.dmg < 0) other.dmg = 0; hp -= other.dmg; } void print_value() { cout << "dmg: " << dmg << " def: " << def << " hp: " << hp << endl << endl; } }; int main() { srand(time(nullptr)); hero red; // automatischer aufruf des konstruktors hero blue; hero store; cout << "red: \n"; red.print_value(); //aufruf von memberfunktion cout << "blue: \n"; blueprint_value(); }
-
Nathan_logoff schrieb:
Und Klassen können Memberfunktionen haben.
structs auch

-
Ja, klar.
Aber ich meinte mit "Structs" C-Style Structs und mit "Klassen" C++ Klassen/Structs.
War ungünstig ausgedrückt, ja.Ich sollte mir aber mal mein Passwort merken, dass ist schlimm.

-
Ja du hast recht Furble ich kauf mir nächten monat ein buch

WAs genau nicht funktionert ist das wenn ich nullptr verwende mir der compiler sagt das nullptr nicht deklariert ist. Wenn ich 0 benutze geht es aber ich weiss jetzt nicht wie sich das verhält ist 0 = nullptr?
das hero vor der funktion ist glaube ich die typbezeichnung für den rückgabewert.
sowas wie
int funktion(int a){ a=a+10; return a;}hero ist ja mein eigener typ und weil ich den in die funktion reingebe oder ausgeben will muss vor der funktion hero stehen oder?
Ich hoffe ich liege jetzt nicht total daben.Nein ich weiss nicht so genau wie es sich mit referenz und wert verhält. Das
fällt unter das thema zeiger oder?
Werde mich mal informieren.Über Klassen auch nochmal ich verstehe nicht alles aus deinem code. Warum print_value void sein kann ist mir jetzt klar. Aber der showdown oder wie du ihn nennst shutdown ? Ich will doch da mit hero red und blue rechnen muss ich die dann nicht beide reingeben?
-
Photon schrieb:
WAs genau nicht funktionert ist das wenn ich nullptr verwende mir der compiler sagt das nullptr nicht deklariert ist. Wenn ich 0 benutze geht es aber ich weiss jetzt nicht wie sich das verhält ist 0 = nullptr?
Jein.
Aber bei dir ist das egal.das hero vor der funktion ist glaube ich die typbezeichnung für den rückgabewert.
Ja
hero ist ja mein eigener typ und weil ich den in die funktion reingebe oder ausgeben will muss vor der funktion hero stehen oder?
Ich hoffe ich liege jetzt nicht total daben.Das vor dem Funktionsnamen ist der Rückgabewert, die Argumente stehen in den Klammern.
Du musst das nur davor schreiben, wenn du hero zurückgeben willst.[quote}Über Klassen auch nochmal ich verstehe nicht alles aus deinem code. Warum print_value void sein kann ist mir jetzt klar. Aber der showdown oder wie du ihn nennst shutdown ? Ich will doch da mit hero red und blue rechnen muss ich die dann nicht beide reingeben?[/quote]
Das shutdown bei mir war ein Tippfehler.
Und die musst du nicht beide reingeben, bei Membefunktion kannst du immer implizit auf die aktuelle Instanz zugreifen.
Bei:red.print_value()ist die aktuelle Instanz red und du kannst auf die Variablen von red zugreifen.
Bei
blue.print_value();
blue und due kannst darauf zugreifen.
Aber warte einfach auf dein Buch.
-
Photon schrieb:
Nein ich weiss nicht so genau wie es sich mit referenz und wert verhält.
Ich hab da mal was vorbereitet. Auch wenn meine didaktischen Konzepte in diesem Thread schon kritisiert wurden.

Folgendes:
#include <iostream> #include <string> // Held mit Name struct hero { std::string name; int dmg, def, hp; }; bool is_alive(hero h) { bool alive = 0<h.hp; if(alive) std::cout << h.name << " is alive.\n"; else std::cout << h.name << " is dead.\n"; return alive; } // Uebergabe per Wert void break_neck(hero h){ // h ist eine Kopie des übergebenen Objekts std::cout << h.name << " slipped and broke his neck!\n"; h.hp=0; } // Uebergabe per Referenz void meet_dragon(hero& h){ // h ist ein Alias für das übergebene Objekt std::cout << h.name << " took a wrong turn and entered the dragon's lair.\n"; h.hp=0; } int main(){ hero red = { "red", 10, 10, 10 }; hero blue = { "blue", 8, 8, 8 }; break_neck(red); if(is_alive(red)) std::cout << "Impossibru!\n"; meet_dragon(blue); if(is_alive(blue)) std::cout << "goddammit!\n"; }Das spannende sind Zeile 27:
h wird als eine neue Variable vom Typ hero deklariert - das System initialisiert h beim Aufruf mit dem Funktionsargument. h ist also eine Kopie(!) des Arguments.Und im Gegensatz dazu Zeile 33:
h wird als Referenz auf ein hero Objekt (hero&) deklariert. h ist lediglich ein Aliasname für das Funktionsargument. Referenzen erkennst Du am & hinter der Typangabe.Lass das Programm laufen. Hast Du die Ausgabe erwartet?
Wenn ja: Übergabe per Wert/Referenz begriffen.
Wenn nein: nochmal drüber grübeln - ist ganz einfach. Ebenso einfach wie der Unterschied zwischen einer Kopie und einem Alias im echten Leben.Memberfunktionen habe ich bisher bewusst nicht erwähnt.
-
ok ich war das wochende weg aber ich hab mir die sache angeschaut. Ich habe jetzt verstanden wie das mit den referenzen funktioniert und warum es besser ist direkt auf den speicherplatz zuzugreifen anstatt immer neue variablen zu erzeugen und diese auch im speicher abzulegen.
Als nächstes werde ich mir wohl die pointer nochmal genauer ansehen die ja auch was damit zu tun haben. Hab da noch nicht so ganz den durchblick.
Danke furble das war ein gutes beispiel. Jetzt werde ich öfter mal void funktionen nutzen können.
-
Photon schrieb:
ok ich war das wochende weg aber ich hab mir die sache angeschaut. Ich habe jetzt verstanden wie das mit den referenzen funktioniert und warum es besser ist direkt auf den speicherplatz zuzugreifen anstatt immer neue variablen zu erzeugen und diese auch im speicher abzulegen.
Zieh nicht die falschen Schlußfolgerungen. Besser oder schlechter habe ich noch gar nicht gesagt.
Was ich zeigen wollte:
In einer Funktion auf einer Kopie eines Arguments zu arbeiten ist etwas komplett anderes als auf dem Original zu arbeiten.Photon schrieb:
Als nächstes werde ich mir wohl die pointer nochmal genauer ansehen die ja auch was damit zu tun haben. Hab da noch nicht so ganz den durchblick.
Zeiger sind mit Sicherheit ein wichtiger Aspekt von C++, aber als Anfänger kommst Du erstmal gut ohne aus.
Z.B. möchte ich Dir noch zwei Sachen zeigen.
Mein letztes Beispiel enthielt zwei Verzweigungen, in denen ich Codefehler aufspüren wollte:
break_neck(red); if(is_alive(red)) std::cout << "Impossibru!\n"; meet_dragon(blue); if(is_alive(blue)) std::cout << "goddammit!\n";Nachdem rot sich den Hals brach, bzw. blau einen Drachen traf hätten beide tot sein sollen. Sobald eine der beiden Bedingungen wahr wurde war ich einem Programmfehler auf der Spur - in dem Fall
break_neck().
C++ bietet für sowas sog. Assertions.
D.h. wenn Du an einer Stelle im Programmcode eine Bedingung voraussetzt, kannst Du eine Assertion einbauen. Das Programm wird an der Stelle beendet, sollte die Bedingung doch nicht erfüllt sein. Z.B.#include <iostream> #include <string> #include <cassert> // wie oben... int main(){ // ... break_neck(red); assert( !is_alive(red) ); // Laufzeitfehler, wenn assert( false ) meet_dragon(blue); assert( !is_alive(blue) ); // dto. }Sehr hilfreich!
Und weiter noch: siehe z.B. folgenden Code, der weitestgehend identisch mit dem bisherigen ist:
#include <iostream> #include <string> #include <cassert> struct hero { std::string name; int dmg, def, hp; }; bool is_alive(hero h) { bool alive = 0<h.hp; if(alive) std::cout << h.name << " is alive.\n"; else std::cout << h.name << " is dead.\n"; return alive; } void break_neck(hero h){ // um assert() zu demonstrieren immer noch buggy :( std::cout << h.name << " slipped and broke his neck!\n"; h.hp=0; } void meet_dragon(hero& h){ std::cout << h.name << " took a wrong turn and entered the dragon's lair.\n"; h.hp=0; } // Uebergabe per Referenz auf const void print(const hero& h){ // h ist Referenz auf unveraenderliches (const) Objekt v. Typ hero std::cout << h.name << " (hp:" << h.hp << ", dmg:" << h.dmg << ", def:" << h.def << ')'; h.hp = 0; // toedliches print(). Kompiliert nicht. h ist const & ! } int main(){ hero red = { "red", 10, 10, 10 }; hero blue = { "blue", 8, 8, 8 }; print(red); std::cout << '\n'; print(blue); std::cout << '\n'; break_neck(red); assert( !is_alive(red) ); // Laufzeitfehler, wenn assert( false ) meet_dragon(blue); assert( !is_alive(blue) ); // dto. }Hoffentlich kriege ich das mit den Zeilennummern diesmal hin!

Spannend ist die Zeile 31.
h ist diesmal eine Referenz auf ein konstantes Objekt. D.h. h ist eine Referenz, wie Du sie schon kennst, aber darüberhinaus, kannst Du das Objekt, das h referenziert nicht über h verändern - siehe Zeile 33.Betrachte mit Deinem neuen Wissen Über Referenzen folgenden Code, der nicht ganz wie geplant funktioniert:
// attacking greift attacked an void attack(hero attacking, hero attacked); // Schlagabtausch - a hat die Initiative void showdown(hero a, hero b);Wie könnten Die Funktionen richtig aussehen? Kannst Du sie implementieren?
Wenn Du noch dabei bist - und folgen konntest - würde ich wohl beim nächsten Mal ein paar Worte zu Klassen und deren Member verlieren.
-
Furble Wurble schrieb:
Hoffentlich kriege ich das mit den Zeilennummern diesmal hin!

Spannend ist die Zeile 31.
Boah! Ich bin so ein Depp!

Aber jetzt ist's nur noch ein "Off-by-one"-Fehler.
Natürlich ist nur Zeile 30 spannend!
-
Hey,
Soweit ich es verstanden habe benutzt du die const variable als schutz damit sie nicht ausversehen geändert wird?
Zu den zwei funktionen. Bei der zweiten ist mir denke ich klar was zu tun ist aber bei der ersten weiss ich nicht so genau. Willst du einfach ur ne print funktionen die sagt held a mit den werten x,y,z greift held b mmit werten x,y,z an? und dann halt in er der nächsten wirklich "kämpfen" lasssen?
Ich werde mich nach der schule mal ransetzen und die dinger in deinen code einbauen.
Danke für die lehrstunde und beste Grüße aus Berlin
Photon
-
Photon schrieb:
Hey,
Moin!

Photon schrieb:
Soweit ich es verstanden habe benutzt du die const variable als schutz damit sie nicht ausversehen geändert wird?
So kannst Du es sehen.
Ein "tödliches print()" ist ein Bug, den ich so schon beim Kompilieren finde.Man spricht von "const-correctness" und die finde ich so wichtig, dass ich sie Dir von Beginn an nahelege.
Photon schrieb:
Zu den zwei funktionen. Bei der zweiten ist mir denke ich klar was zu tun ist aber bei der ersten weiss ich nicht so genau. Willst du einfach ur ne print funktionen die sagt held a mit den werten x,y,z greift held b mmit werten x,y,z an? und dann halt in er der nächsten wirklich "kämpfen" lasssen?
In der ersten sollst Du einen Angriff
attacker->attackedschreiben. Den richtigen Angriff. D.h. den Schaden berechnen und evtl.attackedLebenspunkte abziehen.
Aber es ist gar nicht der Inhalt auf den ich hinauswill: ich will nur sehen, dass Du die Funktionssignatur änderst - speziell die Typen der formalen Parameter.Dto. in der zweiten - wobei Du bei der Implementierung hoffentlich auf die erste Funktion zurückgreifst - dann wird's ein Zwei- oder Dreizeiler.
-
Ich habe jetzt eine weile nachgedacht aber ich komme nicht drauf.
Für die erste funktion habe ich das hier verwendet:
void attack(hero attacking, hero& attacked){ attacking.dmg -= attacked.def; if(attacking.dmg>0){ attacked.hp -= attacking.dmg;} }Aber wie du das jetzt mit der zweiten meinst verstehe ich nicht. Was genau soll jetzt noch bei showdown passieren? Ich steh irgendwie auf dem schlauch

-
Photon schrieb:
void attack(hero attacking, hero& attacked){ attacking.dmg -= attacked.def; if(attacking.dmg>0){ attacked.hp -= attacking.dmg;} }Aber wie du das jetzt mit der zweiten meinst verstehe ich nicht. Was genau soll jetzt noch bei showdown passieren? Ich steh irgendwie auf dem schlauch

Hmm...ja, mein Fehler. Ich dachte in
showdown()würde a erst b schlagen und b dann a - aber meinattack()ist Deinshowdown().
Egal:
Wieso übergibst Duattackingper Value?
Wieso ziehst Du vonattacking.dmgab? Verliert der Angreifer (bzw. dessen Kopie) Schadenspunkte?Meine Implementierungen:
void attack(const hero& attacker, hero& attacked){ assert(alive(attacker) && alive(attacked)); int dmg = attacked.def < attacker.dmg ? attacker.dmg - attacked.def : 0; attacked.hp = dmg < attacked.hp ? attacked.hp - dmg : 0; } void showdown(hero& a, hero& b){ attack(a, b); if(alive(b)) attack(b, a); }Der Ternäre Operator ist wahrscheinlich noch neu für Dich.
Funktioniert ganz einfach:
Bedingung ? Wert_wenn_Bedingung_wahr : Wert_wenn_Bedingung_falsch;Ist klar warum ich die Parameter so deklariere, wie ich sie deklariere?