精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>● VB和Basic>>〓〓....周边技巧....〓〓>>kingywq对螺旋方阵的解法

主题:kingywq对螺旋方阵的解法
发信人: kingywq()
整理人: gzwsh(2002-11-05 22:59:39), 站内信件

    我用VB 6编了一个螺旋方阵的解法,可求解任意阶的螺旋方阵,只受限于
机器的性能和容量。

    以下是我的原代码,有些注释还需时间整理。

    以下是frmMain的代码:


Private lMin As Long
Private lMax As Long
Private lIncrement As Long
Private iRank As Integer

Private Sub Init()
    lMin = 1
    lMax = 4
    lIncrement = 1
    iRank = 2
End Sub

Private Function Format_Long(sValue As String, lMin As Long, lMax As Long, sMsg As String, sTitle As String, ByRef ctlText As TextBox) As Integer
    On Error GoTo HandleError
    
    Dim lTemp As Long
    
    If sValue = "" Then
        MsgBox sMsg, vbCritical + vbOKOnly, sTitle
        ctlText.SetFocus
        ctlText.SelStart = 1
        ctlText.SelLength = Len(sValue)
    Else
        If IsNumeric(sValue) = False Then
            MsgBox sMsg, vbCritical + vbOKOnly, sTitle
            ctlText.SetFocus
            ctlText.SelStart = 0
            ctlText.SelLength = Len(sValue)
        Else
            lTemp = CLng(sValue)
            If lMax > -1 Then
                If Not (lTemp >= lMin And lTemp <= lMax) Then
MsgBox sMsg, vbCritical + vbOKOnly, sTitle
ctlText.SetFocus
ctlText.SelStart = 0
ctlText.SelLength = Len(sValue)
Else
Format_Long = lTemp
End If
Else
If Not lTemp >= lMin Then
                    MsgBox sMsg, vbCritical + vbOKOnly, sTitle
                    ctlText.SetFocus
                    ctlText.SelStart = 0
                    ctlText.SelLength = Len(sValue)
                Else
                    Format_Long = lTemp
                End If
            End If
        End If
    End If
    
    Exit Function
HandleError:
    MsgBox "发生了错误号为" + CStr(Err.Number) + "的" + Err.Description + "错误,程序将退出,请检查所输入参数是否正确", vbCritical + vbOKOnly, "严重错误"
    End
End Function

Private Function Check_Validate(ByVal lMin As Integer, ByVal lMax As Integer, ByVal lIncrement As Integer, ByVal iRank As Integer, ByVal sMsg As String, ByVal sTitle As String) As Boolean
    On Error GoTo HandleError
    
    If lMax = lMin + (iRank * iRank - 1) * lIncrement Then
        Check_Validate = True
    Else
        MsgBox sMsg, vbInformation + vbOKOnly, stile
        Check_Validate = False
    End If
    
    Exit Function
HandleError:
    MsgBox "发生了错误号为" + CStr(Err.Number) + "的" + Err.Description + "错误,程序将退出,请检查所输入参数是否正确", vbCritical + vbOKOnly, "严重错误"
    End
End Function

Private Sub cmdClear_Click()
    frmResult.txtResult.Text = ""
End Sub

Private Sub cmdCreate_Click()
    Dim cPhalanx As clsPhalanx
    Dim aryPhalanx() As Long
    Dim bReturn As Boolean
    Dim iLoop1, iLoop2 As Integer
    Dim sResult, sTemp As String
    
    If Check_Validate(lMin, lMax, lIncrement, iRank, "所输入参数不能形成一个旋转方阵,请检查", "参数错误") = False Then
        txtMin.SetFocus
        txtMin.SelStart = 0
        txtMin.SelLength = Len(txtMin.Text)
    Else
        Set cPhalanx = New clsPhalanx
        cPhalanx.Min = lMin
        cPhalanx.Max = lMax
        cPhalanx.Increment = lIncrement
        cPhalanx.Rank = iRank
        
