@vladmany

Как правильно перевести алгоритм с Javascript на Lua?

Есть один алгоритм решения игры "Пятнашки", написанный на JavaScript, который я хочу перевести на луа. Сложных конструкций языка там почти нет, элементарная работа с массивами. Основная сложность заключается в том, что в JS массивы начинаются с нулевого элемента, а в Lua с первого, из этого и вытекают все трудности. По началу все шло хорошо, закомментировал исходник, и построчно переписывал код на луа постоянно отлаживая данные, чтобы они совпадали. И тут я столкнулся с ситуацией, где вроде все данные совпадают, но на луа пропускается одна итерация цикла(не первая и не последняя). Спустя долгое время отладки я выяснил, на каком именно этапе происходит расхождение данных(в комментариях кода я это пометил). Но найти конкретное место, где возникает проблема я так и не смог, уже всё перепробовал, всё что можно отладил во всех местах. Может Вы, на свежую голову поймете в чем проблема и укажите мне на неё. А если найдутся умельцы, которые сами переведут этот алгоритм на луа, я буду безгранично благодарен.

Исходник, который нужно перевести на луа(код, который я ещё не перевел на луа закомментирован)
spoiler
var posit = new Array ();
var maxhgh = 10;         //maximum height of board
var maxwid = 10;        //maximum width of board
var hgh = 4;            //height of board; 2-maxhgh
var wid = 4;            //width of board; 2-maxwid
var siz = (hgh*wid)-1;           //Number of tiles, = wid*hgh-1. Only have provision for 2-digit numbers on display
var mode = 0;           //0=normal  1=solving scrambled  2=edit  3=solving
var seq = new Array();  //solving sequence
var edt;                //next piece to place in edit mode
var blnkx,blnky;        //position of blank space
blnkx=wid-1;
blnky=hgh-1;

posit = [8, 13, 11, 14, 15, 10, 0, 4, 9, 1, 12, 5, 3, 2, 7, 6]
solve()

function push(){
    //push list onto list of moves for solution. Also does moves without showing them.
    for (var i=0;i<push.arguments.length;i++){
        var c=push.arguments[i];
        if(seq.length && seq[seq.length-1]+c==3) {
            seq.length--;
        } 
        else {
            seq[seq.length]=c;
        } 
        domove(c);
    }
}

function domove(m){  //0=right, 1=down, 2=up, 3=left
    //does move without showing it.
    var d=blnkx+blnky*wid;
    if(m==0)     { 
        posit[d]=posit[d-1]; 
        posit[d-1]=siz; 
        blnkx--; 
    }
    else if(m==1){ 
        posit[d]=posit[d-wid]; 
        posit[d-wid]=siz; 
        blnky--; 
    }
    else if(m==2){ 
        posit[d]=posit[d+wid]; 
        posit[d+wid]=siz; 
        blnky++; 
    }
    else if(m==3){ 
        posit[d]=posit[d+1  ];
        posit[d+1  ]=siz; 
        blnkx++; 
    }
}

function solve(){
        seq.length=0;

        //no solution set up yet. Construct it!
        //save pieces;
        var back = new Array();
        for(var i=0;i<=siz;i++) { 
            back[i] = posit[i];
        } 
        
        //restore top rows
        var rr=0;
        for(var r=0; r<hgh-2;r++) {
            // console.log('solveFor1')
            for(var c=0;c<wid;c++) {
                movepiece(rr + c, r, c);
            } 
            rr+=wid;
        }
    //     //restore left columns
    //     for(c=0;c<wid-2;c++){
    //         //restore top tile of column.
    //         movepiece(rr,hgh-2,c);
    //         //restore bottom tile of column
    //         if(blnkx==c) push(3);  //fill destination spot
    //         if(posit[rr+wid]!=rr+wid){
    //             movepiece(rr+wid,hgh-1,c+1);
    //             if(blnky!=hgh-1) {    //0=right, 1=down, 2=up, 3=left
    //                 //A.X or AX.
    //                 //XBX    XBX
    //                 if( blnkx==c+1 ) push(3);
    //                 push(2);
    //             }
    //             //AXX
    //             //XB.
    //             while( blnkx>c+2 ) push(0);
    //             push(0,0,1,3,2,3,1,0,0,2,3);
    //         }
    //         rr++;
    //     }
    //     //last 2x2 square
    //     if(blnkx<wid-1) push(3);
    //     if(blnky<hgh-1) push(2);
    //     rr=siz-wid-1;
    //     if(posit[rr]==rr+1)   push(1,0,2,3);
    //     if(posit[rr]==rr+wid) push(0,1,3,2);
    //     //restore pieces;
    //     for(var i=0;i<=siz;i++) posit[i]=back[i];
    //     blnkx=back[siz+1];
    //     blnky=back[siz+2];
}

