Crea un Risolutore Frogger


12

🐸🐸

È necessario creare il programma più breve per trovare sempre la soluzione ottimale per un gioco Frogger semplificato su una griglia 9x9.

Elementi del corso:

  • L- Registro (lunghezza: 3-4). Quando salti su un tronco, ti porta con sé.
  • V - Veicolo (lunghezza: 1-2)
  • Velocità (1-2): sul lato sinistro della riga si trova la velocità con cui si muovono gli elementi della riga.
  • Spazi: ci saranno sempre almeno due spazi tra gli elementi.
  • Direzione: nelle sezioni Veicolo e Registro, la direzione di movimento in ciascuna corsia si alterna tra sinistra e destra.

Struttura del corso:

  • Se è capitale, va bene; se è minuscolo, va a sinistra. Tutti gli elementi di fila vanno nella stessa direzione. Non appena parte di un elemento esce dallo schermo, apparirà sul lato opposto dello schermo.
  • La prima fila è una zona sicura. La rana inizia da F, che è sempre lo stesso punto.
  • Le successive 3 file sono strade con veicoli.
  • La riga successiva è una zona sicura.
  • Le successive 3 file sono acqua (acqua toccante == morte) con Log.
  • Una volta raggiunta la Wcorsia, vinci.
  • Se la rana muore, ritorna a F

Controlli del giocatore:

  • L - Sinistra
  • R - Giusto
  • U - Su
  • D - Giù
  • W - Aspettare

Dopo lo spostamento, passa un altro fotogramma. (Nota che il frame passa dopo la tua mossa, non contemporaneamente alla tua mossa.) Il tuo programma deve fornire la soluzione ottimale come una sequenza di caratteri come URWUUL. Se un corso non ha soluzione, il tuo programma dovrebbe produrre N.

Esempi: (Da quando li ho fatti a mano non so se sono soluzioni ottimali.)

0WWWWWWWWW
1 lll    
2 LLLL   
2 llll   
0         
1 vv vv 
1 V V   
1 vv    
0 F.    

Soluzione: WUWUUURWUULWUU

0WWWWWWWWW
2 lll   
1 LLLL  
1 lll   
0         
2 vv    
1 VV     
2 vv    
0 F.    

Soluzione: WUWUWUUWUUWWUU

0WWWWWWWWW
2 llll  
2 LLL   
1 llll  
0         
2 v vv 
1 VV VV 
1 v v   
0 F.    

Soluzione: WWUUUURURRWWUUU

0WWWWWWWWW
2 llll   
2 LLL   
1 lll   
0         
1 vv v 
2 VVV 
2 vvv 
0 F.    

Soluzione: N(nessun modo per superare la prima fila.)

Prova questi nello snippet incollando il corso nella casella di testo e premendo "Carica corso". Quindi incollare la soluzione in "Input" e premere invio.

Snippet: è difficile creare casi di test, quindi ho creato questo snippet che ti consente di vedere se il tuo programma è in grado di risolvere corsi generati casualmente. A scopo di test, tutto ciò che devi fare è inserire la soluzione del tuo programma (ad es. LRUWL...) Nella sezione "Input" e premere invio. Per ripristinare il corso allo stato originale, premere "Ripristina". Fammi sapere se trovi qualche bug.

var timer;
var f_x, f_y;
var replaced;
var copy;
document.body.onkeyup = function(e) {
  var a = document.activeElement;
  if (a !== controls && a !== data) hop(e.keyCode);
};

function setup() {
  stop();
  var rows = game.children;
  rows[0].innerHTML = "0WWWWWWWWW";
  load(logs, "L");
  rows[2].innerHTML = "0         ";
  load(cars, "V");
  rows[4].innerHTML = "0    F    ";
  copy = game.innerHTML;
  save();

  f_x = 5;
  f_y = 9;
  replaced = " ";
}

function save() {
  data.value = "";
  for (var i = 1; i <= 9; i++) {
    data.value += getRow(i).textContent;
    if (i < 9) data.value += "\n";
  }
}

