// forked from uwi's forked from: forked from: 少し凝ったAI + SnakeGame // forked from uwi's forked from: 少し凝ったAI + SnakeGame // forked from uwi's 少し凝ったAI + SnakeGame // forked from bkzen's 簡易AI + SnakeGame // forked from bkzen's SnakeGame package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.events.Event; import flash.events.KeyboardEvent; import flash.geom.Rectangle; import flash.text.TextField; // とりあえず、途中の経路で蛇が通れない箇所をつくらないように // つくろうとおもう /** * Snake Game とりあえず100行以内で書きたかった。 * おバカなAI追加 */ [SWF (backgroundColor = "0xFFFFFF", frameRate = "60", width = "465", height = "465")] public class SnakeGame extends Sprite { // bmp, bmd 描画されるところ。 private var bmp: Bitmap, bmd: BitmapData; // key は今から進もうと思っている方向, way は今進んでいる方向。 private var key: uint, way: uint; // snake は ヘビの配列、[0] が先頭。 point はヘビが取っていくドット。 private var snake: Array, point: Snake; // 描画領域 private var viewRect: Rectangle; // speedK は スピード調整用の係数。 1 ~ N (小さいほど早い)、 speedC は wait 用のカウンタ(いじる必要なす)、 snakeLength は ヘビの長さ。(1~) private var speedK: int = 1, speedC: int = 0, snakeLength: int = 1; private var _snakeMap : Array; public function SnakeGame() { if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e: Event = null): void { removeEventListener(Event.ADDED_TO_STAGE, init); // addChild(bmp = new Bitmap(bmd = new BitmapData(stageW, stageW, false, 0))); bmp.scaleX = bmp.scaleY = cellSize; bmd.fillRect(viewRect = new Rectangle(1, 1, stageW2, stageW2), 0xFFFFFF); snake = [new Snake(stageW >> 1, stageW >> 1)], point = new Snake(); //stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); // AI を作るときはこの行をコメントアウト。 addEventListener(Event.ENTER_FRAME, loop); _tf = new TextField(); addChild(_tf); _tf.textColor = 0xff0000; _tf.width = 200; _tf.height = 465; _snakeMap = new Array(31 * 31); for(var r : uint = 1;r <= 29;r++){ for(var c : uint = 1;c <= 29;c++){ var v : int; if(r == 1){ v = -1; // left if(c == 1)v = 31; // down }else{ if(c == 28){ if(r % 2 == 0){ v = -31; // up }else{ v = 1; // right } }else if(c == 29){ if(r % 2 == 0){ v = -1; // left if(r == 2)v = 999; // unknown }else{ v = -31; // up } }else{ if(r == 29){ if(c % 2 == 0){ v = -31; // up }else{ v = 1; // right } }else if(r == 2){ if(c % 2 == 0){ v = 1; // right }else{ v = 31; // down } }else{ if(c % 2 == 0){ v = -31; // up }else{ v = 31; // down } } } } _snakeMap[r*31+c] = v; } } } private var _tf : TextField; private function onKeyDown(e: KeyboardEvent ): void { changeWay(e.keyCode); } /** * 方向変更 * @param keyCode * @return <Boolean> : 方向変更可能だったら true */ private function changeWay(keyCode: uint): Boolean { var b: Boolean; switch (keyCode) { case UP: if (b = (way != 1 << 1)) key = 1 << 0; break; case DOWN: if (b = (way != 1 << 0)) key = 1 << 1; break; case LEFT: if (b = (way != 1 << 3)) key = 1 << 2; break; case RIGHT: if (b = (way != 1 << 2)) key = 1 << 3; break; } return b; } private function loop(e: Event ): void { var s: Snake = snake[0], i: int, c: uint, tx: int, ty: int; var vx : int = 0, vy : int = 0; var optWay : int = _snakeMap[snake[0].y * 31 + snake[0].x]; if(optWay == 999){ if(point.x == 29 && point.y == 1){ vx = 0; vy = -1; }else{ vx = -1; vy = 0; } }else{ vx = optWay % 31; vy = int(optWay / 31); } tx = s.x, ty = s.y; s.x += vx; s.y += vy; c = bmd.getPixel(s.x, s.y); bmd.lock(); bmd.fillRect(viewRect, 0xFFFFFF); bmd.setPixel(s.x, s.y, 1); for (i = 1; i < snakeLength; i++) { s = snake[i]; vx = s.x, vy = s.y; bmd.setPixel(s.x = tx, s.y = ty, 0); tx = vx, ty = vy; } bmd.setPixel(point.x, point.y, 0xFF0000); bmd.unlock(); if(optWay == -999 || c == 0xff0000){ snakeLength = snake.push(point); var pindList : Array = []; for(i = 0;i < stageW * stageW;i++){ if(bmd.getPixel(i%stageW,i/stageW) == 0xffffff){ if(Math.abs(point.x - (i%stageW)) + Math.abs(point.y - uint(i/stageW)) > 1){ pindList.push(i); } } } var rind : int = pindList[int(Math.random() * pindList.length)]; point = new Snake(rind%stageW,rind/stageW); }else if (c == 0) { removeEventListener(Event.ENTER_FRAME, loop); return; } } } } const stageW: int = 31; // stage のサイズ const stageW2: int = stageW - 2; // stage のサイズから、枠を除いた数 const cellSize: int = 15; // 一つ一つのセルのサイズ (px) const UP: uint = 38; // AI が changeWay する時用の 上 Key のキーコード const DOWN: uint = 40; // AI が changeWay する時用の 下 Key のキーコード const LEFT: uint = 37; // AI が changeWay する時用の 左 Key のキーコード const RIGHT: uint = 39; // AI が changeWay する時用の 右 Key のキーコード class Snake { public var x: int, y: int; function Snake(x_: int = 0, y_: int = 0) { x = x_ || Math.random() * stageW2 + 1, y = y_ || Math.random() * stageW2 + 1; } } class Cell { public var wall:int; public var x:int; public var y:int; public var d:int; public var prev:Cell; public var score:Number; public function Cell(x : int, y : int) { this.x = x; this.y = y; this.d = -1; this.wall = 0; this.prev = null; this.score = Number.MAX_VALUE; } } なんでこれに気づかなかったんだろうなAI + SnakeGame