Jump to content

DuFF

Přispěvatel
  • Příspěvků

    205
  • Registrován

  • Aktivní

  • Vítězných dnů

    42

Příspěvky posted by DuFF

  1. milous sa ti snažil naznačiť, že chyba je tu:
     

    case CCP1:
    {
        DisablePlayerCheckpoint(playerid);
        SetPlayerCheckpoint(playerid,1142.7788,1264.6090,11.4266,5.0);
        autoskolac[playerid] = CCP1;
    }

    AK hráč vezme 1. checkpoint Cčka, do autoskolac ukladáš zase 1. checkpoint Cčka. Chceš tam autoskolac[playerid] = CCP2 a podobne to posunúť všade (v Cčku).

    Čo sa týka returnu, skús si najskôr prečítať ako funguje napríklad tu: https://sampwiki.blast.hk/wiki/Control_Structures#return
    Pamätám si, že keď som sa učil pawn (moja prvá skúsenosť s programovaním), tak som return dlho nechápal, až kým som nenarazil na tento článok.

    • Kappa 1
    • Líbí se mi to! (+1) 1
  2. On 19. 4. 2024 at 7:44, MrShoTys74 said:

    tento isty stock môžem kludne využívat aj na dalšie preukazy priklad?

    Tento istý stock nie, pretože v ňom "natvrdo" používaš "pVodickyB".
    Ideálne by si mal spraviť stock, ktorý dostane ako parameter číslo 0/1 reprezentujúce, či hráč vlastní/nevlastní daný preukaz, a vráti text "Vlastni"/"Nevlastni".
    Napríklad:

    stock VlastniPreukaz(vlastni)
    {
        new text[10];
        if (vlastni) 
            text = "Vlastni";
        else 
            text = "Nevlastni";
        return text;
    }
    
    // Použitie v kóde:
    VlastniPreukaz(PlayerInfo[playerid][pVodickyB])
    // Alebo pre iný preukaz:
    VlastniPreukaz(PlayerInfo[playerid][pZbrojny])

     

  3. Warning je spôsobený tým, že lokálna premenná "autoskolabb" má rovnaký názov ako stock "autoskolabb". Jedno z nich premenuj a warning by ti mal zmiznúť.

    K Hipovej odpovedi:
    Pawn compiler poskytnutý v zipe so serverom od sa-mp teamu má problémy s vracaním "string literal" - prestane reagovať.
    Mám pocit, že to je už vyriešené v compileri od Zeexa, ale nie som si istý.

    • Kappa 1
  4. před 10minutami, MrShoTys74 said:

    Ďakujem za odpoved, Ano už som si to celé prerobil a je to oveľa prehľadnejšie.

    este aby som nemusel znovu otvárať nový topic chcel som sa spýtať, spravil som si autoškolu a všetko funguje ako má ale neviem prísť ako na premennú čisla/hodnoty na text?

    priklad

    PlayerInfo[playerid][pAutoskolaB] = 0; 

    Zmenit hodnotu 0 na “Nevlastni” ?

    pri všetkých pokusoch mi to vyhadzuje errory alebo to nefunguje  a pri stocku mi prestalo reagovať pawno. 😅 uz neviem ako na to Dakujem ak by mi s tým niekto pomohol. 

    (Potreboval by som to do vypisovanie všetkých štatistík Vodičský preukaz - Nevlastním / Vlastním)

    Toto je fakt na samostatný topic a rovno prilož aj kód

  5. Ahoj, čím skôr sa naučíš správne formátovať svoj kód, tým menej podobného utrpenia zažiješ v budúcnosti. Dobrá prax je posunúť telo bloku - to medzi { a } - o 1 tabulátor (alebo 4 medzery) doprava. Potom vždy ľahko vidíš, ktorá zátvorka uzatvára ktorý blok a vieš ľahšie vložiť kód do správnej časti. Porovnaj svoj kód s formátovanou verziou v spoileri. Čo z toho sa ti ľahšie číta?
     

    Spoiler
    public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
    {
        //==============================================================================REGISTER/LOGIN======================================================================================
        switch (dialogid)
        {
            case DIALOG_REGISTER:
            {
                if (!response) return Kick(playerid);
                if (response)
                {
                    if (!strlen(inputtext)) return ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_INPUT, ""
                        COL_WHITE "Registrácia", ""
                        COL_RED "Zadali ste neplatné heslo.\n"
                        COL_WHITE "Zadajte svoje heslo nižšie a zaregistrujte si nový účet.", "Registracia", "Ukončit");
                    new INI: File = INI_Open(UserPath(playerid));
                    INI_SetTag(File, "data");
                    INI_WriteInt(File, "Password", udb_hash(inputtext));
                    INI_WriteInt(File, "Cash", 0);
                    INI_WriteInt(File, "Admin", 0);
                    INI_WriteInt(File, "Kills", 0);
                    INI_WriteInt(File, "Deaths", 0);
                    INI_WriteInt(File, "Wanted", 0);
                    INI_WriteInt(File, "Skin", 0);
                    INI_WriteInt(File, "VodickyB", 0);
                    INI_Close(File);
    
                    SetSpawnInfo(playerid, 0, 0, 1958.33, 1343.12, 15.36, 269.15, 0, 0, 0, 0, 0, 0);
                    SpawnPlayer(playerid);
                }
            }
            case DIALOG_LOGIN:
            {
                if (!response) return Kick(playerid);
                if (response)
                {
                    if (udb_hash(inputtext) == PlayerInfo[playerid][pPass])
                    {
                        INI_ParseFile(UserPath(playerid), "LoadUser_%s", .bExtra = true, .extra = playerid);
                        GivePlayerMoney(playerid, PlayerInfo[playerid][pCash]);
                        SetPlayerWantedLevel(playerid, PlayerInfo[playerid][pWanted]);
                        SetPlayerSkin(playerid, PlayerInfo[playerid][pSkin]);
                        SpawnPlayer(playerid);
                    }
                    else
                    {
                        ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_INPUT, ""
                            COL_WHITE "Prihlasenie", ""
                            COL_RED "Zadali ste nesprávne heslo.\n"
                            COL_WHITE "Pre prihlásenie zadajte svoje heslo nižšie.", "Login", "Quit");
                    }
    
                    return 1;
                }
            }
        }
    
        //=========================================================================WARPY===================================================================================================
        if (dialogid == DIALOG_WARPY)
        {
            if (!response)
            {
                //zrust
                return 1;
            }
    
            switch (listitem)
            {
                case 0:
                {
                    new vehicleid = GetPlayerVehicleID(playerid);
                    new State = GetPlayerState(playerid);
                    if (IsPlayerInAnyVehicle(playerid) && State == PLAYER_STATE_DRIVER)
                    {
                        LinkVehicleToInterior(vehicleid, 0);
                        SetPlayerInterior(playerid, 0);
                        SetVehicleZAngle(vehicleid, 227.2756);
                        SetCameraBehindPlayer(playerid);
                        SetVehiclePos(vehicleid, -1986.5483, 305.5474, 35.0071);
                        return SendClientMessage(playerid, COLOR_GREEN, "[RealnySvet] Bol si teleportovaný do San Fierro!");
                    }
    
                    SetPlayerPos(playerid, -1969.0593, 294.0901, 35.1719);
                    SetPlayerFacingAngle(playerid, 89.9102);
                    SetPlayerInterior(playerid, 0);
                    SetCameraBehindPlayer(playerid);
                    SendClientMessage(playerid, COLOR_GREEN, "[RealnySvet] Bol si teleportovaný do San Fierro!");
                }
    
                case 1:
                {
                    new vehicleid = GetPlayerVehicleID(playerid);
                    new State = GetPlayerState(playerid);
                    if (IsPlayerInAnyVehicle(playerid) && State == PLAYER_STATE_DRIVER)
                    {
                        LinkVehicleToInterior(vehicleid, 0);
                        SetPlayerInterior(playerid, 0);
                        SetVehicleZAngle(vehicleid, 227.2756);
                        SetCameraBehindPlayer(playerid);
                        SetVehiclePos(vehicleid, 1608.3900, -1719.7670, 13.3786);
                        return SendClientMessage(playerid, COLOR_GREEN, "[RealnySvet] Bol si teleportovaný do Los Santos!");
                    }
    
                    SetPlayerPos(playerid, 1606.3514, -1739.5194, 13.5469);
                    SetPlayerFacingAngle(playerid, 89.9102);
                    SetPlayerInterior(playerid, 0);
                    SetCameraBehindPlayer(playerid);
                    SendClientMessage(playerid, COLOR_GREEN, "[RealnySvet] Bol si teleportovaný do Los Santos!");
                }
    
                case 2:
                {
                    new vehicleid = GetPlayerVehicleID(playerid);
                    new State = GetPlayerState(playerid);
                    if (IsPlayerInAnyVehicle(playerid) && State == PLAYER_STATE_DRIVER)
                    {
                        LinkVehicleToInterior(vehicleid, 0);
                        SetPlayerInterior(playerid, 0);
                        SetVehicleZAngle(vehicleid, 227.2756);
                        SetCameraBehindPlayer(playerid);
                        SetVehiclePos(vehicleid, 2128.2754, 1333.6340, 10.6558);
                        return SendClientMessage(playerid, COLOR_GREEN, "[RealnySvet] Bol si teleportovaný do Las Venturas!");
                    }
    
                    SetPlayerPos(playerid, 2096.9543, 1322.6205, 10.8203);
                    SetPlayerFacingAngle(playerid, 89.9102);
                    SetPlayerInterior(playerid, 0);
                    SetCameraBehindPlayer(playerid);
                    SendClientMessage(playerid, COLOR_GREEN, "[RealnySvet] Bol si teleportovaný do Las Venturas!");
                }
            }
            return 1;
        }
        //=========================================================================Autoskola===================================================================================================
        if (dialogid == DIALOG_AUTOSKOLA)
        {
            if (response) // If they clicked 'Select' or double-clicked a weapon
            {
                switch (listitem)
                {
                    case 0:
                    {
                        GivePlayerWeapon(playerid, WEAPON_M4, 120); // Give them an M4
                    }
                    case 1:
                    {
                        GivePlayerWeapon(playerid, WEAPON_MP5, 90); // Give them an MP5
                    }
                    case 2:
                    {
                        GivePlayerWeapon(playerid, WEAPON_AK47, 120); // Give them an AK-47
                    }
                }
            }
            return 1; // We handled a dialog, so return 1. Just like OnPlayerCommandText.
        }
        return 1;
    }

     

    Na záver ešte dodám, že keď už máš v OnDialogResponse switch na dialogid, tak ho kľudne využi a pridaj do neho ďalšie možnosti (case DIALOG_WARPY, case DIALOG_AUTOSKOLA). Môžeš sa tak vyhnúť zbytočným ifom.

    • Líbí se mi to! (+1) 1
  6. před 7hodinami, Hip said:

    když je to teď, co vím, opensource, to jim to neběží na githubu? A pokud ne, proč to tam ještě není, každej by si to mohl upravit podle sebe a komunitní vývoj by se rozjel ve velkém...

    Pokiaľ viem, team open.mp zatiaľ riešil iba náhradu samp serveru a ku klientovi sa ešte nedostali. Toto bol problém v klientovi.

  7. Ahoj, skús drobnú úpravu v OnDialogResponse:
     

    if (dialogid == REG_DIALOG) // Všimni si, že som odstránil && response==1 z podmienky
    {
        if (!response) // Ak hráč stlačí pravé tlačítko dialogu (v tvojom prípade "Ukončit"), response má hodnotu 0
        {
            // Sem vlož kód na zobrazenie registračného dialogu alebo kicknutie hráča zo serveru
            return 1;
        }
        
        if(strlen(inputtext) == 0)
        {
            SendClientMessage(playerid, B_CERV, "[ ! ] Moc kratke heslo!");
            new message[256]; 
            format(message, sizeof(message), "\n\n{FFFFFF}Vítaj {00FF00}%s{FFFFFF} na servery {00FF00}Realný Svet\n\n{FFFFFF}Pre registraciu si zvol {FF0000}Heslo\n\n", Jmeno(playerid));
            ShowPlayerDialog(playerid, REG_DIALOG, DIALOG_STYLE_PASSWORD, "Registracia", message, "Prihlásit", "Ukončit");
        }
        else 
        {
            if (udb_Create(Jmeno(playerid),inputtext))
            {
                new message[256];
                format(message, sizeof(message), "\n\n{FFFFFF}Vítaj {00FF00}%s{FFFFFF} späť na servery {00FF00}Realný Svet\n\n{FFFFFF}Pre prihlásenie zadaj {FF0000}heslo!\n\n", Jmeno(playerid));
                ShowPlayerDialog(playerid, LOG_DIALOG, DIALOG_STYLE_PASSWORD, "Prihlasenie", message, "Prihlásit", "Ukončit");
            }
            else
            {
                new message[256];
                format(message, sizeof(message), "\n\n{FFFFFF}Vítaj {00FF00}%s{FFFFFF} na servery {00FF00}Realný Svet\n\n{FFFFFF}Pre registraciu si zvol {FF0000}Heslo\n\n", Jmeno(playerid));
                ShowPlayerDialog(playerid, REG_DIALOG, DIALOG_STYLE_PASSWORD, "Registrace", message, "Prihlásit", "Ukončit");
            }
    
        }
    }

     

    • Líbí se mi to! (+1) 1
  8. před 12minutami, PartyGameOficial said:

    Ahoj, @DuFF,

     

    Takže co jsem od tebe pochopil stačí pouze přidat [Hodnota]? 

     

    Takže to bude vypadat nějak takhle?

    sscanf(Data,"s[250]d",SeskokTopName[SeskokCount][i],SeskokTopTime[SeskokCount][i]);

     

    Díky za odpověd.

     

    Áno, to by malo fungovať (za predpokladu, že SeskokTopName má fakt 2. rozmer o veľkosti aspoň 250)

  9. Ahoj,
    predpokladám, že v scriptoch, kde máš goto/warpy, sa používa na zmenu pozície funkcia SetPlayerPos. Potrebuješ docieliť, aby sa pri každom volaní SetPlayerPos aktualizovali hodnoty v premenných xo, yo a zo. Vyriešiš to pomocou tzv. hookovania funkcií. Tanga má o tom návod: https://pawno.cz/index.php?/topic/54592-hookovanie-funkcií-callbackov/

    Chceš teda vytvoriť niečo takéto:

    stock SetPlayerPosEx(playerid, Float:x, Float:y, Float:z)
    {
        // Update premenných xo, yo, zo
        xo[playerid] = x;
        yo[playerid] = y;
        zo[playerid] = z;
    
        // Volanie pôvodnej SetPlayerPos
        return SetPlayerPos(playerid, x, y, z);
    }
    
    #if defined _ALS_SetPlayerPos
      #undef SetPlayerPos
    #else
      #define _ALS_SetPlayerPos
    #endif
    #define SetPlayerPos SetPlayerPosEx

    Máš antiairbrk v rovnakom móde/filterscripte ako goto a warpy? Ak nie, pravdepodobne budeš musieť ešte čarovať s includami a CallRemoteFunction.

  10. Za predpokladu, že ten cheat používa rovnakú animáciu skoku ako klasický skok...

    Po stlačení KEY_JUMP (je jedno, čím hráč skáče, vždy to bude KEY_JUMP) by som kontroloval zmenu hráčovej výšky po ukončení animácie skoku.

    V OnPlayerUpdate by som si zapamätal hráčovu pôvodnú výšku prvýkrát po stlačení KEY_JUMP. Následne by som čakal, kým hráčovi zmizne animácia skoku (GetPlayerAnimationIndex). Po zmiznutí animácie by som zistil hráčovu výšku znova a urobil rozdiel s pôvodnou výškou.

    Treba si dať pozor na situácie, kedy hráča počas skoku niečo warpne/počas skoku do neho niečo narazí a odhodí ho, ...

  11. před 51minutami, sakulmore said:

    Keď hru spustím normálne (bez DXWnd) tak to funguje ako má. Lenže... ja chcem hrať cez DXWnd pretože chcem hru hrať v okne

    Nefunguje ti klasicky Alt + Enter prepnutie hry do okna? Už si nespomínam, či nejak išlo nastaviť zapínanie hry v režime okna bez 3rd party programov.

    Každopádne mám radosť, že si našiel riešenie

  12. Na cleo sa doporučuje verzia hry 1.0 US. Je to akýsi štandard pre módy, ktoré pracujú s pamäťou.

    Hodí sa to hlavne ak plánuješ nejaké zložitejšie módy do sampu, ktoré vyžadujú sampfuncs. Na sampfuncs potom budeš potrebovať verziu sampu R1. S tým je však aktuálne problém, pretože R1 je deravá (obsahuje RCE - servery ti môžu ovládať PC), takže veľmi nedoporučujem.

    Našiel som nejaký svoj upload z 2016, kde by mala byť verzia hry 1.0 US a cleo inštalačka, ktorá mi s ňou fungovala bez problémov. Zvyšok súborov v packu môžeš ignorovať: https://mega.nz/file/xBtgTD6J#7rrTPWiyl4-q4XwKbz3BcLvPAPiKX0XcdzOHbxfTcsY

    Skús a daj vedieť, či ti to fixlo myš

  13. Tak som niečo zbúchal podľa textu, ktorý som napísal vyššie... Nie je to úplne elegantné a neviem, či to poriadne funguje (nemám testy), ale možno ťa to aspoň trochu inšpiruje:
     

    Spoiler
    function countMoveScore(oldBoard, newBoard) {
        const newLetters = findNewLetters(oldBoard, newBoard);
        const newWords = findNewWords(newBoard, newLetters);
        const wordScores = newWords.map(countWordScore);
        const moveScore = wordScores.reduce((a, b) => a + b, 0);
        // TODO: add 50 points for using all 7 letters?
        return moveScore;
    }
    
    function findNewLetters(oldBoard, newBoard) {
        let newLetters = [];
        for (let x = 0; x < newBoard.length; ++x) {
            for (let y = 0; y < newBoard[x].length; ++y) {
                if (newBoard[x][y] != "" && oldBoard[x][y] == "") {
                    newLetters.push({letter: newBoard[x][y], x: x, y: y});
                }
            }
        }
        return newLetters;
    }
    
    function findNewWords(newBoard, newLetters) {
        let newWords = [];
    
        let areNewLettersHorizontal = areLettersHorizontal(newLetters);
        if (areNewLettersHorizontal) {
            for (const letter of newLetters) {
                const verticalWord = findVerticalWord(newBoard, letter.x, letter.y);
                if (verticalWord) {
                    applyBonuses(verticalWord, newLetters);
                    newWords.push(verticalWord);
                }
            }
            const letter = newLetters[0];
            const horizontalWord = findHorizontalWord(newBoard, letter.x, letter.y);
            if (horizontalWord) {
                applyBonuses(horizontalWord, newLetters);
                newWords.push(horizontalWord);
            }
        }
        else
        {
            for (const letter of newLetters) {
                const horizontalWord = findHorizontalWord(newBoard, letter.x, letter.y);
                if (horizontalWord) {
                    applyBonuses(horizontalWord, newLetters);
                    newWords.push(horizontalWord);
                }
            }
            const letter = newLetters[0];
            const verticalWord = findVerticalWord(newBoard, letter.x, letter.y);
            if (verticalWord) {
                applyBonuses(verticalWord, newLetters);
                newWords.push(verticalWord);
            }
        }
    
        return newWords;
    }
    
    function areLettersHorizontal(letters) {
        return letters.length > 1 && letters[0].x != letters[1].x;
    }
    
    function findHorizontalWord(newBoard, letterX, letterY) {
        return findWord(newBoard, letterX, letterY, [1, 0]);
    }
    
    function findVerticalWord(newBoard, letterX, letterY) {
        return findWord(newBoard, letterX, letterY, [0, 1]);
    }
    
    function findWord(newBoard, letterX, letterY, direction) {
        const [stepX, stepY] = direction;
    
        let wordHead = [];
        x = letterX - stepX;
        y = letterY - stepY;
        while (x >= 0 && y >= 0 && newBoard[x][y] != "") {
            wordHead.push({letter: newBoard[x][y], x: x, y: y});
            x -= stepX;
            y -= stepY;
        }
    
        const wordMid = [
            {letter: newBoard[letterX][letterY], x: letterX, y: letterY}
        ];
        
        let wordTail = []
        x = letterX + stepX;
        y = letterY + stepY;
        while (x < newBoard.length && y < newBoard[x].length && newBoard[x][y] != "") {
            wordTail.push({letter: newBoard[x][y], x: x, y: y});
            x += stepX;
            y += stepY;
        }
    
        const word = wordHead.reverse()
            .concat(wordMid)
            .concat(wordTail);
        
        if (word.length >= 2) {
            return word;
        }
    
        return null;
    }
    
    function applyBonuses(word, newLetters) {
        const bonuses = [
            /*První řádek*/
            { x: 0, y: 0, multiplier: 3, type: 1 },
            { x: 3, y: 0, multiplier: 2, type: 0 },
            { x: 7, y: 0, multiplier: 3, type: 1 },
            { x: 11, y: 0, multiplier: 2, type: 0 },
            { x: 14, y: 0, multiplier: 3, type: 1 },
            /*Druhý řádek*/ 
            { x: 1, y: 1, multiplier: 2, type: 1 },
            { x: 5, y: 1, multiplier: 3, type: 0 },
            { x: 9, y: 1, multiplier: 3, type: 0 },
            { x: 13, y: 1, multiplier: 2, type: 1 },
            /*Třetí řádek*/ 
            { x: 2, y: 2, multiplier: 2, type: 1 },
            { x: 6, y: 2, multiplier: 2, type: 0 },
            { x: 8, y: 2, multiplier: 2, type: 0 },
            { x: 12, y: 2, multiplier: 2, type: 1 },
            /*Čtvrtý řádek*/ 
            { x: 0, y: 3, multiplier: 2, type: 0 },
            { x: 3, y: 3, multiplier: 2, type: 1 },
            { x: 7, y: 3, multiplier: 2, type: 0 },
            { x: 11, y: 3, multiplier: 2, type: 1 },
            { x: 14, y: 3, multiplier: 2, type: 0 },
            /*Pátý řádek*/ 
            { x: 4, y: 4, multiplier: 2, type: 1 },
            { x: 10, y: 4, multiplier: 2, type: 1 },
            /*Šestý řádek*/ 
            { x: 1, y: 5, multiplier: 3, type: 0 },
            { x: 5, y: 5, multiplier: 3, type: 0 },
            { x: 9, y: 5, multiplier: 3, type: 0 },
            { x: 13, y: 5, multiplier: 3, type: 0 },
            /*Sedmý řádek*/ 
            { x: 2, y: 6, multiplier: 2, type: 0 },
            { x: 6, y: 6, multiplier: 2, type: 0 },
            { x: 8, y: 6, multiplier: 2, type: 0 },
            { x: 12, y: 6, multiplier: 2, type: 0 },
            /*Osmý řádek*/ 
            { x: 0, y: 7, multiplier: 3, type: 1 },
            { x: 3, y: 7, multiplier: 2, type: 0 },
            { x: 11, y: 7, multiplier: 2, type: 0 },
            { x: 14, y: 7, multiplier: 3, type: 1 },
            /*Devátý řádek*/
            { x: 2, y: 8, multiplier: 2, type: 0 },
            { x: 6, y: 8, multiplier: 2, type: 0 },
            { x: 8, y: 8, multiplier: 2, type: 0 },
            { x: 12, y: 8, multiplier: 2, type: 0 },
            /*Desátý řádek*/ 
            { x: 1, y: 9, multiplier: 3, type: 0 },
            { x: 5, y: 9, multiplier: 3, type: 0 },
            { x: 9, y: 9, multiplier: 3, type: 0 },
            { x: 13, y: 9, multiplier: 3, type: 0 },
            /*Jedenáctý řádek*/ 
            { x: 4, y: 10, multiplier: 2, type: 1 },
            { x: 10, y: 10, multiplier: 2, type: 1 },
            /*Dvanáctý řádek*/ 
            { x: 0, y: 11, multiplier: 2, type: 0 },
            { x: 3, y: 11, multiplier: 2, type: 1 },
            { x: 7, y: 11, multiplier: 2, type: 0 },
            { x: 11, y: 11, multiplier: 2, type: 1 },
            { x: 14, y: 11, multiplier: 2, type: 0 },
            /*Třináctý řádek*/ 
            { x: 2, y: 12, multiplier: 2, type: 1 },
            { x: 6, y: 12, multiplier: 2, type: 0 },
            { x: 8, y: 12, multiplier: 2, type: 0 },
            { x: 12, y: 12, multiplier: 2, type: 1 },
            /*Čtrnáctý řádek*/ 
            { x: 1, y: 13, multiplier: 2, type: 1 },
            { x: 5, y: 13, multiplier: 3, type: 0 },
            { x: 9, y: 13, multiplier: 3, type: 0 },
            { x: 13, y: 13, multiplier: 2, type: 1 },
            /*Patnáctý řádek*/ 
            { x: 0, y: 14, multiplier: 3, type: 1 },
            { x: 3, y: 14, multiplier: 2, type: 0 },
            { x: 7, y: 14, multiplier: 3, type: 1 },
            { x: 11, y: 14, multiplier: 2, type: 0 },
            { x: 14, y: 14, multiplier: 3, type: 1 },
        ];
    
        for (const letter of word) {
            if (newLetters.find(newLetter => letter.x == newLetter.x && letter.y == newLetter.y)) {
                const bonus = bonuses.find(element => element.x == letter.x && element.y == letter.y);
                if (bonus) {
                    letter.bonus = { multiplier: bonus.multiplier, type: bonus.type };
                }
            }
        }
    }
    
    function countWordScore(word) {
        let wordScoreMultiplier = 1;
        let scoreSum = 0;
        for (const letter of word) {
            const letterScore = getLetterValue(letter.letter);
            const bonus = letter.bonus;
            if (bonus) {
                if (bonus.type == 0) {
                    letterScore *= bonus.multiplier;
                } else if (bonus.type == 1) {
                    wordScoreMultiplier *= bonus.multiplier;
                }
            }
            scoreSum += letterScore;
        }
        scoreSum *= wordScoreMultiplier;
        return scoreSum;
    }
    
    function getLetterValue(letter) {
        const letterValues = {
            'a': 1,
            'e': 1,
            'i': 1,
            'l': 1,
            'n': 1,
            'o': 1,
            'r': 1,
            's': 1,
            't': 1,
            'u': 1,
            'd': 2,
            'g': 2,
            'b': 3,
            'c': 3,
            'm': 3,
            'p': 3,
            'f': 4,
            'h': 4,
            'v': 4,
            'w': 4,
            'y': 4,
            'k': 5,
            'j': 8,
            'x': 8,
            'q': 10,
            'z': 10
        };
    
        return letterValues[letter.toLowerCase()] ?? 0;
    }

     

     

  14. Začal by som tak, že by som najskôr zistil, ktoré znaky sú nové a uložil by som si ich súradnice do nejakého poľa.

    Potom by som začal vytvárať pole nových slov...

    Treba zistiť, či sú nové písmenká položené vertikálne, alebo horizontálne.

    Ak sú položené vertikálne, pre každý nový znak by som sa pozrel vľavo a vpravo od neho (až do prázdneho miesta alebo okraja hracej dosky). Ak by som našiel aspoň 2 znaky, znamenalo by to nové slovo. Takéto slovo by som pridal do poľa všetkých nových slov vo forme jednotlivých písmenok a príslušných bonusov. Bonusy pre staré znaky by som označil ako typ 0, multiplier 1 (žiadny bonus). Bonusy pre nové znaky sa zistia z tvojho poľa bonusov. Potom by som identifikoval začiatok a koniec slova vo vertikálnom smere - treba si dať pozor na to, že v tomto slove môže byť viac nových znakov, a teda viac bonusov. Toto nové slovo by som reprezentoval rovnakým spôsobom ako predošlé slová a vložil do rovnakého poľa.

    Ak sú položené horizontálne, postup je analogický s tým rozdielom, že pre každý nový znak sa pozerám hore a dole pre vertikálne slová a potom vľavo a vpravo pre nové horizontálne slovo.

    Na záver potrebuješ nejakú funkciu, ktorá dostane reprezentáciu nového slova (pole objektov zložených z písmenka, typu bonusu a multiplieru) a vyhodnotí jeho skóre. Túto funkciu aplikuješ na všetky nájdené nové slová a spočítaš súčet.

    Zajtra k tomu skúsim napísať nejaký kód... Mohol by si zatiaľ priložiť nejaké jednoduché testy, aby som si overil, že mi to funguje správne?

  15. Zdravím,

    vyzerá to ako zaujímavý problém a pokúsim sa niečo vymyslieť... Zatiaľ zdieľam aspoň hračku, ktorá sa môže hodiť na vizualizáciu pri návrhu generátora:
     

    Spoiler
    class DumbGeneratorStrategy {
        constructor() {
            this.lastPoint = [0, 0]
        }
        
        generatePoint() {
            const [lastX, lastY] = this.lastPoint;
            const newPoint = [lastX + 1, lastY + 1];
            this.lastPoint = newPoint; 
            return newPoint;
        }
    }
    
    // TODO: seed
    function random(min, max) {
        var range = max - min;
        return min + range * Math.random();
    }
    
    class FullyRandomGeneratorStrategy {
        constructor() {
        }
        
        generatePoint() {
            const x = random(0, 100);
            const y = random(0, 100);
            return [x, y];
        }
    }
    
    // https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep
    // sleep time expects milliseconds
    function sleep (time) {
      return new Promise((resolve) => setTimeout(resolve, time));
    }
    
    const CANVAS_ID = 'drawingSpace';
    
    function getCanvas() {
        return document.getElementById(CANVAS_ID);
    }
    
    function addCanvas() {
        const canvas = document.createElement('canvas');
        canvas.setAttribute('id', CANVAS_ID);
        canvas.setAttribute('width', 500);
        canvas.setAttribute('height', 500);
        canvas.setAttribute('style', 'border:1px solid #000000;');
        document.body.append(canvas);
        const ctx = canvas.getContext('2d');
        ctx.scale(5, 5); // show 100x100 space on a 500x500 canvas
    }
    
    function clearCanvas() {
        const canvas = getCanvas();
        const ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    }
    
    async function drawPoints(numberOfPoints, millisecondsPerPoint, strategy,) {
        const canvas = getCanvas();
        const ctx = canvas.getContext('2d');
        for (var i = 1; i < numberOfPoints; ++i) {
            var [x, y] = strategy.generatePoint();
            ctx.fillRect(x, y, 1, 1);
            await sleep(millisecondsPerPoint);
        }
    }
    
    addCanvas();
    while (true) {
        await drawPoints(100, 10, new FullyRandomGeneratorStrategy());
        clearCanvas();
    }

     

    Viete si napísať vlastnú stratégiu generovania bodov - stačí vytvoriť triedu, ktorá obsahuje metódu generatePoint, ktorá vracia súradnice nového bodu. Táto metóda môže tiež ako side-effect napríklad updatovať nejaký váš stav (v prípade DumbGeneratorStategy je to iba posledný bod, ale môže to byť kľudne nejaká kolekcia všetkých bodov atď.), ktorý sa dá použiť na maximalizáciu vzdialenosti medzi generovanými bodmi.

    // Edit:
    Napísal som SquareSectorGeneratorStrategy, ktorá by možno mohla stačiť:
     

    Spoiler
    class SquareSector {
        constructor(bottomLeft, topRight) {
            [this.bottomLeftX, this.bottomLeftY] = bottomLeft;
            [this.topRightX, this.topRightY] = topRight;
            this.innerSectors = [];
            this.point = null;
            this.cumulativeNumberOfPoints = 0;
        }
        
        addPoint() {
            ++this.cumulativeNumberOfPoints;
            
            // sector does not contain any points yet
            if (!this.point) {
                const randomX = random(this.bottomLeftX, this.topRightX);
                const randomY = random(this.bottomLeftY, this.topRightY);
                this.point = [randomX, randomY];
                return this.point;
            }
            
            // sector contains only a single point - it is needed to create inner sectors
            if (this.innerSectors.length === 0) {
                this.split();
            }
            
            // pick one inner sector based on their cumulativeNumberOfPoints
            const priorities = this.innerSectors.map(sector => 1 - sector.cumulativeNumberOfPoints / this.cumulativeNumberOfPoints);
            const prioritiesSum = priorities.reduce((a, b) => a + b);
            const probabilities = priorities.map(priority => priority / prioritiesSum);
            const probabilityTable = probabilities.reduce((a, b) => {
                const lastElement = a[a.length - 1];
                const newElement = lastElement + b;
                a.push(newElement);
                return a;
            }, [0]);
            const randomNumber = Math.random();
            for (let i = 0; i < probabilityTable.length; ++i) {
                if (randomNumber < probabilityTable[i]) {
                    return this.innerSectors[i - 1].addPoint();
                }
            }
        }
        
        split() {
            // create inner sectors
            const midPointX = (this.bottomLeftX + this.topRightX) / 2;
            const midPointY = (this.bottomLeftY + this.topRightY) / 2;
            this.innerSectors.push(new SquareSector([this.bottomLeftX, this.bottomLeftY], [midPointX, midPointY])); // bottomLeft
            this.innerSectors.push(new SquareSector([midPointX, this.bottomLeftY], [this.topRightX, midPointY])); // bottomRight
            this.innerSectors.push(new SquareSector([this.bottomLeftX, midPointY], [midPointX, this.topRightY])); // topLeft
            this.innerSectors.push(new SquareSector([midPointX, midPointY], [this.topRightX, this.topRightY])); // topRight
            
            // move the existing point to one of the new inner sectors
            for (const sector of this.innerSectors) {
                if (sector.containsPoint(this.point)) {
                    sector.point = this.point;
                    this.point = null;
                    break;
                }
            };
        }
        
        containsPoint(point) {
            const [x, y] = point;
            return this.bottomLeftX <= x && x <= this.topRightX
                && this.bottomLeftY <= y && y <= this.topRightY;
        }
    }
    
    class SquareSectorGeneratorStrategy {
        constructor() {
            this.rootSector = new SquareSector([0, 0], [100, 100]);
        }
        
        generatePoint() {
            return this.rootSector.addPoint();
        }
    }

     

    Funguje tak, že sa kresliaca plocha rozdeľuje na sektory. Začína sa hlavným sektorom, ktorý pokrýva celú plochu. V prípade, že sa do sektoru vkladá 2. bod, sektor sa rozdelí na 4 štvorcové podsektory (ľavý dolný roh, pravý dolný roh, ľavý horný roh, pravý horný roh). Každý (pod)sektor si drží celkový počet bodov, ktoré sa nachádzajú v jeho všetkých podsektoroch (vrátane ich vnorených podsektorov). Tento počet potom zohráva úlohu pri voľbe, do ktorého zo 4 podsektorov sa má bod vložiť. Voľba sa opakuje postupne na nižších a nižších úrovniach, až kým sa nenájde sektor, ktorý neobsahuje žiadny bod. Vtedy sa vygeneruje náhodná pozícia v rámci daného sektoru... 

    Všimol som si, že je trochu problém s tým, keď máš smolu a bod sa vygeneruje presne na hranici sektorov. Susediace sektory o sebe nič nevedia a je možné, že tak skončia 2 body nalepené na sebe. Ak chceš tomuto javu predísť, možno by sa dal upraviť spôsob, akým sa generujú body v najnižšom podsektore, t.j. zmeniť to z úplne náhodnej voľby na nejakú prioritizáciu stredu sektora.

    Vizualizácia: https://www.youtube.com/watch?v=Y2ehPGPD1ZI&ab_channel=HFCDuFF

    • Líbí se mi to! (+1) 1
  16. Predstav si, že máš na serveri registrovaných 1000 účtov. Myslím, že sa zhodneme na tom, že otvárať všetky súbory a čítať z nich dáta pri každom výpise topky nie je najlepší nápad.

    Rieši sa to tak, že si vytvoríš súbor, v ktorom budú uložené top štatistiky. Potom napríklad v SavePlayer pri ukladaní každého statu pozrieš, či je hráčova hodnota "lepšia" ako topka a ak je, updatuješ hodnotu v súbore s topkami. Aby si nemusel otvárať súbor s topkami pri každom porovnaní, je dobré držať si jeho kópiu v pamäti.

    • Líbí se mi to! (+1) 2
  17. Ja by som to vyriešil tak, že by som v dialogu zobrazil najskôr všetky dostupné losy a potom všetky kúpené. Najjednoduchšie to budeš mať 2 for cyklami cez všetky losy... V prvom cykle do bufferu nahádžeš všetky dostupné a v druhom všetky nedostupné. Takto zároveň docieliš, že losy v obidvoch skupinách budú v dialogu zoradené podľa čísla losu

    • Líbí se mi to! (+1) 1
  18. S javascriptom nerobím, mám niečo málo cez rok komerčnej praxe v C# (považujem sa za juniora) a neprišlo mi to príliš zložité - do hodiny som to zbúchal. Dešifrovanie zadania som zvládol bez väčších problémov, ale viem si predstaviť, že Češi by z toho neboli nadšení... Najväčšia bolesť bolo asi dodržiavanie názvov funkcií a premenných v slovenčine.
    Máš k tomu nejaké referenčné riešenie? Celkom by ma zaujímalo aj to riešenie od ChatGPT.
    Ja som vypracoval toto:

    Spoiler
    function rieka(x, y, pole) {  
        var vystup = [];
        for (let i = 0; i < pole.length; ++i) {
            let arr = [];
            for (let j = 0; j < pole[i].length; ++j) {
                arr.push(0);
            }
            vystup.push(arr);
        }
        
        rekurzivnaRieka(x, y, pole, vystup);
       
        printArray(vystup);
    }
    
    function rekurzivnaRieka(x, y, vstup, vystup) {
        //console.log(`rekurzivnaRieka(${x}, ${y})`);
        vystup[x][y] = 1;
        
        const smery = [
            [0, 1],
            [0, -1],
            [1, 1],
            [1, 0],
            [1, -1],
            [-1, 1],
            [-1, 0],
            [-1, -1]
        ];
        
        const validneSmery = smery.filter(smer => {
            const [xSmer, ySmer] = smer;
            const noveX = x + xSmer;
            if (noveX < 0 || noveX >= vstup.length)
                return false;
                
            const noveY = y + ySmer;
            if (noveY < 0 || noveY >= vstup[noveX].length)
                return false;
            
            return true;
        })
        
        let minimalnaVyska = vstup[x][y];
        for (const [xSmer, ySmer] of validneSmery) {
            const vyska = vstup[x + xSmer][y + ySmer];
            if (vyska < minimalnaVyska) {
                minimalnaVyska = vyska;
            }
        }
        
        //console.log(`minimalna vyska: ${minimalnaVyska}`);
        
        for (const [xSmer, ySmer] of validneSmery) { 
            const noveX = x + xSmer;
            const noveY = y + ySmer;
            if (vstup[noveX][noveY] <= minimalnaVyska 
                && vystup[noveX][noveY] === 0) {
                rekurzivnaRieka(noveX, noveY, vstup, vystup);
            }
        }
    
        return vystup;
    }

     

    Každopádne cool obrázky ako odmena za vypracovanie určite potešili

    image.png

    • Paráda! (+1) 1
    • Líbí se mi to! (+1) 1
×
×
  • Create New...