'        ReDim aryPhalanx(iRank, iRank) As Long
        bReturn = cPhalanx.getPhalanx(aryPhalanx)
        If bReturn = False Then
            MsgBox "计算时发生错误,请检查或联系作者", vbCritical + vbOKOnly, "错误"
            End
        End If
        
        frmResult.Show
        sResult = "方阵阶数:" + CStr(iRank) + vbCrLf
        For iLoop1 = 1 To iRank
            For iLoop2 = 1 To iRank
                sTemp = Trim(CStr(aryPhalanx(iLoop1, iLoop2)))
                sResult = sResult + sTemp + Space(Len(Trim(CStr(lMax))) + 5 - Len(sTemp))
            Next iLoop2
            sResult = sResult + vbCrLf
        Next iLoop1
        frmResult.txtResult.Text = frmResult.txtResult.Text + vbCrLf + vbCrLf + sResult
    End If
End Sub

Private Sub Form_Load()
    Init
End Sub

Private Sub Form_Unload(Cancel As Integer)
    End
End Sub

Private Sub txtMin_LostFocus()
    txtMin.Text = Trim(txtMin.Text)
    lMin = Format_Long(txtMin.Text, 1, -1, "请输入正确的起始数值,起始数值为填入方阵的最小整数", "参数错误", txtMin)
    txtMin.Text = CStr(lMin)
End Sub

Private Sub txtMax_LostFocus()
    txtMax.Text = Trim(txtMax.Text)
    lMax = Format_Long(txtMax.Text, 1, -1, "请输入正确的结束数值,起始数值为填入方阵的最大整数", "参数错误", txtMax)
    txtMax.Text = CStr(lMax)
End Sub

Private Sub txtIncrement_LostFocus()
    txtIncrement.Text = Trim(txtIncrement.Text)
    lIncrement = Format_Long(txtIncrement.Text, 1, -1, "请输入正确的间隔值,间隔值是方阵中相邻两个数间的间隔", "参数错误", txtIncrement)
    txtIncrement.Text = CStr(lIncrement)
End Sub

Private Sub txtRank_LostFocus()
    txtRank.Text = Trim(txtRank.Text)
    iRank = Format_Long(txtRank.Text, updRank.Min, updRank.Max, "请输入正确的方阵大小值,方阵大小值是方阵的阶数", "参数错误", txtRank)
    txtRank.Text = CStr(iRank)
End Sub

Private Sub updRank_Change()
    iRank = CInt(txtRank.Text)
End Sub


    以下是类clsPhalanx的代码:

Option Explicit

'保持属性值的局部变量
Private mvarMin As Long '局部复制
Private mvarMax As Long '局部复制
Private mvarIncrement As Long '局部复制
Private mvarRank As Integer '局部复制
Private maryInput() As Long       '保存传入的参数数组或由mvarMin,mvarMax,mvarIncrement,mvarRank形成的初始数组
Private maryResult() As Long      '保存处理后的结果数组
Private mbUseArray As Boolean     '是否用setArray传入参数数组

'检查参数是否可以组成一个方阵
Private Sub Check()
    On Error GoTo HandleError
    
    If mbUseArray = False Then
        If mvarMax <> mvarMin + (mvarRank * mvarRank - 1) * mvarIncrement Then
            MsgBox "所给参数不能形成一个方阵,请检查。", vbOKOnly + vbCritical, "严重错误"
            End
        End If
    End If
    
    Exit Sub
HandleError:
    MsgBox "发生了错误代码为" + CStr(Err.Number) + "的" + Err.Description + "的错误,程序将退出,请检查所参数是否正确或联系作者。", vbCritical + vbOKOnly, "严重错误"
    End
End Sub

'由mvarMin,mvarMax,mvarIncrement,mvarRank组成一个初始数组
Private Sub Init()
    On Error GoTo HandleError
    
    Dim iLoop As Integer
    
    If mbUseArray = False Then
        ReDim maryInput(1 To mvarRank * mvarRank) As Long
        ReDim maryResult(1 To mvarRank, 1 To mvarRank) As Long
        
        For iLoop = 1 To mvarRank * mvarRank
            maryInput(iLoop) = mvarMin + (iLoop - 1) * mvarIncrement
        Next iLoop
    End If

    Exit Sub
HandleError:
    MsgBox "发生了错误代码为" + CStr(Err.Number) + "的" + Err.Description + "的错误,程序将退出,请检查所参数是否正确或联系作者。", vbCritical + vbOKOnly, "严重错误"
    End
