2017-06-29 1 views
1

解決策が達成されるまで再帰的にprocを呼び出すスクリプトを作成しました。問題は私の願いの窓が応答しなくなっていることです。私がロギングのために追加したputsステートメントは表示されません。私は計算でスクリプトが忙しいのですが、なぜputsが標準出力に出力されないのでしょうか?TCL:長い再帰的計算中にタイムアウト/応答のないウィンドウを避ける

このような長い再帰的なプロシージャコールの間、スクリプト/ウィッシュウィンドウを生かし続ける方法。これは完全なスクリプトです。

namespace eval chainReactionGlobal { 
    #variable state [list 0 0 0 0 0 0 0 0 0] 
    variable pos  [list 0 1 2 3 4 5 6 7 8] 
    variable posMax [list 1 2 1 2 3 2 1 2 1] 
    variable burstPos [list {1 3} {0 2 4} {1 5} {0 4 6} {1 3 5 7} {2 4 8} {3 7} {4 6 8} {5 7}] 
    variable players [list A B C] 
    variable boxLen 3 
    variable boxWidth 3 
} 

proc ShowGraphicalState {state} { 
    set length $chainReactionGlobal::boxLen 
    set width $chainReactionGlobal::boxWidth 
    puts "\n" 
    puts "--------------------" 
    puts -nonewline "\| [lindex $state 0][string repeat " " [expr 4-[string length [lindex $state 0]]]]\|" 
    puts -nonewline "\| [lindex $state 1][string repeat " " [expr 4-[string length [lindex $state 1]]]]\|" 
    puts -nonewline "\| [lindex $state 2][string repeat " " [expr 4-[string length [lindex $state 2]]]]\|" 
    puts "\n--------------------" 
    puts -nonewline "\| [lindex $state 3][string repeat " " [expr 4-[string length [lindex $state 3]]]]\|" 
    puts -nonewline "\| [lindex $state 4][string repeat " " [expr 4-[string length [lindex $state 4]]]]\|" 
    puts -nonewline "\| [lindex $state 5][string repeat " " [expr 4-[string length [lindex $state 5]]]]\|" 
    puts "\n--------------------" 
    puts -nonewline "\| [lindex $state 6][string repeat " " [expr 4-[string length [lindex $state 6]]]]\|" 
    puts -nonewline "\| [lindex $state 7][string repeat " " [expr 4-[string length [lindex $state 7]]]]\|" 
    puts -nonewline "\| [lindex $state 8][string repeat " " [expr 4-[string length [lindex $state 8]]]]\|" 
    puts "\n--------------------" 
} 

proc GetNextPlayer {currentPlayer} { 
    set currIdx [lsearch $chainReactionGlobal::players $currentPlayer] 
    if {[expr $currIdx+1]<[llength $chainReactionGlobal::players ]} { 
     return [lindex $chainReactionGlobal::players [expr $currIdx+1]] 
    } else { 
     return [lindex $chainReactionGlobal::players 0] 
    }  
} 

# ------------------------------------------------------------------------ 
# This function will take input of a stable state and current player, will 
# return list of possible unstable state the current player can make. 
# ------------------------------------------------------------------------ 
proc GetPossibleStateMatrix {stableState currentPlayer} { 
    array set stateList {} 

    foreach position $chainReactionGlobal::pos { 

     set localState $stableState 
     set currentPosValue [lindex $localState $position] 
     if {$currentPosValue=="0"} { 
      lset localState $position [string repeat $currentPlayer 1] 
     set stateList($position) $localState 
     } elseif {[regexp -all $currentPlayer $currentPosValue]>0} { 
      lset localState $position $currentPosValue$currentPlayer 
      set stateList($position) $localState 
     } 


    } 

    return [array get stateList] 
} 



proc GetStabilizedState {unstableState impactPosList} { 
    set isStable 0 
    set affectedPosList {} 
    while {!$isStable} { 
     foreach position $impactPosList { 
      set posValue [lindex $unstableState $position] 
      if { $posValue=="0"} { 
        set posLength 0 
      } else { 
       set posLength [string length $posValue] 
      } 
      set posMaxLength [lindex $chainReactionGlobal::posMax $position] 

      if {($posLength>$posMaxLength)} { 
       if {[expr $posLength-$posMaxLength-1] > 0} { 
        lset unstableState $position [string repeat [string range $posValue 0 0] [expr [expr $posLength-$posMaxLength]-1]] 
       } else { 
        lset unstableState $position "0" 
       } 

       foreach affectedPos [lindex $chainReactionGlobal::burstPos $position] { 
        set affectedPosValue [lindex $unstableState $affectedPos] 
        if { $affectedPosValue =="0"} { 
         set affectedPosValueLength 0 
        } else { 
         set affectedPosValueLength [string length $affectedPosValue] 
        } 
        set affectedPosMaxLength [lindex $chainReactionGlobal::posMax $affectedPos] 

        if {[expr $affectedPosValueLength+1]>$affectedPosMaxLength } { 
         if {[lsearch $affectedPosList $affectedPos ] ==-1} { 
          lappend affectedPosList $affectedPos 
         } 
        } 
        lset unstableState $affectedPos [string repeat [string range $posValue 0 0] [expr 1+$affectedPosValueLength]]  
       } 
      } 
     } 

     set isStable 1 
     foreach position $chainReactionGlobal::pos { 
      set posValue [lindex $unstableState $position] 
     if { $posValue=="0"} { 
       set posLength 0 
     } else { 
      set posLength [string length $posValue] 
     } 
     set posMaxLength [lindex $chainReactionGlobal::posMax $position] 
      if {($posLength>$posMaxLength) && ($posValue!="0")} { 
       set isStable 0 
      } 
     } 

     if {$isStable==1} { 
      return $unstableState 
     } 
     set impactPosList $affectedPosList 
    } 

} 


