ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南

[讨论] VBA通过二个题目加深对数组赋值的理解-----蛇形矩阵和螺旋矩阵,详情见附件

[复制链接]

TA的精华主题

TA的得分主题

发表于 2014-3-29 20:33 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖已被收录到知识树中,索引项:数组集合和字典
螺旋形代码:

方向同End()参数的习惯。1、2、3、4为左右上下。
实际次序为2、4、1、3 即右、下、左、上的顺时针螺旋。
  1. Sub test() 'by kagawa
  2.     [a1].CurrentRegion = ""
  3.     n = InputBox("n=", , 19)
  4.     ReDim a(1 To n, 1 To n)
  5.     m = n ^ 2
  6.     i1 = 1: i2 = 1: j1 = 1: j2 = n: r = 2
  7.     Do
  8.         For i = i1 To i2
  9.             For j = j1 To j2
  10.                 k = k + 1
  11.                 If r = 2 Then
  12.                     a(i, j) = k
  13.                 ElseIf r = 4 Then
  14.                     a(i, j) = k
  15.                 ElseIf r = 1 Then
  16.                     a(i, n - j) = k
  17.                 ElseIf r = 3 Then
  18.                     a(n - i + 1, j) = k
  19.                 End If
  20.                 [a1].Resize(n, n) = a '这句产生动画效果 要速度就注释掉
  21.             Next
  22.         Next
  23.         If r = 2 Then
  24.             j1 = j2: i2 = n - i1 + 1: i1 = i1 + 1: r = 4
  25.         ElseIf r = 4 Then
  26.             i1 = i2: j1 = n - j2 + 1: j2 = j2 - 1: r = 1
  27.         ElseIf r = 1 Then
  28.             j2 = j1: i1 = n - i2 + 2: i2 = i2 - 1: r = 3
  29.         ElseIf r = 3 Then
  30.             i2 = i1: j2 = n - j1: j1 = j1 + 1: r = 2
  31.         End If
  32.     Loop Until k = m
  33.     [a1].Resize(n, n) = a
  34.     [a1].Offset(i - 2, j - 2).Activate
  35. End Sub
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-3-29 20:35 | 显示全部楼层
或许能找到一个通用公式,即已知序号k,计算得到螺旋后的二维数组行、列位置。

这样虽然速度不可能快,但比较有趣。

TA的精华主题

TA的得分主题

发表于 2014-3-30 00:22 | 显示全部楼层
改成顺时针、逆时针两个方向,矩阵大小设置为x行、y列。
  1. Sub test1() 'by kagawa
  2.     Dim i&, j&, i1&, j1&, i2&, j2&, k&, m&, r&, x&, y&, z&
  3.     [a1].CurrentRegion = ""
  4.     x = InputBox("行数x=")
  5.     y = InputBox("列数y=")
  6.     z = MsgBox("顺时针Yes/逆时针No", vbYesNo)
  7.     ReDim a(1 To x, 1 To y)
  8.     m = x * y
  9.     i1 = 1: j1 = 1
  10.     If z = vbYes Then
  11.         i2 = 1: j2 = y: r = 2 '2-4-1-3
  12.     Else
  13.         i2 = x: j2 = 1: r = 4 '4-2-3-1
  14.     End If
  15.     Do
  16.         For i = i1 To i2
  17.             For j = j1 To j2
  18.                 k = k + 1
  19.                 If r Mod 2 Then
  20.                     If r = 1 Then
  21.                         If z = vbYes Then a(i, y - j) = k Else a(i, y - j + 1) = k
  22.                     Else 'r=3
  23.                         If z = vbYes Then a(x - i + 1, j) = k Else a(x - i, j) = k
  24.                     End If
  25.                 Else
  26.                     a(i, j) = k
  27.                 End If
  28.                 [a1].Resize(x, y) = a
  29.             Next
  30.         Next
  31.         If k = m Then Exit Do
  32.         If r = 1 Then
  33.             If z = vbYes Then '2-4-1-3
  34.                 j2 = j1: i1 = x - i2 + 2: i2 = i2 - 1: r = 3
  35.             Else '4-2-3-1-4
  36.                 j2 = j1: i2 = x - i1: i1 = i1 + 1: r = 4
  37.             End If
  38.         ElseIf r = 2 Then
  39.             If z = vbYes Then '2-4-1-3
  40.                 j1 = j2: i2 = x - i1 + 1: i1 = i1 + 1: r = 4
  41.             Else '4-2-3-1
  42.                 j1 = j2: i1 = x - i2 + 1: i2 = i2 - 1: r = 3
  43.             End If
  44.         ElseIf r = 3 Then
  45.             If z = vbYes Then '2-4-1-3-2
  46.                 i2 = i1: j2 = y - j1: j1 = j1 + 1: r = 2
  47.             Else '4-2-3-1
  48.                 i2 = i1: j1 = y - j2 + 2: j2 = j2 - 1: r = 1
  49.             End If
  50.         ElseIf r = 4 Then
  51.             If z = vbYes Then '2-4-1-3
  52.                 i1 = i2: j1 = y - j2 + 1: j2 = j2 - 1: r = 1
  53.             Else '4-2-3-1
  54.                 i1 = i2: j2 = y - j1 + 1: j1 = j1 + 1: r = 2
  55.             End If
  56.         End If
  57.     Loop
  58.     [a1].Resize(x, y) = a
  59.     If r Mod 2 Then [a1].Offset(i1 - 1, j1 - 1).Activate Else [a1].Offset(i2 - 1, j2 - 1).Activate
  60. End Sub
