二维阵列
Daniel Shiffman
数组按线性顺序跟踪多个信息片段,即一维列表。然而,与某些系统(数字图像、棋盘游戏等)相关联的数据是二维的。为了使这些数据可视化,我们需要一个多维数据结构,即多维数组。二维数组实际上只不过是数组的数组(三维数组是数组的数组)。想想你的晚餐。你可以有一个你吃的东西的一维列表:
(生菜、西红柿、牛排、土豆泥、蛋糕、冰淇淋)
或者你可以有一个包含三道菜的二维列表,每道菜都包含你吃的两样东西:
(生菜、西红柿)和(牛排、土豆泥)和(蛋糕、冰淇淋)
对于数组,我们老式的一维数组如下所示:
int[] myArray = {0,1,2,3};
二维数组如下所示:
int[][] myArray = { {0,1,2,3}, {3,2,1,0}, {3,5,6,1}, {3,8,3,4} };
为了我们的目的,最好把二维数组看作一个矩阵。矩阵可以被认为是一个数字网格,排列成行和列,有点像宾果游戏板。为了说明这一点,我们可以将二维数组写出如下:
int[][] myArray = { {0, 1, 2, 3},
{3, 2, 1, 0},
{3, 5, 6, 1},
{3, 8, 3, 4} };
我们可以使用这种类型的数据结构来编码有关图像的信息。例如,以下灰度图像可以由以下数组表示:
int[][] myArray = { {236, 189, 189, 0},
{236, 80, 189, 189},
{236, 0, 189, 80},
{236, 189, 189, 80} };
为了遍历一维数组的每个元素,我们使用for循环,即:
int[] myArray = new int[10];
for (int i = 0; i < myArray.length; i++) {
myArray[i] = 0;
}
对于二维数组,为了引用每个元素,必须使用两个嵌套循环。这为矩阵中的每一列和每一行提供了一个反变量。
int cols = 10;
int rows = 10;
int[][] myArray = new int[cols][rows];
//两个嵌套循环允许我们访问二维数组中的每个点。
//对于每一列I,访问每一行J。
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
myArray[i][j] = 0;
}
}
例如,我们可以编写一个使用二维数组绘制灰度图像的程序。
size(200,200);
int cols = width;
int rows = height;
// 声明二维数组
int[][] myArray = new int[cols][rows];
// Initialize 2D array values
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
myArray[i][j] = int(random(255));
}
}
//绘制点
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
stroke(myArray[i][j]);
point(i,j);
}
}
二维数组也可用于存储对象,这对于编写包含某种“网格”或“板”的草图特别方便。以下示例显示存储在二维数组中的单元格对象网格。每个单元格是一个矩形,其亮度在0-255之间以正弦函数振荡。
//二维对象数组
Cell[][] grid;
//网格中的列和行数
int cols = 10;
int rows = 10;
void setup() {
size(200,200);
grid = new Cell[cols][rows];
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
// 初始化每个对象
grid[i][j] = new Cell(i*20,j*20,20,20,i+j);
}
}
}
void draw() {
background(0);
//计数器变量i和j也是列号和行号以及
//用作网格中每个对象的构造函数的参数。
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
// 振荡并显示每个对象
grid[i][j].oscillate();
grid[i][j].display();
}
}
}
//单元格对象
class Cell {
//单元格对象知道其在网格中的位置
//以及变量x,y,w,h的大小
float x,y; // x、 y位置
float w,h; // 宽度和高度
float angle; // 振荡亮度角
// 单元构造函数
Cell(float tempX, float tempY, float tempW, float tempH, float tempAngle) {
x = tempX;
y = tempY;
w = tempW;
h = tempH;
angle = tempAngle;
}
// 振荡意味着增加角度
void oscillate() {
angle += 0.02;
}
void display() {
stroke(255);
// 正弦波计算颜色
fill(127+127*sin(angle));
rect(x,y,w,h);
}
}