function movepiece(p,y,x){
    var c=-1;
    for(var i=0;i<hgh;i++){
        for(var j=0;j<wid;j++){
            c++;
            if(posit[c]==p) break;
        }
        if(posit[c]==p) break; 
    }
    // Move piece to same column         //0=right, 1=down, 2=up, 3=left
    if(j<x && blnky==y) push(2);    // move blank down if it might disturb solved pieces.
    while(j>x){
        //move piece to left
        //First move blank to left hand side of it
        if(blnky==i && blnkx>j){    //if blank on wrong side of piece
            if(i==hgh-1) push(1); else push(2); //then move it to other row
        }
        while(blnkx>=j) {
            push(0);    // move blank to column left of piece
        }
        // while(blnkx<j-1) push(3);
        // while(blnky<i) push(2);     // move blank to same row as piece
        // while(blnky>i) push(1);
        // push(3);                    // move piece to left.
        j--;
    }
    // while(j<x){
        //move piece to right
        //First move blank to right hand side of it
        // if(blnky==i && blnkx<j){
            // if(i==hgh-1) push(1); else push(2);
        // }
        // while(blnkx<=j) push(3);
        // while(blnkx>j+1) push(0);
        // while(blnky<i) push(2);
        // while(blnky>i) push(1);
        // push(0);
        // j++;
    // }

    //Move piece up to same row         //0=right, 1=down, 2=up, 3=left
    // while(i>y){
    //     if(y<i-1){
    //         while(blnky<i-1) push(2);
    //         if(blnkx==j) push( j==wid-1? 0:3);
    //         while(blnky>i-1) push(1);
    //         while(blnkx<j) push(3);
    //         while(blnkx>j) push(0);
    //         push(2);
    //     }else{
    //         if(j!=wid-1){
    //             if(blnky==i) push(2);
    //             while(blnkx<j+1) push(3);
    //             while(blnkx>j+1) push(0);
    //             while(blnky>i-1) push(1);
    //             while(blnky<i-1) push(2);
    //             push(0,2);
    //         }else{
    //             if(blnky<i && blnkx==j){
    //                 while(blnky<i) push(2);
    //             }else{
    //                 while(blnky>i+1) push(1);
    //                 while(blnky<i+1) push(2);
    //                 while(blnkx<j) push(3);
    //                 while(blnkx>j) push(0);
    //                 push(1,1,0,2,3,2,0,1,1,3,2);
    //             }
    //         }
    //     }
    //     i--;
    // }
    // while(i<y){
    //     //move piece downwards
    //     //First move blank below tile
    //     if(blnkx==j && blnky<i){
    //         if(j==wid-1) push(0); else push(3);
    //     }
    //     while(blnky>i+1) push(1);
    //     while(blnky<i+1) push(2);
    //     while(blnkx<j) push(3);
    //     while(blnkx>j) push(0);
    //     push(1);
    //     i++;
    // }
}


Мои наработки и то, на чем я застрял:
spoiler
ins = require("inspect")

posit = {}
seq = {}
hgh = 4
wid = 4
siz = (hgh*wid)-1
blnkx=wid-1
blnky=hgh-1

function domove(m) 
    local d=blnkx+blnky*wid + 1
    if m == 0 then 
        posit[d] = posit[d-1]
        posit[d-1] = siz
        blnkx = blnkx - 1
    elseif m == 1 then
        posit[d] = posit[d-wid]
        posit[d-wid] = siz
        blnky = blnky - 1
    elseif m == 2 then
        posit[d] = posit[d+wid]
        posit[d+wid] = siz
        blnky = blnky + 1
    elseif m == 3 then
        posit[d] = posit[d+1]
        posit[d+1] = siz
        blnkx = blnkx + 1
    end
end

function push(...) 
    local args = {...}
    for k, v in pairs(args) do 
        local c=v
        if seq[#seq] then
            if #seq and seq[#seq]+c == 3 then
                table.remove(seq, #seq)
            else 
                seq[#seq+1] = c
            end
        else
            seq[#seq+1] = c
        end
        domove(c)
    end
end

function movepiece(p, y, x)
    local c = 0
    local ki = 0
    local kj = 0
    for i=0, hgh-1 do
        ki = i
        for j=0, wid-1 do
            kj = j
            c = c + 1
            if (posit[c]==p) then 
                break 
            end
        end
        if (posit[c]==p) then 
            break 
        end
    end
    print(kj) -- на одной из итераций эти данные будут отличаться
    print(ki) -- от тех, которые выводятся в исходнике
    if kj<x and blnky == y then push(2) end
    while(kj > x) do 
        if blnky == ki and blnkx > kj then
            if ki == hgh - 1 then
                push(1)
            else
                push(2)
            end
        end
        -- На этом моменте появляется проблема
        while(blnkx >= kj) do -- Если это закомментировать,
            push(0)           -- то проблема возникать
        end                   -- не будет
        ins.inspect(seq) -- вот тут данные не совпадают с теми, которые выводятся в исходнике
        -- while(blnkx < kj-1) do push(3) end
        -- while(blnky < kj) do push(2) end
        -- while(blnky > kj) do push(1) end
        -- push(3)
        kj = kj - 1
    end
end

function solve() 
    seq = {}

    local back = {}
    for i=1, siz+1 do
        back[i] = posit[i]
    end

    back[siz+2]=blnkx;
    back[siz+3]=blnky;

    local rr=0
    for r=0, (hgh-3) do
        for c=0, wid-1 do
            movepiece(rr + c, r, c)
        end
        rr = rr + wid
    end
end

posit = {8, 13, 11, 14, 15, 10, 0, 4, 9, 1, 12, 5, 3, 2, 7, 6}
solve()

Для вывода таблиц использовал библиотеку inspect.

Возможно вам будет проще переписать код с нуля до того момента, на котором я застрял.
  • Вопрос задан
  • 481 просмотр
Решения вопроса 1
WblCHA
@WblCHA
Как вариант, быстренько перевести код на тайпскрипт и транспилировать его в луа:
https://www.npmjs.com/package/typescript-to-lua
Думаю, будет в разы быстрее и эффективнее.

Либо можешь кастл опробовать, но там последнее обновление 4 года назад.
https://www.npmjs.com/package/castl
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы