仕事と家庭の事情のため、時間が取れず、締め切り前夜に4時間(徹夜ですがなにか?)だけ時間が取れて挑戦してみました。
結果は、ぼろぼろでしたorz
4時間でできたのはPAC-MANだけ。
事前にウォーミングアップと、しりとりはレベル3を手動で勝っていて、OAuthとPAC-MANをこの4時間で挑戦しようとしたのだけど、PAC-MANのみで終了という感じです。
そのPAC-MANも…仕様嫁おれって感じ。(xx;
1.5時間くらいでシミュレータはできたけど、敵の動きのアルゴリズムが問題と食い違っていて、仕様読み直して直してを繰り返しでした。最終的に以下のようなコードで何とかレベル1のみクリア。レベル2以降になると、まだどこか、違ってるみたい。
じゃ、コード貼りますね。
技術的にはCanvas使っています。便利ですね。
ちなみに、Chrome5でしかテストしていません。
上記状況(仕様読み間違えては修正)のため、ひどく突貫工事の後が残っています。とくにEnemy#moveをもっときれいにしたかったですね。
<html> <head> <title>PACMAN</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <script language="JavaScript"> GameCanvas = function(ctx) { this.ctx = ctx; this.drawText = function(text, x, y) { this.ctx.fillText(text, (x + 1) * 12, (y + 1) * 12); } } function $(id) { return document.getElementById(id); } Enemy = function(type, x, y) { this.isFirst = true; this.isJ = (type == "J"); this.type = type; this.x = x; this.y = y; this.dir = 0 // 0:left, 1:up, 2:right, 3:down; this.draw = function(gcvs) { if (this.isJ) { gcvs.drawText("J", this.x, this.y); } else { gcvs.drawText(type, this.x, this.y); } } this.move = function() { if (this.isFirst) { this.isFirst = false; var dSide = this.nextPositionByDir(3); var lSide = this.nextPositionByDir(0); var uSide = this.nextPositionByDir(1); var rSide = this.nextPositionByDir(2); if (PACMAN.getTextAt(dSide.x, dSide.y) != "#") { this.dir = 3; } else if (PACMAN.getTextAt(lSide.x, lSide.y) != "#") { this.dir = 0; } else if (PACMAN.getTextAt(uSide.x, uSide.y) != "#") { this.dir = 1; } else if (PACMAN.getTextAt(rSide.x, rSide.y) != "#") { this.dir = 2; } var nextPos = this.nextPositionByDir(this.dir); this.x = nextPos.x; this.y = nextPos.y; return; } var lSide = this.nextPositionByDir(this.dir - 1); var fSide = this.nextPositionByDir(this.dir); var rSide = this.nextPositionByDir(this.dir + 1); var bSide = this.nextPositionByDir(this.dir + 2); var crossCount = 0; if (PACMAN.getTextAt(lSide.x, lSide.y) != "#") { crossCount++; } if (PACMAN.getTextAt(fSide.x, fSide.y) != "#") { crossCount++; } if (PACMAN.getTextAt(rSide.x, rSide.y) != "#") { crossCount++; } if (PACMAN.getTextAt(bSide.x, bSide.y) != "#") { crossCount++; } if (this.isJ) { // 交差点 if (crossCount >= 3) { this.type = this.type == "R" ? "L" : "R"; } } // 交差点から始まる場合を考慮 if (this.type == "J") { this.type = "L"; } if (crossCount == 1) { this.dir = (this.dir + 2) % 4 } if (crossCount == 2) { var lSide = this.nextPositionByDir(this.dir - 1); var fSide = this.nextPositionByDir(this.dir); var rSide = this.nextPositionByDir(this.dir + 1); if (PACMAN.getTextAt(lSide.x, lSide.y) != "#") { this.dir = (this.dir - 1) % 4; if (this.dir < 0) {this.dir += 4; }} else if (PACMAN.getTextAt(fSide.x, fSide.y) != "#") { } else if (PACMAN.getTextAt(rSide.x, rSide.y) != "#") { this.dir = (this.dir + 1) % 4; } } if (crossCount >= 3) { switch (this.type) { case "V": var dx = PACMAN.player.x - this.x; var dy = PACMAN.player.y - this.y; if (dy > 0 && PACMAN.getTextAt(this.x, this.y + 1) != "#") { this.dir = 3; } else if (dy < 0 && PACMAN.getTextAt(this.x, this.y - 1) != "#") { this.dir = 1; } else if (dx > 0 && PACMAN.getTextAt(this.x + 1, this.y) != "#") { this.dir = 2; } else if (dx < 0 && PACMAN.getTextAt(this.x - 1, this.y) != "#") { this.dir = 0; } else if (PACMAN.getTextAt(this.x, this.y + 1) != "#") { this.dir = 3; } else if (PACMAN.getTextAt(this.x - 1, this.y) != "#") { this.dir = 0; } else if (PACMAN.getTextAt(this.x, this.y - 1) != "#") { this.dir = 1; } else if (PACMAN.getTextAt(this.x + 1, this.y) != "#") { this.dir = 2; } break; case "H": var dx = PACMAN.player.x - this.x; var dy = PACMAN.player.y - this.y; if (dx > 0 && PACMAN.getTextAt(this.x + 1, this.y) != "#") { this.dir = 2; } else if (dy > 0 && PACMAN.getTextAt(this.x, this.y + 1) != "#") { this.dir = 3; } else if (dy < 0 && PACMAN.getTextAt(this.x, this.y - 1) != "#") { this.dir = 1; } else if (dx < 0 && PACMAN.getTextAt(this.x - 1, this.y) != "#") { this.dir = 0; } else if (PACMAN.getTextAt(this.x, this.y + 1) != "#") { this.dir = 3; } else if (PACMAN.getTextAt(this.x - 1, this.y) != "#") { this.dir = 0; } else if (PACMAN.getTextAt(this.x, this.y - 1) != "#") { this.dir = 1; } else if (PACMAN.getTextAt(this.x + 1, this.y) != "#") { this.dir = 2; } break; case "L": var lSide = this.nextPositionByDir(this.dir - 1); var fSide = this.nextPositionByDir(this.dir); var rSide = this.nextPositionByDir(this.dir + 1); if (PACMAN.getTextAt(lSide.x, lSide.y) != "#") { this.dir = (this.dir - 1) % 4; if (this.dir < 0) {this.dir += 4; }} else if (PACMAN.getTextAt(fSide.x, fSide.y) != "#") { } else if (PACMAN.getTextAt(rSide.x, rSide.y) != "#") { this.dir = (this.dir + 1) % 4; } break; case "R": var lSide = this.nextPositionByDir(this.dir - 1); var fSide = this.nextPositionByDir(this.dir); var rSide = this.nextPositionByDir(this.dir + 1); if (PACMAN.getTextAt(rSide.x, rSide.y) != "#") { this.dir = (this.dir + 1) % 4; } else if (PACMAN.getTextAt(fSide.x, fSide.y) != "#") { } else if (PACMAN.getTextAt(lSide.x, lSide.y) != "#") { this.dir = (this.dir - 1) % 4; if (this.dir < 0) {this.dir += 4; }} break; } } var nextPos = this.nextPositionByDir(this.dir); this.x = nextPos.x; this.y = nextPos.y; } this.nextPositionByDir = function(dir) { dir = dir % 4; if (dir < 0) {dir += 4; } if (dir == 0) { return {x: this.x - 1, y: this.y}; } if (dir == 1) { return {x: this.x, y: this.y - 1}; } if (dir == 2) { return {x: this.x + 1, y: this.y}; } if (dir == 3) { return {x: this.x, y: this.y + 1}; } alert(dir); } } Player = function(x, y) { this.x = x; this.y = y; this.draw = function(gcvs) { gcvs.drawText("@", this.x, this.y); }; this.moveLeft = function() {if (PACMAN.getTextAt(this.x - 1, this.y) != "#") {this.x--; PACMAN.keyHistory += "h"; PACMAN.move()}}; this.moveUp = function() {if (PACMAN.getTextAt(this.x, this.y - 1) != "#") {this.y--; PACMAN.keyHistory += "k"; PACMAN.move()}}; this.moveRight = function() {if (PACMAN.getTextAt(this.x + 1, this.y) != "#") {this.x++; PACMAN.keyHistory += "l"; PACMAN.move()}}; this.moveDown = function() {if (PACMAN.getTextAt(this.x, this.y + 1) != "#") {this.y++; PACMAN.keyHistory += "j"; PACMAN.move()}}; this.stay = function() {PACMAN.keyHistory += "."; PACMAN.move()}; } Block = function(x, y) { this.x = x; this.y = y; this.draw = function(gcvs) { gcvs.drawText("#", this.x, this.y); }; } Dot = function(x, y) { this.x = x; this.y = y; this.draw = function(gcvs) { gcvs.drawText(".", this.x, this.y); }; } var PACMAN = new (function() { this.eatCount = 0; this.keyHistory = ""; this.player = new Player(0,0); this.enemies = []; this.blockes = []; this.dots = []; this.getTextAt = function(x, y) { if (this.player.x == x && this.player.y == y) { return "@"; } for (var i = 0; i < this.blockes.length; i++) { if (this.blockes[i].x == x && this.blockes[i].y == y) { return "#"; } } for (var i = 0; i < this.enemies.length; i++) { if (this.enemies[i].x == x && this.enemies[i].y == y) { return this.enemies[i].type; } } for (var i = 0; i < this.dots.length; i++) { if (this.dots[i].x == x && this.dots[i].y == y) { return "."; } } } this.move = function() { for (var i = 0; i < this.enemies.length; i++) { this.enemies[i].move(); } for (var i = 0; i < this.dots.length; i++) { if (this.player.x == this.dots[i].x && this.player.y == this.dots[i].y) { this.dots.splice(i, 1); this.eatCount++; break; } } }; this.draw = function() { var ctx = $('canvas').getContext('2d'); ctx.fillStyle = '#FFFFFF'; ctx.fillRect(0,0,1000,1000); ctx.fillStyle = '#000000'; ctx.font = '12px serif'; var gcvs = new GameCanvas(ctx); this.player.draw(gcvs); for (var i = 0; i < this.blockes.length; i++) { this.blockes[i].draw(gcvs); } for (var i = 0; i < this.enemies.length; i++) { this.enemies[i].draw(gcvs); } for (var i = 0; i < this.dots.length; i++) { this.dots[i].draw(gcvs); } $('keyHistory').innerText = this.keyHistory; $('point').innerText = this.eatCount; }; this.initialize = function(text) { this.eatCount = 0; this.keyHistory = ""; this.player = null; this.blockes = []; this.enemies = []; this.dots = []; var x = 0; var y = 0; for (var i = 0; i < text.length; i++) { var c = text.charAt(i) if (c == "\r") { continue; } if (c == "\n") { y++; x = 0; continue; } if (c == "@") { this.player = new Player(x, y); } if (c == "#") { this.blockes.push(new Block(x, y)); } if (c == ".") { this.dots.push(new Dot(x, y)); } if (c == "V" || c == "H" || c == "L" || c == "R" || c == "J") { this.enemies.push(new Enemy(c, x, y)); } x++; } this.draw(); } })(); </script> </head> <body> key <span id="keyHistory"></span><br /> point <span id="point"></span><br /> <canvas id="canvas" width="800" height="400"></canvas><br /> <textarea id="initData" cols="10" rows="10"> ########## #.....V..# #.######.# #...#....# #L#...#.## #.####..J# #..@##.#.# #.#....#.# #.R.#.#H.# ########## </textarea><br /> <a href="javascript:PACMAN.initialize($('initData').value);">initialize</a> </body> <script language="JavaScript"> PACMAN.draw(); window.onkeydown = function(e) { switch (e.keyCode) { case 32: PACMAN.player.stay(); break; case 37: PACMAN.player.moveLeft(); break; case 38: PACMAN.player.moveUp(); break; case 39: PACMAN.player.moveRight(); break; case 40: PACMAN.player.moveDown(); break; } PACMAN.draw(); } </script> </html>