使用遞迴的問題 |
答題得分者是:TheMoon
|
YTAI
一般會員 發表:2 回覆:1 積分:0 註冊:2004-09-15 發送簡訊給我 |
請問大家:我參考站上的文章後,寫的程式碼如下
void __fastcall TForm1::RzBitBtn4Click(TObject *Sender) { Image2->Picture = NULL; Memo1->Clear(); Byte *ptr = NULL; Graphics::TBitmap *PIC = new Graphics::TBitmap(); PIC->Assign(Image1->Picture); PIC->PixelFormat = pf24bit; Image2->Canvas->Brush->Style = bsClear; Image2->Canvas->Pen->Color = clAqua; for (int y=1; yHeight-1; y++) { ptr = (Byte*)PIC->ScanLine[y]; for (int x=1; xWidth-1; x++) { if (ptr[x*3] == 255) { CCL(PIC, x, y); } } } delete PIC; } void __fastcall TForm1::CCL(Graphics::TBitmap *BMP, int x, int y) { SetPixel(BMP->Canvas->Handle, x, y, clBlack); Image2->Canvas->Pixels[x][y] = clBlue; Memo1->Lines->Add("X:"+IntToStr(x)+" Y: "+IntToStr(y)); Application->ProcessMessages(); if (BMP->Canvas->Pixels[x+1][y]==clWhite) CCL(BMP, x+1, y); if (BMP->Canvas->Pixels[x][y+1]==clWhite) CCL(BMP, x, y+1); if (BMP->Canvas->Pixels[x-1][y]==clWhite) CCL(BMP, x-1, y); if (BMP->Canvas->Pixels[x][y-1]==clWhite) CCL(BMP, x, y-1); }測試圖片如下所示 小弟不懂地方是如下的數據 X:41 Y: 40 X:42 Y: 40 X:43 Y: 40 X:44 Y: 40 X:45 Y: 40 X:46 Y: 40 X:47 Y: 40 X:39 Y: 41 <---為什麼能跳到這個位置? X:39 Y: 42 X:39 Y: 43 ....希望前輩能幫我解惑 |
TheMoon
中階會員 發表:17 回覆:95 積分:67 註冊:2002-06-05 發送簡訊給我 |
給個建議,
請善用Add Watch和設定中斷點來trace程式,
如此便能清楚地知道遞迴是如何呼叫和展開的,
底下的說明希望你能瞭解。
< class="code">
void __fastcall TForm1::RzBitBtn4Click(TObject *Sender)
{
Image2->Picture = NULL;
Memo1->Clear();
Byte *ptr = NULL;
Graphics::TBitmap *PIC = new Graphics::TBitmap();
PIC->Assign(Image1->Picture);
PIC->PixelFormat = pf24bit;
Image2->Canvas->Brush->Style = bsClear;
Image2->Canvas->Pen->Color = clAqua;
for (int y=1; yHeight-1; y )
{
ptr = (Byte*)PIC->ScanLine[y]; //這裡的用意是在搜尋第一個白點
for (int x=1; xWidth-1; x )
{
if (ptr[x*3] == 255)
{
CCL(PIC, x, y); //當x=27 y=40時,開始呼叫CCL function
}
}
}
delete PIC;
} //整段程式碼的重點是在CCL這個function,裡面有用到遞迴呼叫。
void __fastcall TForm1::CCL(Graphics::TBitmap *BMP, int x, int y)
{
//在原圖上將白點設為黑點,表示此點已經走過
SetPixel(BMP->Canvas->Handle, x, y, clBlack); //在Image2上對應的位置塗上藍點
Image2->Canvas->Pixels[x][y] = clBlue; //在Memo1秀出(X,Y)位置
Memo1->Lines->Add("X:" IntToStr(x) " Y: " IntToStr(y));
Application->ProcessMessages(); //下面是遞迴呼叫程式的判斷條件
//當遇到白點就呼叫CCL function
//要注意呼叫CCL function的程式碼位置及x,y的值
//因為程式呼叫展開到某一層執行完畢後會再跳回上一層的進入位置
if (BMP->Canvas->Pixels[x 1][y]==clWhite) //向右走
CCL(BMP, x 1, y); //x=27 1 y=40, 呼叫CCL function //因為當x=27..46 y=40時,向右一直都有白點,
//所以都會執行到上面這個if判斷式裡的CCL,直到x=47 y=40。 //當x=47 y=40時,發現向下,向左,向上都是黑點,於是CCL function執行完畢,
//跳回上一層x=46 y=40時的程式執行位置,並繼續執行以下的程式。
//因為一直碰到黑點,所以會一直跳回上一層呼叫處,直到x=39 y=40。 if (BMP->Canvas->Pixels[x][y 1]==clWhite) //向下走
CCL(BMP, x, y 1); if (BMP->Canvas->Pixels[x-1][y]==clWhite) //向左走
CCL(BMP, x-1, y); if (BMP->Canvas->Pixels[x][y-1]==clWhite) //向上走
CCL(BMP, x, y-1);
}
|
YTAI
一般會員 發表:2 回覆:1 積分:0 註冊:2004-09-15 發送簡訊給我 |
|
TheMoon
中階會員 發表:17 回覆:95 積分:67 註冊:2002-06-05 發送簡訊給我 |
引言: 謝謝TheMoon前輩的指導,我了解了 原來關鍵字在這一句引言: 因為程式呼叫展開到某一層執行完畢後會再跳回上一層的進入位置 所以會一直跳回上一層呼叫處,直到x=39 y=40。還有小一個地方想請教TheMoon前輩,您說[Add Watch]指的是? 因為後來我是用View→Debug Windows→Call Stack才看出程式流程的 再次感謝TheMoon >>< face="Verdana, Arial, Helvetica"> 是在Run→Add Watch裡, 點選後會出現Watch List視窗, 你可以設定想要觀察的變數或物件 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |