仕事と家庭の事情のため、時間が取れず、締め切り前夜に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
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>