Zufalls Funktion
-
Möglicherweise - aber da brauchst du schon sehr exakte Geräte, um dein Wunsch-Ergebnis herbeizutelefonieren
(und für so einen Chat-Bot müsste die Pseudo-Verteilung von rand() eigentlich exakt genug sein)
-
Stromberg schrieb:
Bei meinem Zufall darf das aber nicht passieren, schon klar das bei einem Zufall auch mal 2 Zahlen hintereinander kommen aber
Hätte man sich fast denken können. Du setzt an der komplett falschen Stelle an. Die Lösung ist nicht
int random( int min, int max )(ja, Bezeichner dürfen lang & sinnvoll sein) kaputt zu machen, sondern dein Bot muss sich selber merken welche Antwort er zuletzt gegeben hat (ggf mehr als nur die letzte ->std::deque,std::list).
-
Stromberg schrieb:
...1.die Zufallsfunktion in C++ find ich soieso irgendwie merkwürdig, das ist kein richtiger Zufall sondern es wird nur errechnet und ist somit kein Zufall mehr weil mans immer ausrechnen kann. 2.was ist eigentlich Zufall ist das was C++ da jetzt macht Zufall oder ist es Zufall wenn man diesen nicht errechnet sondern "zufällig" vom Treiber rauschen bekommt (hab da mal sowas gelesen das man das mit so ner Speziellen Hardware machen kann), oder ist es nur Zufall wenn man würfelt oder gibts überhaupt gar keinen Zufall. Ich find das is jetzt schon fast bisschen philosophisch.
3. Bei mir dürfen keine gleichen Zahlen hintereinander kommen, da http://www.c-plusplus.net/forum/viewtopic-var-t-is-169080-and-start-is-0.html da ist mein Programm bisschern weiter gepostet (jetzt funktioniert alles und es ist bisschen umgebaut) zumindestens will ich nicht das der "Bot" zweimal den gleichen Satz sagt. Wäre ja immer blöd wenn der dreimal hintereinander sagt "Schön dich zu sehen." "Schön dich ....."........".*** semantic underflow error ***
Sorry, aber das kann kein Mensch lesen.
Übrigens: Zufall ist mitnichten "philospohisch" (im Sinne von "kann jeder machen, wie er will"), sondern durchaus streng mathematisch zu fassen.
Du musst Dich halt entscheiden, welches Zufallskriterium Du brauchst (und in welchem Maß): Unvorhersagbarkeit ? gleichförmige Verteilung ? Unabhängigkeit von bestimmten Parametern (z.B. Zeit) ? ....Ersteres also schonmal nicht, denn Deine Forderung "x(i) != x(i-1)" bricht damit - übrigens sitzt Du damit einem Trugschluß über den Zufall auf. Darf denn der übernächste Wert wieder gleich sein ? Oder auch das nicht ? Und der überübernächste ? ....
Mit jeder weiteren Abhängigkeit schränkst Du den Zufall weiter ein - obwohl Du ihn doch eigentlich erweitern willst, oder ?Ach ja: "Echten Zufall" (im Sinne von underterministischem Verhalten) wirst Du mit deterministischen Algorithmen sowieso nicht hinbekommen - egal, wie Du sie noch "verrickelst".
Dann lies lieber gleich den (ungenutzten) Eingang der TV-Karte aus.Gruß,
Simon2.
-
Oder du häckst ein paar Dialog-Abläufe hart ein und läufst diese einfach durch. Dann hast du zwar mehrere Abläufe fest vorgegeben, aber garantiert nichts doppelt. Du wirst dann zwar immer noch eine random-Funktion brauchen, um einen der vielen Dialog-Abläufe zufällig auszuwählene, aber das ist dann wirklich nicht mehr anders zu lösen.
Wenn du andere Random-Algos brauchst: in der Boost-Library sind welche vorhanden. Habe von der Materie selber aber keine Ahnung. Sieht aber interessant aus:
http://www.boost.org/libs/random/index.htmlDiese random-Lib ist auch im TR1 drin, dürfte hier im Forum aber noch niemand haben.
-
Hier wäre jetzt die Zufallsfunktion die eigentlich immer die letzten 10 Zufallszahlen speichert, sodass der Bot nie hintereinander 10 gleiche Sätze ausliest. Hm aber irgendwie bin ich mir nicht so ganz sicher ob das auch funktioniert,(also es kommen keine Errors das mein ich nicht) einerseits bilde ich mir ein das es geht andererseits hab ich mir auch schon eingebildet (Einbildung ist die schönste Bildung
) das es nicht funktioniert. (Hab halt die Zahlen mitgezählt und deren Abstände) Aber irgendwie bin ich mir überhaupt nicht mehr sicher und umso länger ich mir die Funktion anschaue, desto konfuser wird sie für mich. Obwohl ichs ja noch vor 5 min Verstanden habe. Deshalb müsst ihr jetzt mal als aussenstehende das betrachten und mir sagen ob das sch.... oder nicht.long rnd(long a,long b) { int Zufall=(rand() % (b-a+1)) + a; static int *temp=new int[10]; static int *counter=new int(0); static int *hv=new int(0); if (*counter>10) { *counter=0; } if (*hv>10) { *hv=10; } for(int i=0;i<*hv+1;i++) { if(Zufall==temp[i]) { return rnd(a,b); } } temp[*counter]=Zufall; *counter++; *hv++; return Zufall; }Dankeschön schon mal im Voraus.
-
Jo, Boost.Random ist gut. Nimm einfach boost::mt19937, das ist ein echt guter Generator. Der hat u.A. den "die hard test" bestanden, einer der härtesten Tests für Zufallszahlengeneratoren.
Zum Seeden verwendest du dann z.B. /dev/rand (*nix) bzw. CryptGenRandom (win32), dann hast du sehr sehr gute Zufallszahlen.
Und zu guten Zufallszahlen gehört auch dass manchmal 2x (oder auch öfters) hintereinander die gleiche Zahl kommt.
p.S.: zum Thema Bot: schreib doch einfach alle Antworten beim Initialisieren des Bots in einen Vektor, und mische den dann mit Hilfe des Zufallszahlengenerators durch. Dann gehst du einfach der Reihe nach den Vektor durch, und wenn du am Ende angekommen bist mischt du den Vektor nochmal durch und fängst von vorne an.
Und natürlich tuts für so eine einfache und unkritische Aufgabe auch rand()