End Sub

'这是一个递归函数
'是程序的核心部分,对数组进行处理,形成旋转方阵
Private Sub Caculate(iRank As Integer)
    On Error GoTo HandleError
    
    Dim iTemp, iTemp1, iTemp2, iTemp3, iLoop As Integer
    
       
'假设有如下mvarRank*mvarRank阶的方阵
'
'
'            * ... *  *  *  *  *  *  * ... *
'            *            ...              *
'            *     A  *  *  *  *  B  C ... *
'            *     H                 * ... *
'            *     *                 * ... *
'            *     *      ...        * ... *
'            *     *                 * ... *
'            *     *                 D ... *
'            *     G  F  *  *  *  *  E ... *
'            *            ...              *
'            * ... *  *  *  *  *  *  * ... *
'
'
'以上是递归循环到阶数iRank时的方阵
'A...B C...D E...F G...H表示当前循环要填入数字的位置
'A在方阵中的位置应为(iTemp,iTemp),iTemp的值为(mvarRank - iRank) / 2 + 1
'C在方阵中的位置应为(iTemp,iTemp+iRank-1)
'E在方阵中的位置应为(iTemp+iRank-1,iTemp+iRank-1)
'G在方阵中的位置应为(iTemp+iRank-1,iTemp)
'当前iRank阶循环的内部(不包括外围)的元素个数为(iRank-2)*(iRank-2)
'因此,位置H处应填入maryInput(iTemp1),iTemp1的值为mvarRank * mvarRank - (iRank - 2) * (iRank - 2)
'其他位置应填入的值的情况请参看程序
'
'
'
    
    If iRank = 1 Then      '递归的终结条件之一,当当前要处理的阶数为1时
        iTemp = (mvarRank + 1) / 2
        maryResult(iTemp, iTemp) = maryInput(mvarRank * mvarRank)
    ElseIf iRank = 2 Then   '递归的终结条件之一,当当前要处理的阶数为2时
        iTemp = mvarRank / 2
        maryResult(iTemp, iTemp) = maryInput(mvarRank * mvarRank - 3)
        maryResult(iTemp, iTemp + 1) = maryInput(mvarRank * mvarRank - 2)
        maryResult(iTemp + 1, iTemp + 1) = maryInput(mvarRank * mvarRank - 1)
        maryResult(iTemp + 1, iTemp) = maryInput(mvarRank * mvarRank)
    Else    '如果当前要处理的阶数大于2
        iTemp = (mvarRank - iRank) / 2 + 1
        iTemp1 = mvarRank * mvarRank - (iRank - 2) * (iRank - 2)
        
        '填充位置A至B
        iTemp2 = (iRank - 1) * 4 - 1
        iTemp3 = iTemp1 - iTemp2
        For iLoop = 1 To iRank - 1
            maryResult(iTemp, iTemp + iLoop - 1) = maryInput(iTemp3 + iLoop - 1)
        Next iLoop
        
        '填充位置C至D
        iTemp2 = (iRank - 1) * 3 - 1
        iTemp3 = iTemp1 - iTemp2
        For iLoop = 1 To iRank - 1
            maryResult(iTemp + iLoop - 1, iTemp + iRank - 1) = maryInput(iTemp3 + iLoop - 1)
        Next iLoop
        
        '填充位置E至F
        iTemp2 = (iRank - 1) * 2 - 1
        iTemp3 = iTemp1 - iTemp2
        For iLoop = 1 To iRank - 1
            maryResult(iTemp + iRank - 1, (iTemp + iRank - 1) - (iLoop - 1)) = maryInput(iTemp3 + iLoop - 1)
        Next iLoop
        
        '填充位置G至H
        iTemp2 = (iRank - 1) * 1 - 1
        iTemp3 = iTemp1 - iTemp2
        For iLoop = 1 To iRank - 1
            maryResult((iTemp + iRank - 1) - (iLoop - 1), iTemp) = maryInput(iTemp3 + iLoop - 1)
        Next iLoop
        
        '递归调用
        Caculate (iRank - 2)
    End If
    
    Exit Sub
