สร้าง Frogger Solver


12

🐸🐸

คุณต้องสร้างโปรแกรมที่สั้นที่สุดเพื่อหาทางออกที่ดีที่สุดสำหรับเกม Frogger ที่เรียบง่ายบนกริด 9x9

องค์ประกอบของหลักสูตร:

  • L- บันทึก (ความยาว: 3-4) เมื่อคุณกระโดดเข้าสู่ระบบมันจะพาคุณไปด้วย
  • V - ยานพาหนะ (ความยาว: 1-2)
  • ความเร็ว (1-2): ทางด้านซ้ายของแถวจะเป็นความเร็วที่องค์ประกอบต่างๆในแถวเคลื่อนที่
  • Spaces: จะเสมอเป็นอย่างน้อยสองช่องว่างระหว่างองค์ประกอบ
  • ทิศทาง: ทั้งในส่วนยานพาหนะและส่วนบันทึกทิศทางการเคลื่อนไหวในแต่ละเลนจะสลับระหว่างซ้ายและขวา

โครงสร้างหลักสูตร:

  • ถ้าเป็นทุนมันจะไปทางขวา ถ้ามันเป็นตัวพิมพ์เล็กมันจะไปทางซ้าย องค์ประกอบทั้งหมดในแถวไปในทิศทางเดียวกัน ทันทีที่ส่วนหนึ่งขององค์ประกอบปิดหน้าจอองค์ประกอบนั้นจะปรากฏที่ด้านตรงข้ามของหน้าจอ
  • แถวแรกเป็นโซนที่ปลอดภัย กบเริ่มต้นที่Fซึ่งเป็นจุดเดียวกันเสมอ
  • 3 แถวถัดไปคือถนนที่มียานพาหนะ
  • แถวถัดไปเป็นเขตปลอดภัย
  • 3 แถวถัดไปคือน้ำ (น้ำสัมผัส == ความตาย) พร้อมบันทึก
  • เมื่อคุณไปถึงWเลนที่คุณชนะ
  • ถ้ากบตายมันก็กลับไป F

การควบคุมผู้เล่น:

  • L - ซ้าย
  • R - ใช่
  • U - ขึ้น
  • D - ลง
  • W - รอ

หลังจากที่คุณย้ายเฟรมอื่นผ่าน (หมายเหตุว่าเฟรมผ่านหลังจากที่ย้ายของคุณไม่ได้ในเวลาเดียวกับการย้ายของคุณ.) URWUULโปรแกรมของคุณจะต้องให้การแก้ปัญหาที่ดีที่สุดเป็นลำดับของตัวอักษรเช่น Nหากหลักสูตรมีทางออกไม่มีโปรแกรมของคุณควรเอาท์พุท

ตัวอย่าง: (ตั้งแต่ฉันทำสิ่งเหล่านี้ด้วยตัวเองฉันไม่ทราบว่าเป็นทางออกที่ดีที่สุดหรือไม่)

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

วิธีการแก้: WUWUUURWUULWUU

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

วิธีการแก้: WUWUWUUWUUWWUU

0WWWWWWWWW
2 llll  
2 LLL   
1 llll  
0         
2 v vv 
1 VV VV 
1 โวลต์   
0 F    

วิธีการแก้: WWUUUURURRWWUUU

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

การแก้ไข: N(ไม่มีทางผ่านแถวแรก)

ทดสอบสิ่งเหล่านี้ในตัวอย่างโดยวางหลักสูตรลงในกล่องข้อความและกด "โหลดหลักสูตร" จากนั้นวางโซลูชันลงใน "ป้อนข้อมูล" แล้วกดส่ง

ตัวอย่าง:มันยากที่จะทำกรณีทดสอบดังนั้นฉันจึงสร้างตัวอย่างนี้ซึ่งช่วยให้คุณดูว่าโปรแกรมของคุณสามารถแก้หลักสูตรที่สร้างแบบสุ่มหรือไม่ สำหรับจุดประสงค์ในการทดสอบสิ่งที่คุณต้องทำคือป้อนวิธีแก้ปัญหาโปรแกรมของคุณ (เช่นLRUWL...) ลงในส่วน "ป้อนข้อมูล" แล้วกดส่ง หากต้องการรีเซ็ตหลักสูตรกลับสู่สถานะเดิมให้กด "รีเซ็ต" แจ้งให้เราทราบหากคุณพบข้อบกพร่องใด ๆ

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>

เริ่มต้นที่ไหน:

ที่เกี่ยวข้อง:

ดูสิ่งนี้ด้วย:


1
สำหรับผู้ที่มองไม่เห็นตัวละครสองตัวแรกของโพสต์คือUnicode U + 1F438: Frog Face
cat

6
วิธีแก้ไข:WWUUUURURRWWUUU -> Chewie กำลังเล่น Frogger
Digital Trauma

3
@ DigitalTrauma "Let the Wookie win" - C3PO ไปยังเครื่องอาร์เคด
FryAmTheEggman

จะเกิดอะไรขึ้นถ้ากบกระทบขอบของหน้าจอ
user81655

2
@quintopia ตัวพิมพ์เล็กเหลืออยู่ดังนั้นพวกเขาจึงไปทางซ้าย
geokavel

คำตอบ:


1

Javascript, 854 ไบต์

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)
    }
}

ฉันแค่ทดสอบหา up, Wait and Right ในตัวอย่างเพื่อเพิ่มความเร็ว:

JSFiddle


1
เจ๋งมากที่มีคนทำสิ่งนี้ในที่สุด!
geokavel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.