复制代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-3-30 08:21 | 显示全部楼层
香川群子 发表于 2014-3-29 18:09
我出的【左右蛇行】题目的代码非常简单。事实上一句代码就解决了。→ 数组的行列位置计算是很见功力的。

...

呵呵,谢谢裙子的参与,倍感荣幸啊,其实左右蛇行的,用公式就可以搞定的,http://club.excelhome.net/thread-1102841-1-1.html

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-3-30 08:38 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
香川群子 发表于 2014-3-30 00:22
改成顺时针、逆时针两个方向,矩阵大小设置为x行、y列。

方向和大小都可以通过变量来控制

TA的精华主题

TA的得分主题

发表于 2014-3-31 09:24 | 显示全部楼层
来试试
Sub Main()
    Const Num As Integer = 10
    Const k1 As Integer = 1 '1为顺时针,0为逆时针
    Dim i As Integer, j As Integer
    Dim r As Integer, c As Integer, n As Integer
    Dim k2 As Integer
    If k1 Then k2 = 0 Else k2 = 1
    r = 1: c = 1: n = 1
    Cells.Clear
    For i = Num - 1 To 1 Step -2
        For j = 0 To i - 1
            Cells(r + j * k2, c + j * k1) = n
            Cells(r + j * k1 + i * k2, c + i * k1 + j * k2) = n + i
            Cells(r + i - j * k2, c + i - j * k1) = n + i * 2
            Cells(r + (i - j) * k1, c + (i - j) * k2) = n + i * 3
            n = n + 1
        Next
        n = n + i * 3
        r = r + 1: c = c + 1
    Next
    If Num Mod 2 Then Cells(r, c) = n
End Sub

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-3-31 13:45 | 显示全部楼层
141475046 发表于 2014-3-31 09:24
来试试
Sub Main()
    Const Num As Integer = 10

谢谢参与,当然最好是能写到数组里,这样看起来就更好了

TA的精华主题

TA的得分主题

发表于 2014-3-31 13:55 | 显示全部楼层
经研究,螺旋矩阵算法可以大大地简化:
  1. Sub test2() '顺时针螺旋 by kagawa
  2.     Dim x&, y&, i&, j&, k&, l&, n&, ii&, jj&
  3.    
  4.     [a1].CurrentRegion = ""
  5.     x = InputBox("x=")
  6.     y = InputBox("y=")
  7.     ReDim a(1 To x, 1 To y)
  8.    
  9.     i = 1: j = 0
  10.     r = Array(0, 1, 0, -1) '行列递增规律
  11.     If x > y Then n = y * 2 - 1 Else n = x * 2 - 2 '计算螺旋圈数
  12.     For t = 0 To n '按圈数遍历循环
  13.         ii = r(t Mod 4): jj = r((t + 1) Mod 4) '计算本圈螺旋的行增量ii、列增量jj
  14.         tt = (t + 1) \ 2 '计算本圈减少数
  15.         For l = 1 To IIf(t Mod 2, x - tt, y - tt) '按计算结果循环本圈
  16.             i = i + ii: j = j + jj '本次行列位置递增改变
  17.             k = k + 1: a(i, j) = k '对应位置写入序号k
  18.             [a1].Resize(x, y) = a '输出结果到工作表 (观察用) 要速度时注释掉
  19.         Next
  20.     Next
  21.    
  22.     [a1].Resize(x, y) = a '输出到工作表
  23.     [a1].Offset(i - 1, j - 1).Activate '光标移动到当前结束位置 即最大k位置
  24. End Sub
复制代码
本代码的要点,就在于掌握了螺旋式行进时的行、列位置变化规律,以及行列位置的变化长度。


评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-3-31 14:01 | 显示全部楼层
不使用行列增量变化数组r
直接计算也可以:

If t Mod 2 Then i2 = (-1) ^ ((t - 1) / 2) : j2 = 0 Else i2 = 0 : j2 = (-1) ^ (t / 2)

总体上相当于按照下面循环就直接计算出新的行列位置,然后直接赋值了。
For l = 1 To IIf(t Mod 2, x - tt, y - tt)
     i = i + ii: j = j + jj
     k = k + 1: a(i, j) = k
Next

所以这个算法应该是最直接的。


…………
逆时针螺旋应该可以按同样思路进行,但稍有不同。

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-3-31 14:27 | 显示全部楼层
香川群子 发表于 2014-3-31 13:55
经研究,螺旋矩阵算法可以大大地简化:本代码的要点,就在于掌握了螺旋式行进时的行、列位置变化规律,以及 ...

嗯,其实整体思路是没变的,你的代码的亮点在于辅助数组r=Array(0,1,0,-1),这个用得是非常好,代替了他们用的case语句
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-24 00:19 , Processed in 0.043869 second(s), 6 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表