|
VFP 愛用者社區 本討論區為 Visual Foxpro 愛用者經驗交流的地方, 請多多利用"搜尋"的功能, 先查看看有無前例可循, 如果還有不懂的再發問. 部份主題有附加檔案, 須先註冊成為社區居民才可以下載.
|
上一篇主題 :: 下一篇主題 |
發表人 |
內容 |
朱育興
註冊時間: 2003-08-25 文章: 661 來自: 台中市大里區
第 1 樓
|
發表於: 星期五 十月 03, 2003 1:21 am 文章主題: 遞迴函數的應用範例 |
|
|
* 遞迴函數的應用範例
* -------------------------------- *
* 這是在數學中的排列組合的題目
* 例:12 個數字中選 2 個排列的情形
* -------------------------------- *
CLEAR ALL
CLOSE ALL
WW_oMESSAGEBOX = CREATEOBJECT("UserForm1")
WITH WW_oMESSAGEBOX
.spinNum.Value = 12
.spinCircle.Value = 2
.spinNum.Valid
.Show
ENDWITH
IF VARTYPE(WW_oMESSAGEBOX) = "O"
IF !ISNULL(WW_oMESSAGEBOX)
WW_oMESSAGEBOX.Release
ENDIF
ENDIF
CLEAR ALL
CLOSE ALL
RETURN
* ---------- DEFINE CLASS ---------- *
DEFINE CLASS UserForm1 AS Form
AutoCenter = .T.
BackColor = RGB(0,128,192)
BorderStyle = 3
Closable = .F.
DoCreate = .T.
FontName = "細明體"
FontSize = 12
ForeColor = RGB(255,255,255)
KeyPreview = .T.
MaxButton = .F.
MinButton = .F.
ShowTips = .T.
ShowWindow = 1
Top = 100
WindowState = 0
WindowType = 1
Width = 250
Height = 140
Caption = "M 個數字中選 N 個排列一覽表"
ADD OBJECT (SYS(2015)) AS LABEL WITH;
AutoSize = .T.,;
BackStyle = 0,;
Caption = "請輸入 M 值",;
ForeColor = RGB(255,255,255),;
FontName = "細明體",;
FontSize = 12,;
Left = 15,;
Top = 27
ADD OBJECT spinNum AS SPINNER WITH;
FontName = "細明體",;
FontSize = 11,;
Format = "RK",;
Height = 23,;
InputMask = "99",;
KeyboardHighValue = 99,;
KeyboardLowValue = 1,;
Left = 130,;
SpinnerHighValue = 99,;
SpinnerLowValue = 1,;
Top = 25,;
Width = 45
ADD OBJECT (SYS(2015)) AS LABEL WITH;
AutoSize = .T.,;
BackStyle = 0,;
Caption = "請輸入 N 值",;
ForeColor = RGB(255,255,255),;
FontName = "細明體",;
FontSize = 12,;
Left = 15,;
Top = 52
ADD OBJECT spinCircle AS SPINNER WITH;
FontName = "細明體",;
FontSize = 11,;
Format = "RK",;
Height = 23,;
InputMask = "99",;
KeyboardHighValue = 99,;
KeyboardLowValue = 1,;
Left = 130,;
SpinnerHighValue = 99,;
SpinnerLowValue = 1,;
Top = 50,;
Width = 45
ADD OBJECT cmdYes AS CommandButton WITH;
Caption = "執行",;
Height = 25,;
Width = 75,;
Left = 15,;
Top = ThisForm.Height-36
ADD OBJECT cmdCancel AS CommandButton WITH;
Caption = "離開",;
Height = 25,;
Width = 75,;
Left = ThisForm.Width-90,;
Top = ThisForm.Height-36
PROCEDURE spinNum.Valid
* One
WITH This.Parent
STORE .spinNum.Value TO UserForm1_nNum
STORE .spinCircle.Value TO UserForm1_nCircle
ENDWITH
* Two
UserForm1_nCircle = MIN(UserForm1_nNum,UserForm1_nCircle)
* Three
WITH This.Parent
.spinCircle.KeyboardHighValue = UserForm1_nNum
.spinCircle.SpinnerHighValue = UserForm1_nNum
.spinCircle.Value = UserForm1_nCircle
ENDWITH
ENDPROC
PROCEDURE cmdYes.Click
WITH This.Parent
STORE .spinNum.Value TO UserForm1_nNum
STORE .spinCircle.Value TO UserForm1_nCircle
ENDWITH
=TT(UserForm1_nNum,UserForm1_nCircle)
ENDPROC
PROCEDURE KeyPress
LPARAMETERS nKeyCode, nShiftAltCtrl
DO CASE
* >> ESC
CASE nKeyCode = 27
.cmdCancel.SetFocus
.cmdCancel.Click
ENDCASE
ENDPROC
PROCEDURE Destroy
ThisForm.Visible = .F.
RELEASE THISFORM
ENDPROC
PROCEDURE cmdCancel.Click
THISFORM.Destroy()
ENDPROC
ENDDEFINE
* ---------- ENDDEFINE CLASS ---------- *
FUNCTION TT
* ---------------------- *
* L_nNum N 要幾個數字
* L_nCircle N 一次抽幾個
* ---------------------- *
PARAMETERS L_nNum,L_nCircle
LOCAL W1_SUB_A,W1_SUB_B
M_nMaxNum = L_nNum
M_nColOfTT = L_nCircle
* > 最後一組的合計數:避免最後一組會重覆一次
M_nSumOfLast = 0
FOR W1_SUB_A = M_nMaxNum-M_nColOfTT+1 TO M_nMaxNum
M_nSumOfLast = M_nSumOfLast + W1_SUB_A
ENDFOR
* >
DIMENSION M_aTT(1,M_nColOfTT)
M_nRowOfTT = 0
* >
=CIRCLE(1,L_nCircle,1)
* > 排版
W1_nLenOfMaxNum = LEN(LTRIM(STR(M_nMaxNum)))
W1_mCombine = ""
FOR W1_SUB_A = 1 TO ALEN(M_aTT,1)
FOR W1_SUB_B = 1 TO ALEN(M_aTT,2)
IF W1_SUB_A > 1 AND W1_SUB_B = 1
W1_mCombine = W1_mCombine + CHR(13) + CHR(10)
ENDIF
W1_mCombine = W1_mCombine + TRANSFORM(M_aTT(W1_SUB_A,W1_SUB_B),REPLICATE("9",W1_nLenOfMaxNum))
IF W1_SUB_B < ALEN(M_aTT,2)
W1_mCombine = W1_mCombine + SPACE(1)
ENDIF
ENDFOR
ENDFOR
* > 顯示
W1_cFileName = SYS(2015) + ".TXT"
=STRTOFILE(W1_mCombine,W1_cFileName)
MODIFY FILE (W1_cFileName) NOEDIT
DELETE FILE (W1_cFileName)
RETURN
FUNCTION CIRCLE
* 遞迴函數
* ------------------------------------ *
* L_nMinNum N 最小數
* L_nChoice N 同一次還剩幾個數可以抽
* L_nWho N 每一次抽的第幾個數
* ------------------------------------ *
PARAMETERS L_nMinNum,L_nChoice,L_nWho
LOCAL W1_nMinNum,W1_nChoice,W1_nWho
LOCAL W1_SUB_A,W1_SUB_B,W1_nSumOfLast
LOCAL W1_nNextMinNum,W1_nNextChoice,W1_nNextWho
W1_nMinNum = L_nMinNum
W1_nChoice = L_nChoice
W1_nWho = L_nWho
* >
IF W1_nChoice = 0
RETURN
ENDIF
IF W1_nWho > M_nColOfTT
RETURN
ENDIF
* >
IF W1_nWho = 1
M_nRowOfTT = M_nRowOfTT + 1
DIMENSION M_aTT(M_nRowOfTT,M_nColOfTT)
FOR W1_SUB_B = 1 TO ALEN(M_aTT,2)
M_aTT(M_nRowOfTT,W1_SUB_B) = 0
ENDFOR
ENDIF
* >
FOR W1_SUB_A = W1_nMinNum TO M_nMaxNum-W1_nChoice+1
M_aTT(M_nRowOfTT,W1_nWho) = W1_SUB_A
* > 當每一組的資料填滿時要新增下一組
IF (W1_nWho = ALEN(M_aTT,2))
* >> Set Filter:不是最後一組
W1_nSumOfLast = 0
FOR W1_SUB_B = 1 TO ALEN(M_aTT,2)
W1_nSumOfLast = W1_nSumOfLast + M_aTT(M_nRowOfTT,W1_SUB_B)
ENDFOR
IF W1_nSumOfLast = M_nSumOfLast
LOOP
ENDIF
* >> 新增
M_nRowOfTT = M_nRowOfTT + 1
DIMENSION M_aTT(M_nRowOfTT,M_nColOfTT)
* >
IF M_nRowOfTT > 1 AND W1_nWho > 1
FOR W1_SUB_B = 1 TO ALEN(M_aTT,2)
M_aTT(M_nRowOfTT,W1_SUB_B) = M_aTT(M_nRowOfTT-1,W1_SUB_B)
ENDFOR
ENDIF
ENDIF
* >
W1_nNextMinNum = W1_SUB_A + 1
W1_nNextChoice = W1_nChoice - 1
W1_nNextWho = W1_nWho + 1
=CIRCLE(W1_nNextMinNum,W1_nNextChoice,W1_nNextWho)
ENDFOR
RETURN |
|
回頂端 |
|
|
朱育興
註冊時間: 2003-08-25 文章: 661 來自: 台中市大里區
第 2 樓
|
發表於: 星期六 十月 04, 2003 5:49 pm 文章主題: |
|
|
由於之前是用陣列的方式,它會受陣列的最大筆數的限制而當掉
現在改為用 Cursor 的方式
* 遞迴函數的應用範例
* -------------------------------- *
* 這是在數學中的排列組合的題目
* 例:12 個數字中選 2 個排列的情形
* -------------------------------- *
CLEAR ALL
CLOSE ALL
M_cSetEscape = SET("ESCAPE")
SET ESCAPE OFF
__Esc = .F.
__IsCalc = .F. && 是否正在計算中
M_nTran = "99,999,999,999,999,999,999,999,999,999"
WW_oMESSAGEBOX = CREATEOBJECT("UserForm1")
WITH WW_oMESSAGEBOX
.spinNum.Value = 12
.spinCircle.Value = 2
.spinNum.Valid
.Show
ENDWITH
IF VARTYPE(WW_oMESSAGEBOX) = "O"
IF !ISNULL(WW_oMESSAGEBOX)
WW_oMESSAGEBOX.Release
ENDIF
ENDIF
SET ESCAPE &M_cSetEscape
CLEAR ALL
CLOSE ALL
RETURN
* ---------- DEFINE CLASS ---------- *
DEFINE CLASS UserForm1 AS Form
AutoCenter = .T.
BackColor = RGB(0,128,192)
BorderStyle = 3
Closable = .F.
DoCreate = .T.
FontName = "細明體"
FontSize = 12
ForeColor = RGB(255,255,255)
KeyPreview = .T.
MaxButton = .F.
MinButton = .F.
ShowTips = .T.
ShowWindow = 1
Top = 100
WindowState = 0
WindowType = 1
Width = 450
Height = 165
Caption = "M 個數字中選 N 個排列一覽表"
ADD OBJECT (SYS(2015)) AS LABEL WITH;
AutoSize = .T.,;
BackStyle = 0,;
Caption = "請輸入 M 值",;
ForeColor = RGB(255,255,255),;
FontName = "細明體",;
FontSize = 12,;
Left = 15,;
Top = 27
ADD OBJECT spinNum AS SPINNER WITH;
FontName = "細明體",;
FontSize = 11,;
Format = "RK",;
Height = 23,;
InputMask = "99",;
KeyboardHighValue = 99,;
KeyboardLowValue = 1,;
Left = 130,;
SpinnerHighValue = 99,;
SpinnerLowValue = 1,;
Top = 25,;
Width = 45
ADD OBJECT (SYS(2015)) AS LABEL WITH;
AutoSize = .T.,;
BackStyle = 0,;
Caption = "請輸入 N 值",;
ForeColor = RGB(255,255,255),;
FontName = "細明體",;
FontSize = 12,;
Left = 15,;
Top = 52
ADD OBJECT spinCircle AS SPINNER WITH;
FontName = "細明體",;
FontSize = 11,;
Format = "RK",;
Height = 23,;
InputMask = "99",;
KeyboardHighValue = 99,;
KeyboardLowValue = 1,;
Left = 130,;
SpinnerHighValue = 99,;
SpinnerLowValue = 1,;
Top = 50,;
Width = 45
ADD OBJECT lblRecL AS LABEL WITH;
AutoSize = .T.,;
BackStyle = 0,;
Caption = "記錄產生中...",;
ForeColor = RGB(255,255,0),;
FontName = "細明體",;
FontSize = 10,;
Visible = .F.,;
Left = 15,;
Top = 75
ADD OBJECT lblRec AS LABEL WITH;
AutoSize = .T.,;
BackStyle = 0,;
Caption = "",;
ForeColor = RGB(255,255,0),;
FontName = "細明體",;
FontSize = 10,;
Visible = .F.,;
Left = 15,;
Top = 95
ADD OBJECT cmdYes AS CommandButton WITH;
Caption = "執行",;
Height = 25,;
Width = 75,;
Left = 15,;
Top = ThisForm.Height-36
ADD OBJECT cmdCancel AS CommandButton WITH;
Caption = "離開",;
Height = 25,;
Width = 75,;
Left = ThisForm.Width-90,;
Top = ThisForm.Height-36
PROCEDURE spinNum.Valid
* One
WITH This.Parent
STORE .spinNum.Value TO UserForm1_nNum
STORE .spinCircle.Value TO UserForm1_nCircle
ENDWITH
* Two
UserForm1_nCircle = MIN(UserForm1_nNum,UserForm1_nCircle)
* Three
WITH This.Parent
.spinCircle.KeyboardHighValue = UserForm1_nNum
.spinCircle.SpinnerHighValue = UserForm1_nNum
.spinCircle.Value = UserForm1_nCircle
ENDWITH
ENDPROC
PROCEDURE cmdYes.Click
* One
WITH This.Parent
STORE .spinNum.Value TO UserForm1_nNum
STORE .spinCircle.Value TO UserForm1_nCircle
ENDWITH
* Two
* > 計算共有幾組以供顯示資訊使用
M_nReccount = 1
FOR UserForm1_SUB_A = UserForm1_nNum-UserForm1_nCircle+1 TO UserForm1_nNum
M_nReccount = M_nReccount * UserForm1_SUB_A
ENDFOR
FOR UserForm1_SUB_A = 1 TO UserForm1_nCircle
M_nReccount = M_nReccount / UserForm1_SUB_A
ENDFOR
* > 顯示記錄產生筆數資訊
WITH This.Parent
.lblRecL.Caption = "記錄產生中... " + TRANSFORM(M_nReccount,M_nTran)
.lblRec.Caption = ""
.lblRecL.Visible = .T.
.lblRec.Visible = .T.
ENDWITH
__Esc = .F.
__IsCalc = .T.
=TT(UserForm1_nNum,UserForm1_nCircle)
__IsCalc = .F.
WITH This.Parent
.lblRec.Caption = PADR(.lblRec.Caption,LEN(M_nTran)) + "(請按任何一個鍵...)"
ENDWITH
WAIT WIND ""
WITH This.Parent
.lblRecL.Visible = .F.
.lblRec.Visible = .F.
ENDWITH
WAIT CLEAR
ENDPROC
PROCEDURE KeyPress
LPARAMETERS nKeyCode, nShiftAltCtrl
DO CASE
* >> ESC
CASE nKeyCode = 27
__Esc = .T.
IF !__IsCalc
.cmdCancel.SetFocus
.cmdCancel.Click
ENDIF
ENDCASE
ENDPROC
PROCEDURE Destroy
ThisForm.Visible = .F.
RELEASE THISFORM
ENDPROC
PROCEDURE cmdCancel.Click
THISFORM.Destroy()
ENDPROC
ENDDEFINE
* ---------- ENDDEFINE CLASS ---------- *
FUNCTION TT
* ---------------------- *
* L_nNum N 要幾個數字
* L_nCircle N 一次抽幾個
* ---------------------- *
PARAMETERS L_nNum,L_nCircle
LOCAL W1_SUB_A,W1_SUB_B
M_nMaxNum = L_nNum
M_nFiledCNT = L_nCircle
* 最後一筆的合計數:避免最後一筆會重覆一次
M_nSumOfLast = 0
FOR W1_SUB_A = M_nMaxNum-M_nFiledCNT+1 TO M_nMaxNum
M_nSumOfLast = M_nSumOfLast + W1_SUB_A
ENDFOR
* 建立暫存表格檔
W1_cCursorString = "CREATE CURSOR TMP_TT ("
FOR W1_SUB_A = 1 TO M_nFiledCNT
W1_cSUB_A = TRANSFORM(W1_SUB_A,"@L 999")
IF !W1_SUB_A = 1
W1_cCursorString = W1_cCursorString + ","
ENDIF
W1_cCursorString = W1_cCursorString + "N" + W1_cSUB_A + " N(3)"
ENDFOR
W1_cCursorString = W1_cCursorString + ")"
SELECT 0
&W1_cCursorString
* 取得排列組合的資料
=CIRCLE(1,L_nCircle,1)
* 顯示資料內容
W1_cFileName = SYS(2015) + ".TXT"
SELECT TMP_TT
LIST OFF NOCONSOLE TO FILE (W1_cFileName)
MODIFY FILE (W1_cFileName) NOEDIT
DELETE FILE (W1_cFileName)
* 關閉暫存表格檔
USE IN TMP_TT
RETURN
FUNCTION CIRCLE
* 遞迴函數
* ------------------------------------ *
* L_nMinNum N 最小數
* L_nChoice N 同一次還剩幾個數可以抽
* L_nWho N 每一次抽的第幾個數
* ------------------------------------ *
PARAMETERS L_nMinNum,L_nChoice,L_nWho
LOCAL W1_nMinNum,W1_nChoice,W1_nWho
LOCAL W1_SUB_A,W1_SUB_B,W1_nSumOfLast
LOCAL W1_nNextMinNum,W1_nNextChoice,W1_nNextWho
W1_nMinNum = L_nMinNum
W1_nChoice = L_nChoice
W1_nWho = L_nWho
* >
IF __Esc
RETURN
ENDIF
IF W1_nChoice = 0
RETURN
ENDIF
IF W1_nWho > M_nFiledCNT
RETURN
ENDIF
* >
IF W1_nWho = 1
SELECT TMP_TT
APPEND BLANK
WW_oMESSAGEBOX.lblRec.Caption = TRANSFORM(RECNO(),M_nTran) + ;
" (按 Esc 鍵中斷)"
ENDIF
* >
FOR W1_SUB_A = W1_nMinNum TO M_nMaxNum-W1_nChoice+1
REPLACE ("N"+TRANSFORM(W1_nWho,"@L 999")) WITH W1_SUB_A
* > 當每一筆的資料填滿時要新增下一筆
IF W1_nWho = M_nFiledCNT
* >> Set Filter:不是最後一筆
W1_nSumOfLast = 0
FOR W1_SUB_B = 1 TO M_nFiledCNT
W1_nSumOfLast = W1_nSumOfLast + EVAL("N"+TRANSFORM(W1_SUB_B,"@L 999"))
ENDFOR
IF W1_nSumOfLast = M_nSumOfLast
LOOP
ENDIF
* >> 新增
SELECT TMP_TT
SCATTER TO W1_aTT
APPEND BLANK
WW_oMESSAGEBOX.lblRec.Caption = TRANSFORM(RECNO(),M_nTran) + ;
" (按 Esc 鍵中斷)"
* >
IF RECNO() > 1 AND W1_nWho > 1
GATHER FROM W1_aTT
ENDIF
ENDIF
* >
IF !__Esc
__Esc = INKEY() = 27
ENDIF
IF __Esc
RETURN
ENDIF
W1_nNextMinNum = W1_SUB_A + 1
W1_nNextChoice = W1_nChoice - 1
W1_nNextWho = W1_nWho + 1
=CIRCLE(W1_nNextMinNum,W1_nNextChoice,W1_nNextWho)
IF __Esc
RETURN
ENDIF
ENDFOR
RETURN _________________ 希望有更多人來參與
VFP wiki - 需要大家一起完成的VFP電子書與FAQ |
|
回頂端 |
|
|
Ruey
註冊時間: 2003-03-12 文章: 1698 來自: tunglo
第 3 樓
|
發表於: 星期六 十月 04, 2003 7:29 pm 文章主題: |
|
|
從未見過有人用VFP寫遞回函數
不固頂可不行喔 _________________ #############################
快樂媽咪系列幸福宅配,喝十全雞湯~原來幸福那麼簡單!!
學會VFP使用者社區的搜尋,Code才會更有趣~
############################# |
|
回頂端 |
|
|
|
|
您 無法 在這個版面發表文章 您 無法 在這個版面回覆文章 您 無法 在這個版面編輯文章 您 無法 在這個版面刪除文章 您 無法 在這個版面進行投票 您 無法 在這個版面附加檔案 您 無法 在這個版面下載檔案
|
|