好久没写 js 了,下一个项目要用 web 开发,虽然没有太多的机会参与代码开发,但是至少是要做web项目了,借 CSDN 上的一个算法帖子温习一下 JavaScript。
帖子的大概内容如下,打印出有规律的矩阵图形,矩形的大小可以为 2 - 9,以矩阵大小等于 8 为例。
---- 1 ---- (回形的内旋结构)
01 02 03 04 05 06 07 08
28 29 30 31 32 33 34 09
27 48 49 50 51 52 35 10
26 47 60 61 62 53 36 11
25 46 59 64 63 54 37 12
24 45 58 57 56 55 38 13
23 44 43 42 41 40 39 14
22 21 20 19 18 17 16 15
---- 2 ---- (斜切 [ / ] 循环的结构)
01 02 06 07 15 16 28 29
03 05 08 14 17 27 30 43
04 09 13 18 26 31 42 44
10 12 19 25 32 41 45 54
11 20 24 33 40 46 53 55
21 23 34 39 47 52 56 61
22 35 38 48 51 57 60 62
36 37 49 50 58 59 63 64
---- 3 ---- (斜切 [ / ] 跳跃的结构)
01 02 04 07 11 16 22 29
03 05 08 12 17 23 30 37
06 09 13 18 24 31 38 44
10 14 19 25 32 39 45 50
15 20 26 33 40 46 51 55
21 27 34 41 47 52 56 59
28 35 42 48 53 57 60 62
36 43 49 54 58 61 63 64
---- 4 ---- (斜切 [ \ ] 两边分的结构)
01 09 23 35 45 53 59 63
16 02 10 24 36 46 54 60
29 17 03 11 25 37 47 55
40 30 18 04 12 26 38 48
49 41 31 19 05 13 27 39
56 50 42 32 20 06 14 28
61 57 51 43 33 21 07 15
64 62 58 52 44 34 22 08
---- 5 ---- (由小矩形向外扩展的结构)
64 63 62 61 60 59 58 57
37 38 39 40 41 42 43 56
36 35 34 33 32 31 44 55
17 18 19 20 21 30 45 54
16 15 14 13 22 29 46 53
05 06 07 12 23 28 47 52
04 03 08 11 24 27 48 51
01 02 09 10 25 26 49 50
---- 6 ---- (从上到下左右迂回的结构)
01 02 03 04 05 06 07 08
16 15 14 13 12 11 10 09
17 18 19 20 21 22 23 24
32 31 30 29 28 27 26 25
33 34 35 36 37 38 39 40
48 47 46 45 44 43 42 41
49 50 51 52 53 54 55 56
64 63 62 61 60 59 58 57
我的解决思路是这样的,把矩阵生成看成一系列的动作游走后的轨迹。以 1 图为例,就是从原点 (0, 0) 开始向右走 -> 碰壁后向下走 -> 碰壁后向左走 -> 碰壁后向上走,四个过程如此循环,最终便可走完全图。分析后可以把动作归纳为以下七种:
TurnLeft // 左转
Up // 上转
TurnRight // 右转
Down // 下转
ReverseX // 反转 X 轴,如 size = 8 的矩阵,x = 0 反转后 x = 7
ReverseY // 反转 Y 轴
SwitchXY // 交换 X, Y 坐标的值,如 [1, 4] 交换后为 [4, 1]
另外加一个特殊的动作:
OneOff // 表示该动作只使用一次,不用等到碰壁后再使用下一个动作。
注:斜走的动作可以分解上下左右的组合,如 “向右下方转” 可以分解为 “右转 + 下转”。
封装后的 Matrix 类:

Matrix 类
var Action = {
TurnLeft: 1, Up: 2, TurnRight: 4, Down: 8,
ReverseX: 16, ReverseY: 32, SwitchXY: 64,
OneOff: 128
};
var Point = function (x, y) { this.X = x; this.Y = y; }
var Matrix = function (reverse)
{
var actionList = [], actionIndex = 0;
this.AddAction = function ()
{
var actions = [];
for (var i = 0; i < arguments.length; i++) actions.push(arguments[i]);
actionList.push(actions);
}
this.GetArray = function (size)
{
actionIndex = 0;
var point = new Point(0, 0);
var array = new Array(size);
for (var i = 0; i < size; i++) array[i] = new Array(size);
var minValue = 1, maxValue = size * size;
var value = reverse ? maxValue : minValue;
do
{
array[point.X][point.Y] = value;
point = GetNextPoint(array, size, point);
value += (reverse ? -1 : 1);
}
while (value >= minValue && value <= maxValue);
return array;
}
function GetNextPoint (array, size, currentPoint)
{
var attempts = 0;
while (attempts <= 2)
{
attempts++;
var actions = actionList[actionIndex % actionList.length];
for (var i = 0; i < actions.length; i++)
{
var x = currentPoint.X, y = currentPoint.Y;
if ((actions[i] & Action.TurnLeft) == Action.TurnLeft) x--;
if ((actions[i] & Action.TurnRight) == Action.TurnRight) x++;
if ((actions[i] & Action.Up) == Action.Up) y--;
if ((actions[i] & Action.Down) == Action.Down) y++;
if ((actions[i] & Action.ReverseX) == Action.ReverseX) x = size - 1 - x;
if ((actions[i] & Action.ReverseY) == Action.ReverseY) y = size - 1 - y;
if ((actions[i] & Action.SwitchXY) == Action.SwitchXY) { var tmp = x; x = y; y = tmp; }
if (x > -1 && x < size && y > -1 && y < size && array[x][y] == undefined)
{
if ((actions[i] & Action.OneOff) == Action.OneOff) actionIndex++;
return new Point(x, y);
}
}
actionIndex++;
}
return null;
}
}
调用,生成矩阵:

生成矩阵
var matrixList = [];
matrixList[0] = new Matrix(false);
matrixList[0].AddAction(Action.TurnRight);
matrixList[0].AddAction(Action.Down);
matrixList[0].AddAction(Action.TurnLeft);
matrixList[0].AddAction(Action.Up);
matrixList[1] = new Matrix(false);
matrixList[1].AddAction(Action.TurnRight | Action.OneOff, // 先尝试右转,如果失败,再尝试下转。
Action.Down | Action.OneOff);
matrixList[1].AddAction(Action.Down | Action.TurnLeft); // 向左下方转
matrixList[1].AddAction(Action.Down | Action.OneOff,
Action.TurnRight | Action.OneOff);
matrixList[1].AddAction(Action.Up | Action.TurnRight);
matrixList[2] = new Matrix(false);
matrixList[2].AddAction(Action.Down | Action.SwitchXY | Action.OneOff,
Action.TurnRight | Action.SwitchXY | Action.OneOff);
matrixList[2].AddAction(Action.TurnLeft | Action.Down);
matrixList[3] = new Matrix(false);
matrixList[3].AddAction(Action.TurnRight | Action.Down);
matrixList[3].AddAction(Action.TurnLeft | Action.ReverseX | Action.ReverseY | Action.OneOff,
Action.ReverseX | Action.ReverseY | Action.OneOff);
matrixList[4] = new Matrix(true);
matrixList[4].AddAction(Action.TurnRight);
matrixList[4].AddAction(Action.Down);
matrixList[4].AddAction(Action.TurnLeft | Action.OneOff);
matrixList[4].AddAction(Action.Up);
matrixList[4].AddAction(Action.TurnLeft);
matrixList[4].AddAction(Action.Down | Action.OneOff);
matrixList[5] = new Matrix(false);
matrixList[5].AddAction(Action.TurnRight);
matrixList[5].AddAction(Action.Down | Action.OneOff);
matrixList[5].AddAction(Action.TurnLeft);
matrixList[5].AddAction(Action.Down | Action.OneOff);
for (var i = 0; i < matrixList.length; i++)
{
document.writeln("---- " + (i + 1) + " ----<br>");
PrintArray(matrixList[i].GetArray(8));
}
function PrintArray(array)
{
var size = array.length;
for(var y = 0; y < size; y++)
{
for(var x = 0; x < size; x++)
{
document.write("<span style='background:#" +
(array[x][y] + 128).toString(16) + (array[x][y] + 128).toString(16) + (array[x][y] + 16).toString(16) +
"'>");
document.write((array[x][y] < 10 ? "0" : "") + array[x][y]);
document.write(" </span>");
}
document.write("<br>");
}
}
生成的效果图:
---- 1 ----
01 02 03 04 05 06 07 08
28 29 30 31 32 33 34 09
27 48 49 50 51 52 35 10
26 47 60 61 62 53 36 11
25 46 59 64 63 54 37 12
24 45 58 57 56 55 38 13
23 44 43 42 41 40 39 14
22 21 20 19 18 17 16 15
---- 2 ----
01 02 06 07 15 16 28 29
03 05 08 14 17 27 30 43
04 09 13 18 26 31 42 44
10 12 19 25 32 41 45 54
11 20 24 33 40 46 53 55
21 23 34 39 47 52 56 61
22 35 38 48 51 57 60 62
36 37 49 50 58 59 63 64
---- 3 ----
01 02 04 07 11 16 22 29
03 05 08 12 17 23 30 37
06 09 13 18 24 31 38 44
10 14 19 25 32 39 45 50
15 20 26 33 40 46 51 55
21 27 34 41 47 52 56 59
28 35 42 48 53 57 60 62
36 43 49 54 58 61 63 64
---- 4 ----
01 09 23 35 45 53 59 63
16 02 10 24 36 46 54 60
29 17 03 11 25 37 47 55
40 30 18 04 12 26 38 48
49 41 31 19 05 13 27 39
56 50 42 32 20 06 14 28
61 57 51 43 33 21 07 15
64 62 58 52 44 34 22 08
---- 5 ----
64 63 62 61 60 59 58 57
37 38 39 40 41 42 43 56
36 35 34 33 32 31 44 55
17 18 19 20 21 30 45 54
16 15 14 13 22 29 46 53
05 06 07 12 23 28 47 52
04 03 08 11 24 27 48 51
01 02 09 10 25 26 49 50
---- 6 ----
01 02 03 04 05 06 07 08
16 15 14 13 12 11 10 09
17 18 19 20 21 22 23 24
32 31 30 29 28 27 26 25
33 34 35 36 37 38 39 40
48 47 46 45 44 43 42 41
49 50 51 52 53 54 55 56
64 63 62 61 60 59 58 57