javascript座标_Javascript数组与坐标

前几日,看Eloquent Javascript一书,其中第二单元最后又这么一道题:用代码创建一串字符串,形成8×8的网格。其中,使用 newline character 也就是 \n 来分行。网格的每个位置要么是一个空格,要么是一个#号。这些字符要形成黑白棋盘一样的布局。将这一串数组传给console.log之后,应当打出下面这样的形式:

# # # #

# # # #

# # # #

# # # #

# # # #

# # # #

# # # #

# # # #

题目要求,要在程序中定义一个 size = 8 的变量,当传入不同的数值时,这个黑白棋盘的大小可以随意改变。一开始我自己写得很麻烦,进行了多重的判断和循环才得以实现。看了书上的参考代码之后,顿觉十分优雅:

var size = 8;

var str = "";

for(var x = 0; x < size; x++){

for(var y = 0; y < size; y++){

if((x+y)%2){

str += "#";

} else {

str += " ";

}

}

str += "\n";

}

console.log(str);

在此例中,虽然题干中说的是网格,但是由于网格的单位大小相同,其实也可以视为坐标系来看待。

按照坐标来看,上述x和y分别代表了横坐标和纵坐标

按照网格来看,上述x和y分别代表了行号和列号

倒推回来,如果将网格的字符视为一个一维数组(先忽略其中的换行符),那么根据一维数组中某个元素的index,就可以得到它在这样一个网格中的行号和列号(或者说它在坐标系中的x和y值)。方法也十分常见:

对于一维数组,可以字形设置宽高,将其视为二维的来使用,例如:

var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];

var width = 4, height = 3;

/*

0, 1, 2, 3,

4, 5, 6, 7,

8, 9, 10, 11

*/

//要想得到其中某个数字(比如6)在宽为4、高为3的网格(坐标系)中的位置(即坐标或行列号),可以通过该数字的index来反向取得。下面以数字6为例:

var index = arr.indexOf(6);

console.log(index);

var row = Math.floor(index/width);

var col = index % width;

console.log("row: ", row, "; col: ", col);

//row: 1; col: 2 注意,这时候row和col都是从0开始的

//另外根据坐标中的位置,也可以得到数组中某个处于这个位置的值,例如 (2, 1) 这个坐标位置的数字,我们看到是6。

//要得到6的位置,只需要用 x + y * width 就可以得到。如:2 + 1 * 4 = 6

//注意,行列的概念与坐标的概念,两者是相对的。如果得到行号和列号,那么行号所代表的其实是y轴的值;列号代表的其实是x轴的值。

可能引用Eloquent Javascript第7章中的一个例子,可以看得更明白。当我们面对的是二位数组时,可能使用行列的概念更加的直观,如:

var grid = [["top left", "top middle", "top right"],

["bottom left", "bottom middle", "bottom right"]];

console.log(grid[1][2]);

// → bottom right

//这里的grid[1][2]中的1、2可以分别视为行号为1、列号为2(两者都是从0开始记)

如果面对的是一维数组,那么用坐标的概念就更为直观,如:

var grid = ["top left", "top middle", "top right",

"bottom left", "bottom middle", "bottom right"];

console.log(grid[2 + (1 * 3)]);

// → bottom right

//这里的grid[2 + (1 * 3)] 中的2为x值,1为y值,3为width。

关于网格与坐标的使用,Eloquent Javascript中用到过很多次。很有意思的就是在第7章 Electronic Life 里面,用到的几个对象:

首先与坐标相关的就是坐标点了。作者定义了一个名为Vector的对象,可以简单理解为坐标的操作:

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);

//此处定义了两个向量相加的运算

}

Vector.prototype.times = function(factor){

return new Vector(this.x * factor, this.y * factor);

//此处定义了向量乘法的运算

}

现在坐标点有了,接下来就是坐标系或者网格了。作者定义了Grid这样一个对象,如下:

function Grid(width, height){

this.space = new Array(width * height);

//该Grid中的space属性其实就是一个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 + this.width * vector.y];

//此处定义了返回space这个数组中指定坐标位置的值的方法。这里就用到了 x + y * width 来寻找的

}

Grid.ptototype.set = function(vector, value){

this.space[vector.x + this.width * vector.y] = value;

//此处定义了设置space这个数组中指定坐标位置的值的方法。

}

//注意:space其实一直是一个一维数组,但是却可以将其视为二维分布的,根据坐标来进行设置和取值。

要看行列与坐标x、y的对应关系,下面这个例子可能更清楚一些

var objectMap = [];

var plan = ["############",

"# # #",

"# ~ ~ #",

"# ## #",

"# ## o####",

"# #",

"############"];

var width = plan[0].length;

var height = plan.length;

var chr = {

"#": "wall",

" ": "null",

"~": "water",

"o": "human"

}

plan.forEach(function(line, y){ //注意这里的第二个参数是y,也就是行数

for(var x = 0; x < line.length; x++){ //这里遍历的是x,也就是列数

objectMap[x + y * line.length] = chr[line[x]];

}

});

console.log(objectMap);

/*

["wall", "wall", "wall", "wall", "wall", "wall", "wall", "wall", "wall", "wall", "wall", "wall",

"wall", "null", "null", "null", "null", "null", "wall", "null", "null", "null", "null", "wall",

"wall", "null", "null", "null", "water", "null", "null", "null", "null", "water", "null", "wall",

"wall", "null", "null", "wall", "wall", "null", "null", "null", "null", "null", "null", "wall",

"wall", "null", "null", "wall", "wall", "null", "null", "human", "wall", "wall", "wall", "wall",

"wall", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "wall",

"wall", "wall", "wall", "wall", "wall", "wall", "wall", "wall", "wall", "wall", "wall", "wall"]

*/

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值