-
Die Idee mit den vectoren durchmixen is echt clever
mal schaun ob ich das umsetze, aber was sagst du zu der Funktion?
Dankeschön schon mal im Voraus.
-
Die Idee mit den vectoren durchmixen is echt clever
mal schaun ob ich das umsetze, aber was sagst du zu der Funktion?
Dankeschön schon mal im Voraus.
-
Die Funktion sieht recht nett aus, nur daß du das new dort nicht unbedingt brauchst:
long rnd(long a,long b) { int Zufall=(rand() % (b-a+1)) + a; static int temp[10]; static int counter=0; static int hv=0; ... }Eventuell könntest du die Rekursion noch durch eine Schleife ersetzen:
while(find(temp,temp+hv,Zufall)!=temp+hv) Zufall = rand()%(b-a+1) + a;
-
hustbaer schrieb:
...ist ein echt guter Generator...
Dass Problem ist aber wohl, dass er gar keine echten Zufallszahlen will. Letztlich will Stromberg auf eine Strategie hinaus - und da ist echter Zufall nur bedingt hilfreich.
@Stromberg: Ich würde Dir raten, "Zufallszahl" und "Strategie" komplett zu trennen - so wie Du schon damit anfängst, indem Du die Regel "Zug darf nicht innerhalb der letzten 10 Züge vorkommen" aufstellst. Werde Dir doch erstmal klar darüber, welche sonstigen Strategieregeln Du verfolgen möchtest ... das ist viel wesentlicher als die Qualität der Zufallszahl.Gruß,
Simon2.
-
Stromberg schrieb:
...
... static int *counter=new int(0); static int *hv=new int(0); ......
Kann es sein, dass Du von Java kommst ?