function extLoad() {
  stop();
  var rows = data.value.split("\n");
  replaced = " ";
  for (var i = 0; i < rows.length; i++) {
    var r = getRow(i + 1);
    r.innerHTML = rows[i].replace(/ /g, "&nbsp;");
    if (rows[i].indexOf("V") !== -1 || rows[i].indexOf("L") !== -1) r.className = "right";
    else if (rows[i].indexOf("v") !== -1 || rows[i].indexOf("l") !== -1) r.className = "left";
    var f = rows[i].indexOf("F");
    if (f !== -1) {
      f_y = i + 1;
      f_x = f;
    }
  }
  copy = game.innerHTML;
}


function reset() {
  stop();
  game.innerHTML = copy;
  f_x = 5;
  f_y = 9;
  replaced = " ";
}

function play() {
  if (!timer) {
    timer = setInterval(next, 1500);
  }
}

function stop() {
  if (timer) {
    clearInterval(timer);
    timer = null;
  }
}

function input(i) {
  var s = controls.value;
  if (i === 0) {
    stop();
    sub.disabled = true;
  }
  if (s[i] === "L") hop(65);
  else if (s[i] === "U") hop(87);
  else if (s[i] === "R") hop(68);
  else if (s[i] === "D") hop(83);
  next();
  if (i < s.length - 1) setTimeout(function() {
    input(i + 1);
  }, 750);
  else sub.disabled = false;
}

function load(part, code) {
  for (var r = 0; r < 3; r++) {
    var row = part.children[r];
    var s = "";
    var dir = r % 2;
    row.className = dir === 1 ? "right" : "left";
    s += Math.floor(Math.random() * 2) + 1;
    var end = 0;
    for (var c = 0; c < 9-end;) {
      var spaces = Math.min(9 - end - c , Math.floor(Math.random() * 2) + 2);
      if(c === 0 && end===0) {
        spaces = Math.floor(Math.random()*4);
        end = Math.max(0,2-spaces);
      }
      s += "&nbsp;".repeat(spaces);
      c += spaces;
      var type = "";
      var len = 0;
      var rand = Math.floor(Math.random() * 2);
      if (code === "L") {
        type = dir === 1 ? "L" : "l";
        len = rand + 3;
      } else {
        type = dir === 1 ? "V" : "v";
        len = rand + 1;
      }
      if (c + len > 9-end) continue;
      s += type.repeat(len);
      c += len;

    }
    row.innerHTML = s + "&nbsp;".repeat(end);
  }
}

function next() {
  move(logs);
  move(cars);
}

function move(part) {
  var rows = part.children;
  for (var i = 0; i < rows.length; i++) {
    var s = rows[i].textContent;
    var f = s.indexOf("F") !== -1;
    if (f) {
      replace(f_y, f_x, false);
      s = rows[i].textContent;
    }
    var speed = s[0];
    var stuff = s.substring(1);
    var v = vel(speed, rows[i].className);
    rows[i].textContent = s[0] + shift(stuff, speed, rows[i].className);
    if (f) {
      if (part === logs) {
        f_x += v;
        if (f_x < 1 || f_x > 9) {
          go(5 - f_x, f_y - 9);
          return;
        }
      }
      replace(f_y, f_x, true);
      s = rows[i].textContent.substring(1);
      var c = f_x + v;
      var t = "";
      if (c > 9) t = s.substring(f_x) + s.substring(0, c - 9);
      else if (c < 0) t = s.substring(0, f_x) + s.substring(9 + c);
      else t = v > 0 ? s.substring(f_x, c) : s.substring(c, f_x);
      if (t.indexOf("V") !== -1 || t.indexOf("v") !== -1) {
        go(5 - f_x, f_y - 9);
      }

    }



  }
}


function vel(mag, dir) {
  var d = dir === "right" ? 1 : -1;
  var m = parseInt(mag);
  return d * m;
}



