md-sort.inc von Slice

Wichtiger Hinweis: Bitte ändert nicht manuell die Schriftfarbe auf schwarz sondern belasst es bei der Standardeinstellung. Somit tragt ihr dazu bei dass euer Text auch bei Verwendung unseren dunklen Forenstils noch lesbar ist!

Tipp: Ihr wollt längere Codeausschnitte oder Logfiles bereitstellen? Benutzt unseren eigenen PasteBin-Dienst Link
  • new Float:Hospitals[][] =
    {
    {1.0, 2.0, 3.0},
    {2.0, 3.0, 1.0},
    {3.0, 1.0, 2.0}
    };


    new Float:PostDeathSpawn[MAX_PLAYERS][3];


    public OnPlayerDeath(playerid, killerid, reason)
    {
    new Float:dist[3];
    dist[0] = GetPlayerDistanceFromPoint(playerid, Hospitals[0][0], Hospitals[0][1], Hospitals[0][2]);
    dist[1] = GetPlayerDistanceFromPoint(playerid, Hospitals[1][0], Hospitals[1][1], Hospitals[1][2]);
    dist[2] = GetPlayerDistanceFromPoint(playerid, Hospitals[2][0], Hospitals[2][1], Hospitals[2][2]);


    SortDeepArray(dist, 0, SORT_ASC); //ERROR LINE


    PostDeathSpawn[playerid][0] = Hospitals[0][0];
    PostDeathSpawn[playerid][1] = Hospitals[0][1];
    PostDeathSpawn[playerid][2] = Hospitals[0][2];
    return 1;
    }


    public OnPlayerSpawn(playerid)
    {
    SetPlayerPos(playerid, PostDeathSpawn[playerid][0], PostDeathSpawn[playerid][1], PostDeathSpawn[playerid][2]);
    return 1;
    }


    error 001: expected token: ",", but found "["
    warning 215: expression has no effect
    error 001: expected token: ";", but found "]"
    error 029: invalid expression, assumed zero
    fatal error 107: too many error messages on one line


    Falls jemand Erfahrung mit dieser Include hat, wäre es nett, wenn er/sie helfen würde! :)

  • SortDeepArray(dist, 0, SORT_ASC); //ERROR LINE


    Du sortierst ein 1 dimensionales Array und verwendest es danach nicht mehr? :huh:


    Ich hab dir mal einen kleinen Algorithmus geschrieben, der 1 dimensionale Arrays sortiert:


    //Schreib das so:
    new Float:dist[3];
    dist[0] = GetPlayerDistanceFromPoint(playerid, Hospitals[0][0], Hospitals[0][1], Hospitals[0][2]);
    dist[1] = GetPlayerDistanceFromPoint(playerid, Hospitals[1][0], Hospitals[1][1], Hospitals[1][2]);
    dist[2] = GetPlayerDistanceFromPoint(playerid, Hospitals[2][0], Hospitals[2][1], Hospitals[2][2]);


    d_Sort(dist, sizeof dist);
    //Und du solltest hier dann auch dist verwenden...



    //unten im Skript
    stock d_Sort(Float:x[], const anz) {
    for (new i,Float:tmp,j; i < anz; i++) {
    for (j=0; j < anz - i - 1; j++) {
    if (x[j] > x[j + 1]) tmp = x[j],x[j] = x[j + 1],x[j + 1] = tmp;
    }
    }
    return 1;
    }


    mfg. :thumbup:

    ast2ufdyxkb1.png


    Leute, lernt scripten und versucht mal lieber etwas selber zu schreiben, als es aus einem GF zu kopieren. :S

  • Mein Problem liegt jetzt ja nicht an einem fehlenden Algorithmus, sondern daran, wie ich von der Distanzberechnung wieder auf die richtigen Koordinaten im Array verweise.
    "dist" speichert ja die Distanz zu jedem Punkt und wird dann praktisch aufsteigend sortiert. Wie kann ich zurückverfolgen welche Distanz zu welchen Koordinaten gehören?

  • Mein Problem liegt jetzt ja nicht an einem fehlenden Algorithmus, sondern daran, wie ich von der Distanzberechnung wieder auf die richtigen Koordinaten im Array verweise.
    "dist" speichert ja die Distanz zu jedem Punkt und wird dann praktisch aufsteigend sortiert. Wie kann ich zurückverfolgen welche Distanz zu welchen Koordinaten gehören?


    Achsoo :D


    Jetzt verstehe ich was du da versuchst, schreibe es so:


    public OnPlayerDeath(playerid, killerid, reason)
    {
    new Float:dist[3];
    dist[0] = GetPlayerDistanceFromPoint(playerid, Hospitals[0][0], Hospitals[0][1], Hospitals[0][2]);
    dist[1] = GetPlayerDistanceFromPoint(playerid, Hospitals[1][0], Hospitals[1][1], Hospitals[1][2]);
    dist[2] = GetPlayerDistanceFromPoint(playerid, Hospitals[2][0], Hospitals[2][1], Hospitals[2][2]);


    new idx = d_Sort(dist, sizeof dist);


    PostDeathSpawn[playerid][0] = Hospitals[idx][0];
    PostDeathSpawn[playerid][1] = Hospitals[idx][1];
    PostDeathSpawn[playerid][2] = Hospitals[idx][2];
    return 1;
    }


    stock d_Sort(const Float:x[], const anz) {
    new t;
    for (new i=1,Float:tmp=x[0]; i < anz; i++) if(x[i] < tmp) t=i,tmp=x[i];
    return t;
    }


    mfg. :thumbup:

    ast2ufdyxkb1.png


    Leute, lernt scripten und versucht mal lieber etwas selber zu schreiben, als es aus einem GF zu kopieren. :S

  • Dann mach aus der 1 Dimension eben 2.
    http://forum.sa-mp.com/showpost.php?p=1866779&postcount=1
    http://forum.sa-mp.com/showpost.php?p=1867509&postcount=14
    Die Beispiele erklären es ganz gut. Du nimmst pro Datensatz ein Float (für die Distanz) und eine Zahl (zB für den Index, der diese Distanz bei Hospitals beschreibt)



    // enum anlegen mit Float:distanz und hospital_index und für dist[3][enum] nutzen.
    dist[0][distanz] = GetPlayerDistanceFromPoint(playerid, Hospitals[0][0], Hospitals[0][1], Hospitals[0][2]);
    dist[0][hospital_index] = 0;
    [...] // für 1 und 2 auch noch
    SortDeepArray( dist , distanz , SORT_ASC);
    // dist[0] ist jetzt mit distanz und hospital_index der "nächste Ort"

  • Ich find das alles ziemlich verwirrend... Ich hab das hier jetzt.
    enum hSpawn
    {
    Float:Distance,
    hIndex
    }


    new dist[MAX_PLAYERS][4][hSpawn];


    new Float:Hospitals[][] =
    {
    {1177.0387, -1323.8035, 14.0510, EAST},
    {-2655.6882, 636.9452, 14.4531, SOUTH},
    {1607.2102, 1818.1615, 10.820, NORTH}
    };


    public OnPlayerDeath(playerid, killerid, reason)
    {
    dist[playerid][0][Distance] = GetPlayerDistanceFromPoint(playerid, Hospitals[0][0], Hospitals[0][1], Hospitals[0][2]);
    dist[playerid][0][hIndex] = 0;
    dist[playerid][1][Distance] = GetPlayerDistanceFromPoint(playerid, Hospitals[1][0], Hospitals[1][1], Hospitals[1][2]);
    dist[playerid][1][hIndex] = 1;
    dist[playerid][2][Distance] = GetPlayerDistanceFromPoint(playerid, Hospitals[2][0], Hospitals[2][1], Hospitals[2][2]);
    dist[playerid][2][hIndex] = 2;


    SortDeepArray(dist[playerid], Distance, SORT_ASC);
    return 1;
    }


    public OnPlayerSpawn(playerid)
    {
    SetPlayerPos(playerid, dist[playerid][0], dist[playerid][1], dist[playerid][2]);
    SetPlayerFacingAngle(playerid, dist[playerid][3]);
    return 1;
    }


    ...und bekomme folgende Errors.
    error 017: undefined symbol "SA_4"
    warning 215: expression has no effect
    error 001: expected token: ";", but found "sizeof"
    error 001: expected token: "]", but found "-identifier-"
    fatal error 107: too many error messages on one line
    Die Errormeldungen sehen für mich eher danach aus, dass etwas in der Include nicht stimmt...

  • So wie ich das sehe willst du nur das Krankenhaus herausfinden, welches dir beim Tod am nächsten ist.
    Dazu brauchst du diese ganze Sortiererei gar nicht. Außerdem war das mit der Verwendung der Variablen etwas durcheinander bei deinem Code, du hast da Sachen angegeben die gar nicht existieren.


    Schreibe es so:
    new hospitalID[MAX_PLAYERS]; //Zwischenspeicher

    new Float:Hospitals[][] =
    {
    {1177.0387, -1323.8035, 14.0510, EAST},
    {-2655.6882, 636.9452, 14.4531, SOUTH},
    {1607.2102, 1818.1615, 10.820, NORTH}
    };

    public OnPlayerDeath(playerid, killerid, reason)
    {
    new Float:dist = 999999999.0, idx, Float:tmp;
    for(new i=0; i<sizeof(Hospitals); i++) //Schleife durch alle Krankenhäuser, dynamisch.
    {
    tmp = GetPlayerDistanceFromPoint(playerid, Hospitals[i][0], Hospitals[i][1], Hospitals[i][2]);
    if(tmp < dist) //Wenn Krankenhaus näher als das zuletzt nähste.
    {
    dist = tmp;
    idx = i;
    }
    }
    hospitalID[playerid] = idx; //Nähstes Krankenhaus in den Zwischenspeicher packen
    return 1;
    }


    public OnPlayerSpawn(playerid)
    {
    new idx = hospitalID[playerid]; //Zwischenspeicher laden und Spieler an die Position setzen.
    SetPlayerPos(playerid, Hospitals[idx][0], Hospitals[idx][1], Hospitals[idx][2]);
    SetPlayerFacingAngle(playerid, Hospitals[idx][3]);
    return 1;
    }

  • Wieso setzt du "dist" auf 999999999.0?


    Damit eine hohe Distanz ensteht und schnell eine kleinere gefunden wird ;)


    Aber du hättest auch meine Funktion einfach benutzen können :D


    mfg. :thumbup:

    ast2ufdyxkb1.png


    Leute, lernt scripten und versucht mal lieber etwas selber zu schreiben, als es aus einem GF zu kopieren. :S

  • Damit eine hohe Distanz ensteht und schnell eine kleinere gefunden wird ;)


    Hätte man es dann nicht auch so machen können?


    new hospitalID[MAX_PLAYERS]; //Zwischenspeicher

    new Float:Hospitals[][] =
    {
    {1177.0387, -1323.8035, 14.0510, EAST},
    {-2655.6882, 636.9452, 14.4531, SOUTH},
    {1607.2102, 1818.1615, 10.820, NORTH}
    };

    public OnPlayerDeath(playerid, killerid, reason)
    {
    new Float:dist = -1, idx, Float:tmp;
    for(new i=0; i<sizeof(Hospitals); i++) //Schleife durch alle Krankenhäuser, dynamisch.
    {
    tmp = GetPlayerDistanceFromPoint(playerid, Hospitals[i][0], Hospitals[i][1], Hospitals[i][2]);
    if(tmp < dist || dist == -1) //Wenn Krankenhaus näher als das zuletzt nähste.
    {
    dist = tmp;
    idx = i;
    }
    }
    hospitalID[playerid] = idx; //Nähstes Krankenhaus in den Zwischenspeicher packen
    return 1;
    }


    public OnPlayerSpawn(playerid)
    {
    new idx = hospitalID[playerid]; //Zwischenspeicher laden und Spieler an die Position setzen.
    SetPlayerPos(playerid, Hospitals[idx][0], Hospitals[idx][1], Hospitals[idx][2]);
    SetPlayerFacingAngle(playerid, Hospitals[idx][3]);
    return 1;
    }

    Einmal editiert, zuletzt von Nemesus Jr. ()

  • Ja, relativ wenig zwar, aber du hast anstatt einer IF Abfrage zwei IF Abfragen, somit braucht die Abfrage theoretisch doppelt so lang. Sind zwar nur Nanosekunden, aber wenn es einfacher und schneller geht, kann man es ja so machen.


    Letztendlich spielt es keine Rolle, da zählt die persönliche Bevorzugung.