Gruß,
Simon2.
-
Stromberg schrieb:
Die Idee mit den vectoren durchmixen is echt clever
mal schaun ob ich das umsetze, aber was sagst du zu der Funktion?
Dankeschön schon mal im Voraus.Ich würde auf jede Fall das
static int *temp=new int[10]; static int *counter=new int(0); static int *hv=new int(0);in das
static int temp[10] = {}; static int counter = 0; static int hv = 0;ändern.
-
Ja halt mh jetzt hab ich ein Verständnis Problem! Ich hab ja das hier gemacht:
static int *temp=new int[10]; static int *counter=new int(0); static int *hv=new int(0);Weil: Wenn ich die Variablen nicht auf dem Heap reserviere dann werden die doch nach Beendigung der Funktion wieder gelöscht. Aber ich will doch das die auch beim neuen Funktionsaufruf scon mitgezählt haben. Weil was auf dem Heap deklariert wird, da is es doch so das es erst wieder gelöscht wird wenn man die halt mit delete löscht. Und static benutze ich da ja nur, das sie nur einmal deklariert werden und nicht andauernd überschrieben werden und es dann Speicherlecks gibt!
Oder macht static etwa etwas anderes hab ich hier irgendwas falsch verstanden.
Bitte klärt mich auf :)! Dankeschön schon mal im Voraus.PS: Is mir noch aufgefallen hier is n kleiner Fehler drin. Gut das ich den selber gefunden habe is n peinlicher Fehler.
long rnd(long a,long b) { int Zufall=(rand() % (b-a+1)) + a; static int *temp=new int[10]; //<-- wenn das Array 10 Felder hat dann is es ja von 0-9 static int *counter=new int(0); static int *hv=new int(0); if (*counter>10) //Dann muss es hier aber heißen if(*counter>9) { *counter=0; } if (*hv>10) //Und hier muss es heißen is *hv>9 { *hv=10; } for(int i=0;i<*hv+1;i++) { if(Zufall==temp[i]) { return rnd(a,b); } } temp[*counter]=Zufall; *counter++; *hv++; return Zufall; }
-
Wenn du die Variable als 'static' deklarierst, wird sie nicht auf dem Stack untergebracht und überlebt schon von sich aus das Ende der Funktion. Da ist es nicht nötig, sich noch zusätzlichen Heap-Speicher anzufordern (der übrigens nie wieder freigegeben wird).
PS: Und den Flüchtigkeitsfehler hast du vermutlich an der falschen Stelle ausgemerzt - lass lieber das "i<*hv+1" in der for-Schleife weg.
-
So das wäre jetzt dei vollendete rnd Funktion. Ist doch in Ordnung oder? Einen Zeiger auf den Heap musste ich leider drin lassen.
//c ist in welchem Abstand eine Zahl wieder kommen darf! //Also wenn eine Zufallszahl gekommen ist darf sie erst nach c anderen //Zufallszahlen wieder kommen. long rnd(long a,long b,int c) { int Zufall=(rand() % (b-a+1)) + a; static int *temp=new int[c]; static int counter=0; static int hv=0; if (counter>c) { counter=0; } if (hv>c) { hv=c; } for(int i=0;i<hv+1;i++) { if(Zufall==temp[i]) { return rnd(a,b,c); } } temp[counter]=Zufall; counter++; hv++; return Zufall; }So is ja alles schön und gut jetzt, aber mir ist aufgefallen das ich die Funktion ja nur einmal einsetzen kann (Wie gesagt ich benutz die ja um bei meinem Bot durch Zufall vector strings auszulesen). Mh weil wenn ich sie dann nochmal starte dann sind ja immer noch die alten Werte drin. Versteht jemand was ich mein? Das is ja natürlich beabsichtig das er sich die Werte merkt, ja aber wenn ich dann z.B. für meinen Bot aus einem anderen vector string lese dann stehen in temp ja noch die alten Werte und so drin. Und *temp kann man nicht überschreiben da es ja static ist und wenn es nicht static wäre würde es sich aber nichts mehr merken und würde dauernd überschrieben werden --> SPEICHERLECKS! Mh äh is jetzt irgendwie so eine Zwickmühle! Kann ich die Funktion jetzt echt nur einmal auf einen vector ansetzen oder lässt sich da noch was dran drehen?
Dankeschön schon mal im Voraus.
-
Du könntest deinen Zufallsgenerator als Objekt anlegen:
class Random { long min,max,count; std::deque<long> values; public: Random(long a,long b,long c) : min(a),max(b),count(c) {} long getZahl() { long Zufall; do Zufall=rand()%(max-min+1)+min; while(find(values.begin(),values.end(),Zufall)!=values.begin()); values.push_back(Zufall); if(values.size()>count) values.push_front(); return Zufall; } };
-
Ehm, vielleicht hat mich Java berufsmäßig schon verdorben, aber muß das nicht heißen:
*(temp[counter])=Zufall;Weil sonst setzt du ja die Speicheradresse zufällig, und nicht den int-Wert.
Und wenn du mehrere Vectoren durchlaufen willst, müsstest du nur den Counter wieder auf Null zurück setzen. Aber irgendwie ist dein Design wirklich etwas crazy.
Ich würde das ganze irgendwie anders lösen. Ich würde der rnd-Funktion gleich nen vector übergeben und gleich umsortieren.
-
Stromberg schrieb:
So das wäre jetzt dei vollendete rnd Funktion. Ist doch in Ordnung oder? Einen Zeiger auf den Heap musste ich leider drin lassen.
//c ist in welchem Abstand eine Zahl wieder kommen darf! //Also wenn eine Zufallszahl gekommen ist darf sie erst nach c anderen //Zufallszahlen wieder kommen. long rnd(long a,long b,int c) { int Zufall=(rand() % (b-a+1)) + a; static int *temp=new int[c]; static int counter=0; static int hv=0; if (counter>c) { counter=0; } if (hv>c) { hv=c; } for(int i=0;i<hv+1;i++) { if(Zufall==temp[i]) { return rnd(a,b,c); } } temp[counter]=Zufall; counter++; hv++; return Zufall; }Nein, das new muss nicht drin bleiben, static ist static, da musst du nicht new bemühen.
Weiss nicht was daran so schwer zu verstehen ist.
-
Ja doch new muss schon sein, weil das array temp ist doch noch ungewisse, man weiß doch nicht wie groß es wird deshalb kommt es auf den Heap?
Meinst du etwa so?static int temp[c];Da kommt bei mir n Error:
Compiling: C:\MinGW\Andi\C++\rnd funktion.cpp
C:\MinGW\Andi\C++\rnd funktion.cpp: In functionlong int rnd(long int, long int, int)': C:\\MinGW\\Andi\\C++\\rnd funktion.cpp:23: error: storage size oftemp' isn't constant
C:\MinGW\Andi\C++\rnd funktion.cpp:23: error: size of variable 'temp' is too large
Process terminated with status 1 (0 minutes, 0 seconds)
2 errors, 0 warnings
-
Mit new ist schon korrekt, wenn die Größe erst zur Laufzeit bekannt ist. Nur vergisst du immer am Ende deine mit new reservierten ints mit delete zu zerstören!!!
Speicherleck!!!Und dann brauchst du es auch nicht static machen, wenn du es eh bei jedem Durchlauf neu anlegen mußt.