VFP 愛用者社區 首頁 VFP 愛用者社區
本討論區為 Visual Foxpro 愛用者經驗交流的地方, 請多多利用"搜尋"的功能, 先查看看有無前例可循, 如果還有不懂的再發問. 部份主題有附加檔案, 須先註冊成為社區居民才可以下載.
 
 常見問題常見問題   搜尋搜尋   會員列表會員列表   會員群組會員群組   會員註冊會員註冊 
 個人資料個人資料   登入檢查您的私人訊息登入檢查您的私人訊息   登入登入

遞迴函數的應用範例

 
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區
上一篇主題 :: 下一篇主題  
發表人 內容
朱育興



註冊時間: 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
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件 MSN Messenger
朱育興



註冊時間: 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
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件 MSN Messenger
Ruey



註冊時間: 2003-03-12
文章: 1698
來自: tunglo

第 3 樓

發表發表於: 星期六 十月 04, 2003 7:29 pm    文章主題: 引言回覆

從未見過有人用VFP寫遞回函數
不固頂可不行喔

_________________
#############################
快樂媽咪系列幸福宅配,喝十全雞湯~原來幸福那麼簡單!!

學會VFP使用者社區的搜尋,Code才會更有趣~
#############################
回頂端
檢視會員個人資料 發送私人訊息
從之前的文章開始顯示:   
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區 所有的時間均為 台北時間 (GMT + 8 小時)
1頁(共1頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
無法 在這個版面附加檔案
無法 在這個版面下載檔案


Powered by phpBB © 2001, 2005 phpBB Group
正體中文語系由 phpbb-tw 維護製作