function shift(s, n, d) {
  n = parseInt(n);
  for (var i = 0; i < n; i++) {
    if (d === "left") {
      s = s.substring(1) + s.substring(0, 1);
    } else {
      s = s.substring(s.length - 1) + s.substring(0, s.length - 1);
    }
  }
  return s;
}


function hop(k) {
  if (k === 65) go(-1, 0);
  else if (k === 87) go(0, 1);
  else if (k === 68) go(1, 0);
  else if (k === 83) go(0, -1);
}

function go(x, y) {


  replace(f_y, f_x, false);
  f_y -= y;
  f_x += x;
  replace(f_y, f_x, true);
  if (f_x < 1 || f_x > 9 || f_y > 9) {
    go(5 - f_x, f_y - 9);
    return;
  }



  if (f_y == 1) {
    alert("win!");
    go(5 - f_x, f_y - 9);
  }


}

function replace(y, x, f) {

  var row = getRow(y);
  if (!row) return false;

  var s = row.textContent;
  if (x < 1 || x >= s.length) return false;
  if (f) {
    replaced = s[x];
    if (replaced === "V" || replaced === "v" || (replaced.charCodeAt(0) === 160 && y < 5)) {
      go(5 - f_x, f_y - 9);

    } else {
      row.textContent = s.substring(0, x) + "F" + s.substring(x + 1);
    }
  } else {
    row.textContent = s.substring(0, x) + replaced + s.substring(x + 1);
  }

}

function getRow(y) {
  if (y < 1 || y > 9) return false;
  if (y === 1) return game.firstChild;
  if (y === 9) return game.lastChild;
  if (y > 5) return cars.children[y - 6];
  if (y < 5) return logs.children[y - 2];
  return game.children[2];
}
<body onload="setup()"><code id="game"><div></div><div id="logs"><div></div><div></div><div></div></div><div></div><div id="cars"><div></div><div></div><div></div></div><div></div></code>
  <input type="button" value="Step" onclick="next()" />
  <input type="button" value="Pause" onclick="stop()" />
  <input type="button" value="Play" onclick="play()" />
  <input type="button" value="Reset" onclick="reset()" />
  <input type="button" value="New Course" onclick="setup()" />
  <div>Controls: WASD</div>
  <div>Input:
    <input type="text" id="controls" />
    <input type="submit" onclick="input(0)" id="sub" />
  </div>
  <div>
    <textarea id="data" rows=9 cols=12></textarea>
    <input type="button" onclick="extLoad()" value="Load Course" />
    <input type="button" onclick="save()" value="Save Course" />
  </div>
</body>

Dove iniziare:

Relazionato:

Guarda anche:


1
Per coloro che non possono vederli, i primi due personaggi del post sono Unicode U + 1F438: Frog Face
cat

6
Soluzione:WWUUUURURRWWUUU -> Chewie gioca a frogger.
Trauma digitale

3
@DigitalTrauma "Let the Wookie win" - C3PO, per una macchina arcade.
FryAmTheEggman,

Inoltre cosa succede se la rana colpisce il bordo dello schermo?
user81655

2
@quintopia Minuscole viene lasciato, quindi vanno a sinistra.
geokavel,

Risposte:


1

Javascript, 854 byte

