2012-09-09 42 views
8

對於C#AI程序,我使用遞歸調用來查找最佳下一步移動(使用30x30數組來存儲當前板狀態)。對於我所做的每一個動作,我想看看我可以從新棋盤狀態中做出哪些可能的動作是最好的...等等,直到我達到「遊戲結束」的位置(在這個位置沒有進一步的移動狀態),或者一個計時器停止進程並且不進行進一步的遞歸調用(並且返回「最佳」已知位置)。這只是爲了解釋爲什麼我必須使用遞歸(它不是尾遞歸),我不能使用單個(全局)板狀態,但必須從當前狀態搜索所有可能的板狀態。有沒有辦法在遞歸調用之前檢查可用的堆棧大小? (C#)

(有時)我得到一個System.StackOverflowException。有沒有辦法在下次遞歸調用之前檢查可用堆棧空間?然後,我可以將當​​前狀態作爲「到目前爲止找到的最佳位置」返回,而不進行下一次遞歸調用。即當可用堆棧變得太小時,它也應該算作基本情況。

當然,其他選項可能只是將每個遞歸調用放在try..catch塊中,並通過將它用作基本大小寫來處理System.StackOverflowException?

+5

重新設計你的代碼?一個stackoverflow是一個錯誤或錯誤(C#)代碼的標誌。您需要瘋狂的遞歸調用來觸發一個計算器。如果您真的想這樣做,請使用支持尾巴呼叫的功能語言,如F#。 C#不是爲它設計的。 – Dykam

+0

「如果您正在調用遞歸方法或計劃使用大量堆棧空間,則必須使用RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup方法。」 - (http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.probeforsufficientstack.aspx – DavidO

回答

1

如果你真的想走下去,你可以使用EnsureSufficientExecutionstack方法。

正如其他人指出的,從.NET 2開始。0您不能抓一個StackOverflowException,不過,從MSDN文檔,你知道以前的方法有以下行爲:

確保剩餘的堆棧空間足夠大,可以執行 平均.NET框架的功能。

當堆棧根據這個方法是不是足夠大,那麼它會拋出一個異常InsufficientExecutionStackException能趕上

+0

你試過了嗎? 「確保剩餘的堆棧空間足夠大以執行平均的.NET Framework功能」。在OP的情況下,永遠不可能有足夠的空間 - 這種方法*如何知道*? –

+0

每個遞歸級別都必須重新檢查,否? – DavidO

+0

這部分來自MSDN文檔,我應該爲它添加一個引號,我會更新答案。正如DavidO指出的那樣,該檢查需要在每一步執行才能成爲有效的解決方法。 –

2

實際上,如果系統在現有堆棧上的空間不足,系統將動態擴展堆棧大小。所以,即使你可能測試堆棧的大小,它也無關緊要。

http://msdn.microsoft.com/en-us/library/windows/desktop/ms686774(v=vs.85).aspx細節

的系統提交在需要時從保留堆棧存儲器附加頁面,直到該堆達到保留大小減去一個頁(其被用作保護頁面以防止堆棧溢出)或系統是存儲器如此低,以致操作失敗」

這是說,遞歸發生之前,堆棧一個大小;以及如果所述遞歸導致堆棧溢出,堆棧是一個當發生這種情況時的新尺寸。

既然你不能趕上StackOverflowException,而不是終端遞歸,你可以使用尾遞歸。下面的鏈接提供了關於終端recusion轉換成尾recusion一些良好的細節:http://www.thomaslevesque.com/2011/09/02/tail-recursion-in-c/

+0

「(有時)我得到System.StackOverflowException。」 (可能對此有所解釋。) – DavidO

+0

@DavidO,這並不是說盡管在遞歸進行時增加了堆棧,但內存不足以擴展堆棧。 –

+0

這取決於當前的棋盤位置。如果答案被發現得足夠早(早期發現基本情況),我通常不會得到問題。 –

2

你可以使用一個隊列+環路(Queue<TNode> + while (queue.MoveNext()))代替遞歸和限制隊列的大小。

或者您可以將打開的電話號碼添加到方法中,並以此方式限制遞歸。 (計數條目並退出,如果條目存在> maxOpenCalls,則不要輸入遞歸)。

1

與.NET 2開始,你不能趕上StackOverflowException ...

只有這樣,才能確定已經有多少的籌碼的手段來使用不安全的代碼,我強烈反對......更好的使用明確堆爲基礎的Stack<T>

相關問題