建構一個地圖,
1.需要一個世界類,包含兩個屬性,一個圖例屬性,一個存儲地圖的屬性。
2.需要一個地圖類,地圖類封裝儲存,取出地圖元素的方法,以及存儲地圖。
一個格子類,該類為該格子,x,y坐标。
3.動物類,儲存動物能用方向等資訊。
流程:給世界類輸入地圖和圖例(對象),1,世界類儲存輸入的地圖為地圖類,2,儲存圖例。通過一個foreach函數給該世界對象裡的地圖屬性設定上每個元素,通過一個elementfromchar函數把非空的格子設定成動物類。
給世界添加了以一個屬性tostring,擷取每個地圖類的格子元素,通過charfromelement函數輸出成字元串。
4,添加一個view類為小動物的可視範圍。該類會在世界類調用turn方法裡面的letact方法時調用,也就是在動物移動的時候的才會去看往哪個方向可以移動。
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());
}