proc IsImmediateWin {state currentPlayer} { 
    foreach elem $state { 
     if {$elem==0} { 
      continue 
     } elseif {[regexp $currentPlayer $elem]} { 
      continue 
     } else { 
      return 0 
     } 
    } 
    return 1 
} 

    proc GetWinRatio {state myPlayer currentPlayer {test 0}} { 

     puts "test $test state $state myPlayer $myPlayer currentPlayer $currentPlayer" 

     set loss 0 
     set win 0 
     set possibleStateList [GetPossibleStateMatrix $state $currentPlayer] 
     array set possibleStateArr $possibleStateList 
     # puts possibleStateList$possibleStateList 
     foreach possiblePos [lsort [array names possibleStateArr]] { 
      set possibleState $possibleStateArr($possiblePos) 
      puts "possibleState ----> $possibleState       possiblePos $possiblePos" 
      set stableState [GetStabilizedState $possibleState $possiblePos] 
      puts "stableState ----> $stableState" 


      if {[IsImmediateWin $stableState $currentPlayer]} { 
       if {$currentPlayer==$myPlayer } { 
        incr win 
       } else { 
        incr loss 
       } 
      } else { 
      puts "not immediate win" 

       set result [GetWinRatio $stableState $myPlayer [GetNextPlayer $currentPlayer] [expr $test+1] ] 
       # set result "0:0" 
       set winRes [lindex [split $result ":"] 0] 
       set lossRes [lindex [split $result ":"] 1] 

       incr win $winRes 
       incr loss $lossRes 
      } 
      # puts "state [ShowGraphicalState $stableState] wins:$win loss:$loss" 

     } 
     return ${win}:${loss} 
    } 
    puts "[GetWinRatio [list A CC A A B B A B C] A A]"  
+0

これを実行しているプラ​​ットフォームはどれですか? –

+0

私はWindows 7で実行されているWish86.exeでスクリプトを実行しました。 –

答えて

1

あなたはTkコマンドupdateまたはupdate idletasksを必要とする理由です願いを、使用しています。コンソールでtclshを使用しているときは、このコマンドは必要ありません。

関数GetPossibleStateMatrixが存在しないため、コードをテストできません。 だから、私はこのようなコードをテストしてみた:

for {set i 0} {$i < 10000} {incr i} {puts $i} 

はい、何も出力は実行の終了まではありません。だから、私はupdateコマンドを追加しました:

for {set i 0} {$i < 10000} {incr i} {puts $i; update} 

そして今、私は、実行の過程で出力を見ることができます。

はあなたの最初のputsupdateコマンドを追加してください:

proc GetWinRatio {state myPlayer currentPlayer {test 0}} { 

    puts "test $test state $state myPlayer $myPlayer currentPlayer $currentPlayer" 
    update 
    . . . 
+0

完全なコードを追加しました。どうぞご覧ください –

+1

@Codename_DJそれぞれの 'puts'の後に' update'コマンドを追加してコードを実行しました。これは、迅速に示された: 試験3状態CC 0 AA CCC C A CC C myPlayer A currentPlayer A possibleState ----> AAのCC 0 AA CCC C A CC C possiblePos それが応答立ち止まりました。 'GetStabilizedState'関数の問題のようです。 –

+0

今回私は間違った場所を見ていました。更新についてのヒントをありがとう。 –

1

のWindows Tkのコンソールが実際にメインスレッドで別のインタプリタコンテキストで実行されています。独自のTkウィンドウ階層を持ちますが、Tclコードとのプライマリイベントループを共有します。残念ながら、これは、メインインタプリタで実行中のTclコードを非常にビジー状態にすると(例えば、多くの処理を行うことによって)、コンソールに表示更新を処理しなくなることを意味します。テキストはウィンドウモデルにありますが、実際の表示更新として処理する実際のコードは、アイドルイベントでスケジュールされたコールバックにあります。

修正プログラムは、updateまたはupdate idletasksのいずれかをメイン処理ループのどこかに配置することです。後者はputsコールからの表示更新を処理するのに十分ですが、前者はウィンドウとやりとりすることもできます(スクロールなど)。欠点は、メインウィンドウで他のイベントを処理できることです。長い処理が行われている間にユーザーをロックするために、ユーザーとして注意するか、GUIを更新する必要があります。それにはさまざまな方法がありますが、それがあなた自身のためだけのものであれば、「ちょっと注意してください」アプローチはうまくいきます。

関連する問題