Wegfindefunktion mit Hindernissen



  • Hi zusammen

    Ich schreibe gerade ein Pacman und will da natürlich auch gegner einbaun die KI soll sich auf dem Spielfeld zurechtfinden das er als 2 dim arry bekommt das sieht in ausgegebener Form ca so aus:

    2222222222222222222222222222222222222222
    2000000000000000022200000000000000000002
    2041111114111114022204111111111111111402
    2010000001000001022201000000000000000102
    201022220102220102220100...
    ...

    wobei 1 die Bahn ist auf der die KI sich bewegen soll 0 ein leeres Feld ohne Bedeutung ist 2 eine Mauer und 4 sind Punkte auf denen sie die Richtung wechseln kann aber nicht muss. Ich habe die Richtungen wie folgt definiert:

    #define Links  10
    #define Unten  20
    #define Rechts 30
    #define Oben   40
    

    Die KI wird als einfaches X dargestellt.

    So nun mein Problem:

    if(Spielfeld[gy-1][gx-20]==4)                                               
        richtung=(random(3)+1)*10;
    
      switch(richtung){
        case 10 : if(Spielfeld[gy]  [gx-2] != 2) gx--; break;                
        case 30 : if(Spielfeld[gy]  [gx+2] != 2) gx+;  break;                    
        case 20 : if(Spielfeld[gy+2][gx]   != 2) gy++; break;              
        case 40 : if(Spielfeld[gy-2][gx]   != 2) gy--; break;                
        default : break;                                                          
      }//switch
    

    So nun mein problem: Irgendwie bewegt sich meine KI immer gleich nähmlich von der Startposition zum nächsten Wendepunkt und wieder zurück und ich komm nicht dahinter warum kann mir da wer helfen?



  • Erstmal kann es sein, daß du immer zwei Schritte vorwärts gehst?

    Und zweitens: Wieso fragst du in der if()-Abfrage ein Feld ab, das meilenweit von deiner Position entfernt ist? (ich gehe mal davon aus, daß "spielfeld[gy][gx]" die aktuelle Position der KI ist)



  • nein das kann nicht sein damit prüfe ich ob in 2 schritte weiter eine Mauer ist.

    Was meinst du mit meilenweit entfernt ich verstehe nicht was du meinst



  • Hmm, vielleicht solltest du eher überprüfen, ob auf dem Feld vor dir eine "Schiene" ist.

    bauarbeiterjoe schrieb:

    Was meinst du mit meilenweit entfernt ich verstehe nicht was du meinst

    Du stehst auf Feld gx/gy und prüfst nach, ob im Feld gx-20/gy-1 ein Wendepunkt ist - was bringt das?

    PS: Warum definierst du die Richtungen nicht als 0,1,2,3?



  • Ich defienier die aus dem Grund nicht 1234 damit ich nicht in konflikt mit dem Spielfeld arry kommen kann.

    ganz einfach Mein Spielfeld misst 41*43 so groß ist auch mein arry. deine Frage lässt sich dadurch beantworten das ich das Spielfeld nicht auf der position 1/1 zeichne sondern auf 20/1 damit es in der mitte ist. Jetzt wären aber die koordinaten um 20 mehr als das Feld darum ziehe ich 20 ab damit ich auf den passenden Feldwert komme. Ist vielleicht keine Elegante lösung aber das ist ja jetzt egal



  • bauarbeiterjoe schrieb:

    Ich defienier die aus dem Grund nicht 1234 damit ich nicht in konflikt mit dem Spielfeld arry kommen kann.

    Das dürfte eigentlich keine Konflikte ergeben - zumindest solange du Richtungen und Hindernisse auseinanderhalten kannst.

    ganz einfach Mein Spielfeld misst 41*43 so groß ist auch mein arry. deine Frage lässt sich dadurch beantworten das ich das Spielfeld nicht auf der position 1/1 zeichne sondern auf 20/1 damit es in der mitte ist. Jetzt wären aber die koordinaten um 20 mehr als das Feld darum ziehe ich 20 ab damit ich auf den passenden Feldwert komme. Ist vielleicht keine Elegante lösung aber das ist ja jetzt egal

    Dann solltest du diese Koordinaten-Transformation aber auf ALLE Tests bezüglich der Spielfeld-Position anwenden und nicht nur auf die Überprüfung nach den Wendepunkten (auf deutsch: wenn du davon ausgehst, daß dein Robot an Position gx-20/gy-1 steht, solltest du auch im Umfeld um diese Koordinaten nach Hindernissen suchen).



  • Um auf die eigentliche Frage zurueckzukommen: Was fuer eine random-Funktion verwendest Du? Wenn ich 'man random' eingebe, gibt es random nur ohne Argumente, die einen int zurueckgibt. Auf der man-page von rand steht dann auch geschrieben, wie man sinnvoll Zufallszahlen zwischen 1 und 4 generiert:
    richtung = 1+ (int)(4.0*rand()/(RAND_MAX+1.0));

    Hast Du schonmal ausgeben lassen, welche Zufallszahlen bei Dir generiert werden?

    Noch ein Tip: Wenn Du die Richtungen als Makro definierst, kannst Du sie ja auch im Code einsetzen, oder?



  • ne so hab ich das noch nie gemacht ich habs so gemacht: richtung = random(3)+1;
    so krieg ich 1-4 raus.



  • Hast Du denn schonmal in dem Pacman code ausgeben lassen, ob die Aktionen mit den generierten Zahlen uebereinstimmen? Laesst sich doch recht leicht mit einem
    std::clog << richtung << '\n';
    Vor der switch-Anweisung rausfinden.



  • Da tritt nur n kleines Problem auf ich hab nähmlich nicht den hauch einer anhnung was das std::.... heissen soll



  • bauarbeiterjoe schrieb:

    Da tritt nur n kleines Problem auf ich hab nähmlich nicht den hauch einer anhnung was das std::.... heissen soll

    Tut mir leid, das ist C++. Habs Forum verwechselt.
    Also eher sowas wie
    printf("Richtung: %d\n", richtung);



  • Die Richtung stimmt aber ich brauch ne Funktion damit er einen Weg abfahren kann.



  • Deine switch-Anweisung sieht, zumindest, wenn man nur den CodeAusschnitt betrachtet, den Du uns geschickt hast, nicht korrekt aus, zum Beispiel:

    case 10 : if(Spielfeld[gy]  [gx-2] != 2) gx--; break;
    

    1. Punkt, Die Indizes fuer das Feld:
    Deiner 'random' Anweisung nach ist das aktuelle Feld gegeben durch
    Spielfeld[gy-1][gx-20]. Solltest Du dann nicht auch in den case's von diesen
    Koordinaten ausgehen, also in etwa

    case 10 : if(Spielfeld[gy-1]  [(gx-20)-1] != 2) gx--; break;
    

    2. Punkt: Wenn das Zielfeld eine Mauer ist, was passiert dann? Solltest Du dann nicht dafuer sorgen, dass eine andere Richtung eingeschlagen wird? Es wird aus dem Code nicht deutlich, dass dies geschieht.



  • Da hast du recht.

    Ich hab jetzt mal meine ganzen Grauen Zellen zusammengeworfen und folgendes kamm raus:

    Die Funktion sollte ausgehend von der position der KI das nächste Feld mit einer 4 drin ansteuern. d.h. Es müsste in alle vier Richtungen prüfen wie weit es bis dahin ist und dann zufällig eine Route wählen. die Koordinaten des genauen Weges sollen in ein 2 dim array stehen. Und dann soll er einfach immer zur nächsten Routenposition Gehen dort beginnt das ganze wieder von vorne. So hab ich kein problem mehr mit den Mauern.

    meine Idee sieht so aus:

    [code]
    bool berechnet=0;
    int Grich;
    int Weg, WegL, WegR, WegU, WegO;
    i=0;
    if(berechnet==0){
    while (true){
    if(Spielfeld[gy-1] [gx-20-i] != 4) WegL++;//Weg nach Links erhöhen
    if(Spielfeld[gy-1+i][gx-20] != 4) WegU++;//Weg nach Unten erhöhen
    if(Spielfeld[gy-1] [gx-20+i] != 4) WegR++;//Weg nach Rechts erhöhen
    if(Spielfeld[gy-1-i][gx-20] != 4) WegO++;//Weg nach Oben erhöhen
    i++;
    }//while
    berechnet=1;
    Grich = random(3)+1;
    switch(Grich){
    case 1 : Weg=WegL; break;
    case 2 : Weg=WegU; break;
    case 3 : Weg=WegR; break;
    case 4 : Weg=WegO; break;
    }//switch
    }//if(berechnet==0)

    Nur irgendwie hab ich keinen Plan wie ich die Route in meinen arry reinspeichere.



  • Du solltest in der switch(Grich)-Anweisung auf jeden Fall deine Position korrigieren (indem du gx und gy je nach Richtung um die Weg*-Werte erhöhst/veringerst):

    switch(Grich){ 
    case 1 : Weg=WegL; gx-=WegL; break; 
    case 2 : Weg=WegU; gy+=WegU; break; 
    case 3 : Weg=WegR; gx+=WegR; break; 
    case 4 : Weg=WegO; gy-=WegO; break; 
    }//switch
    

    (und um die Route mitzuschreiben, brauchst du ein entsprechend großes Array von (z.B.) "struct pos{int x,y;};", in das du in jedem Schritt die Zwischenpositionen einträgst)



  • Danke die Idee mit struct ist gut die werd ich gleich probieren.


Anmelden zum Antworten