Kampfskript oder ähnliches
-
:schland: schrieb:
Sind wirklich zuviele if.
Schau mal:if(holz >= 1000 && zeug >= 3442 && soweiter) { machDasDingFunktion(); //Aussagekräftiger Funktionsname. }Machs mal so, dann kann mas auch lesen
Das ist eine gute Idee.
Ich habe mir dieses Projeckt vorgenommen, weil C++ mich seht interessiert, komm aber nur langsam voran, aber ich verbessere den Code ständig, am Anfang sah er noch viel schlimmer aus. So lerne ich schneller und besser finde ich.
Außerdem bleibt mir die Motivation wenn ich an etwas arbeite was mir spaß macht.@Z2: aber ohne Globale Variablen gehts hier glaube ich garnicht.
thx, an euch beide, jetzt brauch ich nur noch wen der mir erklärt wie eine einfache Kampfberechnung durchführen kann!

mfg
Last-Boyscout
-
Es geht immer ohne globale Variablen. Ich programmiere jetzt seit 8 Jahren in C++ und in dieser Zeit hat es noch keinen einzigen Fall gegeben, wo ich nicht ohne globale Variablen ausgekommen wäre.
Was das "Kampfscript" betrifft: akaris Tip ist gut. Formuliere das ganze als mathematische Formeln (wie die aussehen mußt du schon selbst festlegen; das ist keine Implementations-, sondern eine Design-Frage).
-
Auch, wenn es nicht deine Frage ist:
Es würde sich vielleicht auch lohnen, alles in Module zu verpacken, dann hast du mehr übersicht.
Die hier würde ich in eine Klasse bzw. Struktur packen.//Verschiedene Variablen int Rundenzaehler = 0; int Eingabe; //Alles für Holz int Ende = 100; int Holz = 100; int Holzspeicher = 500; int Holzfaeller = 1; //Alles für Erz int Mine = 0; int Erz = 0; int Erzspeicher = 0; int Erzende = 0; //Alles für den Krieg int Kaserne = 0; int Soldaten = 0; int Soldatenlimit = 0; int Panzer = 0; //Alles für Nahrung int Nahrung = 0; int Farm = 0; int Nahrungsende = 0; int Nahrungsspeicher = 0; int Hunger = 2; //Sonstige Gebäude int Werkstatt = 0; int Haus = 0;--> Bis jetzt ist dein Prgramm noch sehr prozedual, probiere einfack mal alles etwas zu kapseln.

-
Kampffunktion:
float power = zufallszahlZwischen0und2oderSo(); int neueAnzahlEinheiten = anzahlEinheiten - (int)((float)anzahlGegner * power);
-
Jetzt noch zum \1:
Erstelle doch einfach eine Klasse Einheit:
class Einheit
{
int staerke;
int verteidigung;
...
}[/cpp]--> die kannste dann alle mit fstream in eine Datei schreiben und manipulieren.
und halt wieder auslesen.
-
Hier fehlt es mir dann an Wissen.
Danke für die vielen Vorschläge.Mal sehen wie weit ich mich da schlau machen kann.
Ne kleine Vorlage habe ich ja jetzt.Wie genau war das mit den Modulen gemeint?
-
Du kannst, wie du lust und laune hast neue Dateien anlegen:
zb.: du legst dir eine Datei names Ki.h an und schreibst dort die KI Funktion rein.
und über #include "ki.h" fügst du die dann in die main ein.
-
Tc++H schrieb:
Du kannst, wie du willst neue Dateien anlegen:
zb.: du legst dir eine Datei names Ki.h an und schreibst dort die KI Funktion rein.
und über #include "ki.h" fügst du die dann in die main ein.
Probier ich direckt mal aus

-
Klassen wären natürlich ideal. Aber wie es aussieht würde dich das im Moment noch überfordern. Also fassen wir die Variablen zumindest mal in structs zusammen, z.B. so:
struct seite // spieler oder gegner { int Mine; int Erz; int Erzspeicher; int Erzende; // und so weiter };in der main-Funktion:
int main() { do { seite Spieler: seite Gegner; InitSpieler (Spieler); InitGegner (Gegner); Interface(); Auswahl (Spieler); Berechnung (Spieler); // ersetzt Schleife-Funktion (komischer Name) Berechnung (Gegner); Kii (Gegner); } while ( 1 < 100); // witzig ;) }Und deine Funktionen sehen dann so aus:
void Auswahl (seite& Seite) { // irgendwas }
-
Last-Boyscout schrieb:
Tc++H schrieb:
Du kannst, wie du willst neue Dateien anlegen:
zb.: du legst dir eine Datei names Ki.h an und schreibst dort die KI Funktion rein.
und über #include "ki.h" fügst du die dann in die main ein.
Probier ich direckt mal aus

Das würde ich übrigens an deiner Stelle nicht machen. Grundsätzlich ist der Hinweis schon korrekt. Aber du solltest erst anfangen zu modularisieren, wenn du auch was zu modularisieren hast. Lediglich einzelne Funktionen in andere Übersetzungseinheiten auszulagern bringt dir erst mal gar nichts.
-
Alles sehr viel neues für micht, aber die nötigen Verbesserungen.
Dankeschön.
Ich geh jetzt erstmal pennen.

Gute Nacht^^
mfg
Last-Boyscout
-
Hier mal ein Ansatz:
unsigned long anzPanzer = 23; unsigned long gegAnzPanzer = 42; unsigned long anzSoldaten = 11; unsigned long gegAnzSoldaten = 33; unsigned long PLeben = 1000; unsigned long PAngriffskraft = 500; unsigned long SLeben = 100; unsigned long SAngriffskraft = 35; unsigned long gegPLeben = 1000; unsigned long gegPAngriffskraft = 500; unsigned long gegSLeben = 100; unsigned long gegSAngriffskraft = 35; // ## Angriff ################################################################## // 1) Panzerbattle // Haben beide Parteien gleich viel Panzer? if (anzPanzer == gegAnzPanzer) { // Alle Panzer haben sich gegenseitig ausgeschaltet! anzPanzer = 0; gegAnzPanzer = 0; } // Hat der Gegner mehr Panzer? if (anzPanzer < gegAnzPanzer) { // Der Gegner vernichtet alle Panzer des Spielers... gegAnzPanzer -= anzPanzer; anzPanzer = 0; // ...und greift danach mit den Panzern die Soldaten // des Spielers an! if (anzSoldaten != 0) { while (1) { // Ein Panzer: Soldaten greifen an, bis keine mehr da // sind oder der Panzer zerstört wurde for (long derGegPanzer = gegPLeben; derGegPanzer > 0 && anzSoldaten != 0; derGegPanzer -= SAngriffskraft, --anzSoldaten); // Hier können z.B. alle noch verbliebenden // Panzer auf die Soldaten schiessen und so // viel mehr von ihnen vernichten, denn die // einfache Dekrementierung hier wirkt, als // ob sich die Soldatengruppe in einer Reihe // aufstellt, die Gruppe mal angreifen darf // und danach der Panzer dran ist. Alle anderen // schauen zu und warten ^^ // Haben die Panzer etwa alle Soldaten erledigt? if (anzSoldaten == 0) { // SPIELER HAT VERLOREN!!! // exit, return, GAME OVER etc. } // Nein! Offensichtlich haben die Soldaten einen Panzer zerstört gegAnzPanzer--; // Hat der Gegner noch Panzer? if (gegAnzPanzer == 0) { // Alle gegnerischen Panzer wurden von den Soldaten zerstört! break; } } } else { // SPIELER HAT VERLOREN!!! // exit, return, GAME OVER etc. } } // Hat der Spieler mehr Panzer? if (anzPanzer > gegAnzPanzer) { // Der Spieler vernichtet alle Panzer des Gegners... anzPanzer -= gegAnzPanzer; gegAnzPanzer = 0; // ...und greift danach mit den Panzern die Soldaten // des Gegners an! if (gegAnzSoldaten != 0) { while (1) { // Ein Panzer: Soldaten greifen an, bis keine mehr da // sind oder der Panzer zerstört wurde for (long derPanzer = PLeben; derPanzer > 0 && gegAnzSoldaten != 0; derPanzer -= gegSAngriffskraft, --gegAnzSoldaten); // Hier können z.B. alle noch verbliebenden // Panzer auf die Soldaten schiessen und so // viel mehr von ihnen vernichten, denn die // einfache Dekrementierung hier wirkt, als // ob sich die Soldatengruppe in einer Reihe // aufstellt, die Gruppe mal angreifen darf // und danach der Panzer dran ist. Alle anderen // schauen zu und warten ^^ // Haben die Panzer etwa alle Soldaten erledigt? if (gegAnzSoldaten == 0) { // SPIELER HAT GEWONNEN!!! // exit, return, GAME OVER etc. } // Nein! Offensichtlich haben die Soldaten einen Panzer zerstört anzPanzer--; // Hat der Spieler noch Panzer? if (anzPanzer == 0) { // Alle eigenen Panzer wurden von den Soldaten zerstört! break; } } } else { // SPIELER HAT GEWONNEN!!! // exit, return, GAME OVER etc. } } // 2) Soldatenkampf // Haben beide Parteien gleich viele Soldatengruppen? if (anzSoldaten == gegAnzSoldaten) { // UNENTSCHIEDEN!!! // exit, return, GAME OVER etc. } // Hat der Gegner mehr Soldaten? if (anzSoldaten < gegAnzSoldaten) { // SPIELER HAT VERLOREN!!! // exit, return, GAME OVER etc. } // Hat der Spieler mehr Soldaten? if (anzSoldaten > gegAnzSoldaten) { // SPIELER HAT GEWONNEN!!! // exit, return, GAME OVER etc. }Ein weiterer (objektorientierterer) Ansatz:
#include <vector> // ## Einheiten ################################################################ // -- Panzer ------------------------------------------------------------------- class Panzer { public: Panzer(int setLeben, int setAngriffskraft); private: int Leben; int Angriffskraft; }; Panzer::Panzer(int setLeben, int setAngriffskraft): Leben(setLeben), Angriffskraft(setAngriffskraft) { } // -- Soldaten ----------------------------------------------------------------- class Soldaten { public: Soldaten(int setLeben, int setAngriffskraft); private: int Leben; int Angriffskraft; }; Soldaten::Soldaten(int setLeben, int setAngriffskraft): Leben(setLeben), Angriffskraft(setAngriffskraft) { } // ## Streitkräfte ############################################################# class Streitkraefte { public: // Der Vereinfachung halber als public std::vector<Panzer> Panzerstreitkraefte; std::vector<Soldaten> Soldatengruppen; private: }; // Allgemeine Angriffsfunktion void angriff(Streitkraefte Angreifer, Streitkraefte Verteidiger); // Dient nur zur Veranschaulichung, in Wirklichkeit // kommt dieser Code halt irgendwo in deinem Programm int main() { unsigned long anzPanzer = 23; unsigned long gegAnzPanzer = 42; unsigned long anzSoldaten = 11; unsigned long gegAnzSoldaten = 33; unsigned long PLeben = 1000; unsigned long PAngriffskraft = 500; unsigned long SLeben = 100; unsigned long SAngriffskraft = 35; unsigned long gegPLeben = 1000; unsigned long gegPAngriffskraft = 500; unsigned long gegSLeben = 100; unsigned long gegSAngriffskraft = 35; Panzer templateEigenePanzer(1000, 500); Soldaten templateEigeneSoldaten(100, 35); Panzer templateGegnerPanzer(1000, 500); Soldaten templateGegnerSoldaten(100, 35); Streitkraefte EigeneArmee; Streitkraefte GegnerArmee; // Bau-Routinen // z.B.: // // EigeneArmee.Panzerstreitkraefte.push_back(templateEigenePanzer); angriff(EigeneArmee, GegnerArmee); // call-by-value, sollte man dann später // natürlich ändern return 0; } // ## Angriff ################################################################## // Angriffsfunktion mit etwas anderer Logik als zuvor (last man standing, // Panzer greifen keine Soldaten an und umbekehrt) void angriff(Streitkraefte Angreifer, Streitkraefte Verteidiger) { short einheitenAngreifer = Angreifer.Panzerstreitkraefte.size() + Angreifer.Soldatengruppen.size(); short einheitenVerteidiger = Verteidiger.Panzerstreitkraefte.size() + Verteidiger.Soldatengruppen.size(); // -- Panzer --------------------------------------------------------------- if (Angreifer.Panzerstreitkraefte.size() == Verteidiger.Panzerstreitkraefte.size()) { Angreifer.Panzerstreitkraefte.clear(); Verteidiger.Panzerstreitkraefte.clear(); } if (Angreifer.Panzerstreitkraefte.size() < Verteidiger.Panzerstreitkraefte.size()) { while (Angreifer.Panzerstreitkraefte.size() != 0) { Angreifer.Panzerstreitkraefte.pop_back(); Verteidiger.Panzerstreitkraefte.pop_back(); } } if (Angreifer.Panzerstreitkraefte.size() > Verteidiger.Panzerstreitkraefte.size()) { while (Verteidiger.Panzerstreitkraefte.size() != 0) { Angreifer.Panzerstreitkraefte.pop_back(); Verteidiger.Panzerstreitkraefte.pop_back(); } } // -- Soldaten ------------------------------------------------------------- if (Angreifer.Soldatengruppen.size() == Verteidiger.Soldatengruppen.size()) { Angreifer.Soldatengruppen.clear(); Angreifer.Soldatengruppen.clear(); } if (Angreifer.Soldatengruppen.size() < Verteidiger.Soldatengruppen.size()) { while (Angreifer.Soldatengruppen.size() != 0) { Angreifer.Soldatengruppen.pop_back(); Verteidiger.Soldatengruppen.pop_back(); } } if (Angreifer.Soldatengruppen.size() > Verteidiger.Soldatengruppen.size()) { while (Verteidiger.Soldatengruppen.size() != 0) { Angreifer.Soldatengruppen.pop_back(); Verteidiger.Soldatengruppen.pop_back(); } } if (Angreifer.Panzerstreitkraefte.size() == 0 && Angreifer.Soldatengruppen.size() == 0) { // ANGREIFER HAT VERLOREN!!! } if (Verteidiger.Panzerstreitkraefte.size() == 0 && Verteidiger.Soldatengruppen.size() == 0) { // VERTEIDIGER HAT VERLOREN!!! } }Das ganze ist als Hinweissammlung und Baukasten zu verstehen, hatte jetzt nicht die Zeit, das zu prüfen und zu kompilieren, aber ich denke, man kann im Ansatz erkennen, was der Code nach ein paar Modifikationen bewerkstelligen sollte. Auch sollte auffallen, dass die objektorientierte Variante weitaus mehr Möglichkeiten bietet, auch wenn ich viele davon gar nicht verwendet habe.
-
Hammer! Danke, endlich ein Ansatz den ich versteh, man hast du dir eine Arbeit gemacht.
Vielen dank!
-
Ähm. Der zweite Ansatz ist doch eher fragwürdig. Mal abgesehen davon, daß da ein paar dicke Fehler im Code sind (ok, das kann in der Eile passieren), ist das Konzept nicht in Ordnung. Im Orignal-Quelltext wird von state-losen Einheiten ausgegegangen, d.h. zwei Einheiten des gleichen Types sind ununterscheidbar. In dem Fall genügt ein einfacher Zähler und man braucht keinen std::vector. Du gibst in deinem Beispiel den Einheiten zwar Attribute, aber du verwendest diese nirgendwo in der Kampfauswertung (hoffe mal, ich habe da nichts übersehen; es ist schon spät
).
-
Ja schon klar, und was mir zusätzlich zu dem, was Z2 gesagt hat, auch noch aufgefallen ist: Die Werte der Panzer und Soldaten für den Spieler und den Verteidiger sind überhaupt nicht verschieden, also ist hier die Unterscheidung eigentlich auch nicht notwendig.
-
proggaholic schrieb:
abend,
Zum Originalquelltext: Den habe ich erst gesehen, als ich schon so 3/4 hatte, da will ich mich jetzt ehrlich gesagt nicht einarbeiten

Hehe, danke, danke du hast schon genug getan^^
Ihr sollt mich ja nicht komplett übercoden hier...
Jetzt habe ich nen guten Ansatz das zusammenschustern mach ich dann noch selber.Das der Code noch so ziemlich unsauber ist liegt daran das mir die Erfahrung fehlt, aber sowas braucht ja nunmal seine Zeit.

-
So, bin nochmal etwas drüber gegangen, und ein paar Sachen habe ich gleich verbessert. Zudem bestand ja nicht wirklich der Anspruch, dass der Pseudo-Code hier am Ende lauffähig oder gar vollständig sein sollte.
-
Ich würde den ganzen aufwand noch mit entweder Polymorhphismus oder instanzen veringern. Warum immer wieder eine Klasse Class Soldat, Class Panzer, etc...
mache doch
class Einheit { stärke; verteidigung; ... } Einheit panzer; Einheit Soldat; ...
-
Du solltest vieleicht noch eine Funktion implantieren, die es dir erlaubt auf einen Schlag gleich mehrere Einheiten zu bauen und eine weitere, die dir die Entwicklung deiner Einheiten erlaubt, sodass deine Panzer, oder Soldaten stärker werden, bzw. die def steigt.
-
Ich finde deine Idee mit dem Spiel super (warum hab ich eigentlich niemals so etwas gemacht
). Was dein Kampfskript angeht, so könntest du doch einfach ein bisschen mit den Zahlen "spielen".Damit z.B. der Angreifer, mit 1000 Soldaten, den Verteidiger, mit 700 Soldaten, nicht sofort platt macht, könntest du doch "zufällig" bestimmen wieviele Soldaten aufeinmal angreifen. Dafür nimmst du die Funktion rand() die dir eine Zufallszahl zurückgibt. Und damit es nicht irgrendeine Zufallszahl (1234323) ist, benutzt du den Modulo Operator (%) um eine Zahl von 0 bis AnzahlSoldaten zu kriegen
//ich nehme jetzt mal das Streitkräfte Struct als Beispiel und gehe davon aus das darin die Angriffs- und Verteidigungswerte, sowie die Einheitenanzahl drin steht void Angriff(Streitkraefte& Angreifer, Streitkraefte& Verteidiger) { srand( (unsigned)time( NULL ) ); //zufallszahlengenerator initialisieren (gehört einfach dazu) int AngreifendeEinheiten = rand() % Angreifer.AnzahlSoldaten; //wenn AnzahlSoldaten = 1000, dann ergibt das eine zufallszahl von 0 - 1000 int Verteidigung = (Verteidiger.AnzahlSoldaten * Verteidiger.SLeben) * 1,2; // 1,2 = +20% Verteidigungsbonus (1,3 wäre dann 30% Bonus usw...) int Angriff = AngreifendeEinheiten * Angreifer.SAngriff; //jetzt kannst du ganz normal die differenz bilden int restLeben = Verteidigung - Angriff; restleben = restleben * 0,2; //jetzt wieder den Verteidigungsbonus (20%) Abziehen, sonst hättest du im ungünstigsten Fall nach einem Angriff mehr Soldaten übrig als du vorher hattest :) //damit errechnest du wieviel Soldaten letztendlich den Angriff überlebt haben (Bsp: restLeben = 500, Verteidiger.SLeben = 50; 500 / 50 = 10 Soldaten überlebt) int ueberlebnede = restLeben / Verteidiger.SLeben; //jetzt noch Verteidiger Armee auf den neuen Wert setzen Verteidiger.AnhahlSoldaten = ueberlebende; }In der nächsten Runde könnten dann die Verteidiger ebenfalls die Angreifer Angreifen. Und voilá, der Gegner hat Verluste. Man müsste schon mit einer großen Armee angreifen, um zufällig soviel Angriffskraft zu erhalten, damit man den Gegner verlustlos schlägt.
Achja, denk daran das der Verteidigungsbonus auch für den Angreifer gilt, wenn du die selbe Funktion für den Gegenschlag benutzt (was du tun solltest). Am besten du übergibst irgendwelche boni immer der Angriffsfunktion.