なんでこれに気づかなかったんだろうなAI + SnakeGame
とりあえず、途中の経路で蛇が通れない箇所をつくらないように
つくろうとおもう
Snake Game とりあえず100行以内で書きたかった。
おバカなAI追加
/**
* Copyright uwi ( http://wonderfl.net/user/uwi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/abXK
*/
// 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;
}
}