JS 构建对象实例

构建一个地图,

1.需要一个世界类,包含两个属性,一个图例属性,一个存储地图的属性。

2.需要一个地图类,地图类封装保存,取出地图元素的方法,以及存储地图。

一个格子类,该类为该格子,x,y坐标。

3.动物类,保存动物能用方向等信息。

流程:给世界类输入地图和图例(对象),1,世界类保存输入的地图为地图类,2,保存图例。通过一个foreach函数给该世界对象里的地图属性设置上每个元素,通过一个elementfromchar函数把非空的格子设置成动物类。

给世界添加了以一个属性tostring,获取每个地图类的格子元素,通过charfromelement函数输出成字符串。

4,添加一个view类为小动物的可视范围。该类会在世界类调用turn方法里面的letact方法时调用,也就是在动物移动的时候的才会去看往哪个方向可以移动。

 

整个过程大概是这样:通过传入地图字符串和图例,构建一个世界类的对象,世界类对象world有两个属性,grid是一个地图类,用来保存地图,legend存储图例对象。在world构造函数中会执行一个地图类(三个属性和四个方法,属性分别为space地图数组,为一维数组,另外2个为地图的宽和高,get方法,读取某个位置字符,set设置某个位置的字符,isinside方法判断该位置是否出界,并且实现了一个自己的forEach方法,目的是顶一个遍历grid的方法),可以使用call传递context)的方法,根据地图字符串设置好这个地图类,使用turn方法让world进行移动,移动规则为首先找到所有的动物即圆圈,根据已经建好的动物类的方法,使用worldletact方法让其移动,未来避免重复移动,在每次的移动中调用动物的act方法,调用的同时传入一个该位置的view类,同的view的方法检查可以移动的位置,移动是随机移动,移动方向根据view的look查看是否可以移动,不能的话找一个空位置移动,然后通过world tostring打印输出。

var plan = [
    "############################",
    "#      #    #      o      ##",
    "#                          #",
    "#          #####           #",
    "##         #   #    ##     #",
    "###           ##     #     #",
    "#           ###      #     #",
    "#   ####                   #",
    "#   ##       o             #",
    "# o  #         o       ### #",
    "#    #                     #",
    "############################"];

function Vector(x,y){
    this.x=x;
    this.y=y;
}
Vector.prototype.plus=function (other) {
    return new Vector(this.x+other.x,this.y+other.y);
};

//网格类
function Grid(width,height){
    this.space = new Array(width*height);
    this.width=width;
    this.height=height;
}
Grid.prototype.isInside=function(vector){
    return vector.x >=0 && vector.x < this.width &&
        vector.y >=0 && vector.y < this.height;
};
Grid.prototype.get=function(vector){
    return this.space[vector.x + (vector.y * this.width)];
}
Grid.prototype.set=function(vector,value){
    this.space[vector.x + vector.y * this.width]=value;
}
Grid.prototype.forEach=function(f,context){
    for(var y=0;y<this.height;y++){
        for(var x=0;x<this.width;x++){
            var value=this.space[x + y * this.width];//一会看一下这里的值,怎么处理的#
            if(value!=null)
            {
                console.log(value);
                f.call(context, value, new Vector(x,y));
            }

        }
    }
}
var grid=new Grid(5,5);
grid.set(new Vector(1,2),"X");
console.log(grid);

//映射方向
var directions = {
    "n":  new Vector( 0, -1),
    "ne": new Vector( 1, -1),
    "e":  new Vector( 1,  0),
    "se": new Vector( 1,  1),
    "s":  new Vector( 0,  1),
    "sw": new Vector(-1,  1),
    "w":  new Vector(-1,  0),
    "nw": new Vector(-1, -1)
};

//蠢萌小动物对象
function randomElement(array){
    return array[Math.floor(Math.random()*array.length)];
}
var directionNames = "n ne e se s sw w nw".split(" ");

function BouncingCritter(){
    this.direction = randomElement(directionNames);
};
BouncingCritter.prototype.act=function(view){
    if(view.look(this.direction)!=" ")
        this.direction = view.find(" ") || "s";
    return {type: "move", direction : this.direction};
};


function elementFromChar(legend, ch){
    if(ch == " ")
        return null;
    var element = new legend[ch]();//这里是创建类
    element.origiChar=ch;
    return element;
}
//World对象
function World(map,legend){
    var grid = new Grid(map[0].length, map.length);
    this.grid = grid;
    this.legend = legend;//图例对象

    map.forEach(function(line, y){
        for(var x=0;x<line.length;x++){
            grid.set(new Vector(x,y),elementFromChar(legend,line[x]));//这里是无法使用this.grid的
        }
    });
}
//Wall对象占据空间
function Wall(){}

//转化字符串
function charFromElement(element){
    if(element == null) return " ";
    else return element.origiChar;
}
World.prototype.toString = function(){
    var output="";
    for(var y=0;y<this.grid.height;y++){
        for(var x=0;x<this.grid.width;x++){
            var element = this.grid.get(new Vector(x, y));
            output += charFromElement(element);
        }
        output+="\n";
    }
    return output;
}
        //world 添加turn方法
World.prototype.turn = function(){
    var acted = [];
    this.grid.forEach(function(critter,vector){
        console.log(critter);
        if(critter.act && acted.indexOf(critter)==-1){
            acted.push(critter);
            this.letAct(critter,vector);
        }
    },this);
};
World.prototype.letAct=function(critter, vector){
    var action = critter.act(new View(this, vector));
    if(action && action.type == "move"){
        var dest = this.checkDestination(action, vector);
        if(dest && this.grid.get(dest) == null){
            this.grid.set(vector, null);
            this.grid.set(dest, critter);
        }
    }
};

World.prototype.checkDestination = function(action, vector){
    if(directions.hasOwnProperty(action.direction)){
        var dest=vector.plus(directions[action.direction]);
        if(this.grid.isInside(dest))
            return dest;
    }
}
var world=new World(plan,{'#':Wall,
                            "o":BouncingCritter});
console.log(world.toString());

//定义一个View类为小动物的可视范围
function View(world,vector){
    this.world = world;
    this.vector = vector;
}
View.prototype.look=function(dir){
    var target = this.vector.plus(directions[dir]);
    if(this.world.grid.isInside(target))
        return charFromElement(this.world.grid.get(target));
    else return '#';
};
View.prototype.findAll=function(ch){
    var found=[];
    for(var dir in directions)
        if(this.look(dir) == ch)
            found.push(dir);
    return found;
}
View.prototype.find=function(ch){
    var found=this.findAll(ch);
    if(found.length == 0) return null;
    return randomElement(found);
};


for(var i=0;i<5;i++){
    world.turn();
    console.log(world.toString());
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值