function f(w){h=[];z=[];for(y=0;y<9;y++){l=w.split('\n')[y];r={s:parseInt(l[0]),d:1,e:[]};for(x=0;x<9;x++){c=l[1+x];if(c=='v'||c=='l')r.d=-1;r.e.push(c);}z.push(r);}h.push(z);h.push(z);for(g=2;g<40;g++){z=JSON.parse(JSON.stringify(z));for(y=0;y<9;y++){r=z[y];if(r.s>0&&(g%2==0||r.s==2)){i=0;t=0;if(r.d==-1){t=r.e[0];for(i=0;i<8;i++)r.e[i]=r.e[i+1];r.e[i]=t;}else{t=r.e[8];for(i=8;i>0;i--)r.e[i]=r.e[i-1];r.e[i]=t;}}}h.push(z);}j=15;k="";m(0,4,8,"","");return k==""?"N":k;function m(s,a,b,u,v){if(s<j){q={'U':[0,-1],'D':[0,1],'L':[-1,0],'R':[1,0]}[u];if(q)a+=q[0],b+=q[1];v+=u;if(!b){j=s;k=v;return;}if(s>0){for(i=0;i<3;i++){z=h[s*2+i-2];r=z[b];if(i&&(i==1||r.s==2)&&r.e[a].toUpperCase()=='L')a+=r.d;if(a<0||a>8||b>8)return;z=h[s*2+i-1];e=z[b].e;if(e[a].toUpperCase()=='V'||(b<4&&e[a].toUpperCase()!='L'))return;}}t="UWRLD";for(x in t)m(s+1,a,b,t[x],v);}}}

Ungolfed

function solve(input) {
    var grids = [];
    var maxgrid = 40;
    // load input
    var grid = [];
    var lines = input.split('\n');
    for (var y = 0; y < 9; y++) {
        var line = lines[y];
        var row = {
            speed: parseInt(line[0]),
            direction: 1,
            cells: []
        }
        for (var x = 0; x < 9; x++) {
            var c = line[1 + x];
            if (c == 'v' || c == 'l')
                row.direction = -1;
            row.cells.push(c);
        }
        grid.push(row);
    }
    grids.push(grid);
    grids.push(grid);
    // animate grids
    for (var g = 2; g < maxgrid; g++) {
        grid = JSON.parse(JSON.stringify(grid));
        for (var y = 0; y < 9; y++) {
            var row = grid[y];
            if (row.speed > 0 && (g % 2 == 0 || row.speed == 2)) {
                if (row.direction == -1) {
                    var i, temp = row.cells[0];
                    for (i = 0; i < 8; i++)
                        row.cells[i] = row.cells[i + 1];
                    row.cells[i] = temp;
                }
                else {
                    var i, temp = row.cells[8];
                    for (i = 8; i > 0; i--)
                        row.cells[i] = row.cells[i - 1];
                    row.cells[i] = temp;
                }
            }
        }
        grids.push(grid);
    }
    var best = 15;
    var best_moves = "";
    var forceExit = false;

    move(0, 4, 8, "", "");
    return best_moves == "" ? "N" : best_moves;

    function move(step, fx, fy, dir, moves) {
        if (step >= best)
            return "die";
        switch (dir) {
            case 'U':
                fy--;
                break;
            case 'D':
                fy++;
                break;
            case 'L':
                fx--;
                break;
            case 'R':
                fx++;
                break;
        }
        if (dir != '')
            moves += dir;
        if (fy == 0) {
            best = step;
            best_moves = moves;
            return "win";
        }
        if (step > 0) {
            for (var i = 0; i < 3; i++) {
                var grid = grids[step * 2 + i - 2];
                if (i > 0 && (i == 1 || row.speed == 2)) {
                    var row = grid[fy];
                    if (row.cells[fx].toUpperCase() == 'L')
                        fx += row.direction;
                }
                if (fx < 0 || fx > 8 || fy > 8)
                    return "die";
                var grid = grids[step * 2 + i - 1];
                var cells = grid[fy].cells;
                if (cells[fx].toUpperCase() == 'V')
                    return "die";
                if (fy < 4 && cells[fx].toUpperCase() != 'L')
                    return "die";
            }
        }
        move(step+1, fx, fy, 'U', moves);
        move(step+1, fx, fy, 'W', moves);
        move(step+1, fx, fy, 'R', moves)
        move(step+1, fx, fy, 'L', moves);
        move(step+1, fx, fy, 'D', moves)
    }
}

Sto solo testando Up, Wait e Right nell'esempio per velocizzare le cose:

JSFiddle


1
Fantastico che qualcuno alla fine l'abbia fatto!
geokavel,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.