HandleError:
    MsgBox "发生了错误代码为" + CStr(Err.Number) + "的" + Err.Description + "的错误,请检查或联系作者。", vbCritical + vbOKOnly, "严重错误"
    End
End Sub

'返回处理后的结果方阵数组
Public Function getPhalanx(ByRef aryResult() As Long) As Boolean
    On Error GoTo HandleError
    
    Dim iLoop1, iLoop2 As Integer
    
    Check
    Init
    
    Caculate (mvarRank)
    
    ReDim aryResult(mvarRank, mvarRank) As Long
    
    '拷贝结果数组各元素之值到返回数组中
    For iLoop1 = 1 To mvarRank
        For iLoop2 = 1 To mvarRank
            aryResult(iLoop1, iLoop2) = maryResult(iLoop1, iLoop2)
        Next iLoop2
    Next iLoop1
    
    getPhalanx = True    '返回值为真表示调用成功
    
    Exit Function
HandleError:
    MsgBox "发生了错误代码为" + CStr(Err.Number) + "的" + Err.Description + "的错误,请检查或联系作者。", vbCritical + vbOKOnly, "严重错误"
    getPhalanx = False
End Function

'将要处理的数组作为参数传入,这样就具有很好的可扩展性
Public Function setArray(ByRef aryInput() As Long, iRank As Integer) As Boolean
    On Error GoTo HandleError
    Dim iLoop1, iLoop2 As Integer
    
    If UBound(aryInput, 1) = iRank And UBound(aryInput, 2) = iRank Then
        ReDim maryInput(1 To iRank, 1 To iRank) As Long
        
        For iLoop1 = 1 To iRank
            For iLoop2 = 1 To iRank
                maryInput(iLoop1, iLoop2) = aryInput(iLoop1, iLoop2)
            Next iLoop2
        Next iLoop1
        
        mvarRank = iRank
        mbUseArray = True
        setArray = True
    Else
        MsgBox "所传入数组不能组成方阵,请检查。", vbCritical + vbOKOnly, "错误"
        setArray = False
    End If
    
    Exit Function
HandleError:
    MsgBox "发生了错误代码为" + CStr(Err.Number) + "的" + Err.Description + "的错误,请检查参数或与作者联系。", vbCritical + vbOKOnly, "严重错误"
    setArray = False
End Function

Public Property Let Rank(ByVal vData As Integer)
'向属性指派值时使用,位于赋值语句的左边。
'Syntax: X.Rank = 5
    If vData < 2 Then
MsgBox "方阵的阶数应大于等于2,请检查参数", vbCritical + vbOKOnly, "错误"
End
Else
mvarRank = vData
End If
End Property


Public Property Get Rank() As Integer
'检索属性值时使用,位于赋值语句的右边。
'Syntax: Debug.Print X.Rank
Rank = mvarRank
End Property



Public Property Let Increment(ByVal vData As Long)
'向属性指派值时使用,位于赋值语句的左边。
'Syntax: X.Increment = 5
mvarIncrement = vData
End Property


Public Property Get Increment() As Long
'检索属性值时使用,位于赋值语句的右边。
'Syntax: Debug.Print X.Increment
Increment = mvarIncrement
End Property



Public Property Let Max(ByVal vData As Long)
'向属性指派值时使用,位于赋值语句的左边。
'Syntax: X.Max = 5
mvarMax = vData
End Property


Public Property Get Max() As Long
'检索属性值时使用,位于赋值语句的右边。
'Syntax: Debug.Print X.Max
Max = mvarMax
End Property



Public Property Let Min(ByVal vData As Long)
'向属性指派值时使用,位于赋值语句的左边。
'Syntax: X.Min = 5
mvarMin = vData
End Property


Public Property Get Min() As Long
'检索属性值时使用,位于赋值语句的右边。
'Syntax: Debug.Print X.Min
Min = mvarMin
End Property

Private Sub Class_Initialize()
mvarMin = 1
mvarMax = 4
mvarIncrement = 1
mvarRank = 2
mbUseArray = False
End Sub



若要整个程序,请发E-MAIL至[email protected]

希望能对你有所帮助。






[关闭][返回]