Jianshiji-これはそのような中国のゲーム(名前で判断)、「ピッキングストーン」として翻訳され、それ自体興味深いです。 各プレイヤーは、任意の山から任意の数の石を取り、同時に両方から同じ量を取ります。 最後の石を取る人が勝ちます。 より詳細な説明はこちらです。 バランスを維持するためのゲーム:一方で、ヒープ内の数値が異なる必要があり、その結果、差異が大きくなりすぎないようにします。 そもそもゲームには勝利戦略がありますが、その起源については考慮しません。 簡単な説明をしてください。 次の動きをするプレイヤーが負けるヒープサイズの組み合わせがあります。
角括弧は、部品全体のキャプチャを示します。 いいえ、最初の式はフィボナッチ数ではありませんが、係数は同じですが、ここでは幾何学的ではなく、算術級数です。 ペアの番号の差はnであることに注意してください。
以前のhabrには、TCLのリバーシが64行で、TCLの15行が10行であり、コンパクトで美しいコードがありましたが、ここではそのようなものは表示されません。 また、彼はおそらくマナーからは程遠い。 一般に、govnokodが好きなように思える場合は、おそらくそうです。 一方で、将来的に改善すべき点があるため、さらに良いことです。 言語が私にとって新しいものであるという事実もあり、説明を行うのがより便利になることもあります。 また、オプションのチェックもありません。
次はプログラムの一部です。 最適とはほど遠いですが、言語の機能と動作を示しています。
プログラムの始まりは次のとおりです。
#!/usr/bin/tclsh #--- (+ ab) #--- , , (a + b) namespace path {::tcl::mathop ::tcl::mathfunc} #--- proc lsum L {expr [join $L +]+0} proc random range {expr int(rand()*$range)}
ペアを失うためのコード:
set n_max 20 ;# for {set i 1} {[<= $i $n_max]} {incr i} { set q [/ [+ [sqrt 5] 1 ] 2] ;# " " set a [int [* $q $i]] ;#i- a set b [+ $a $i] ;#ie b lappend lPair1 "$a $b" ;# lPair1 a b }
次のようなリストを表示できます。
puts lPair1; # ; , ,
出力は次のとおりです。
{0 0} {1 2} {3 5} {4 7} {6 10} {8 13} {9 15} {11 18} {12 20} {14 23} {16 26} {17 28} {19 31} {21 34} {22 36} {24 39} {25 41} {27 44} {29 47} {30 49} {32 52}
そのため、個人のコースに応答するために使用するペアのリストがあります;特定のペアを選択する方法を学ぶ必要があります。 新しい状態に移行するには、3つのオプションがあります。
- 1つのヒープの変更:9 5-> 4 5;
- 別のヒープの変更:9 5-> 9 2;
- 両方を一度に変更:9 5-> 6 2。
石だけを取るべきなので、石の合計は動きごとに減少します。
コンピューターの移動コマンドに移りましょう。
#--- : #----st - , #----lAns - #----lPair - , #-------------- proc turn {st lAns lPair} { set st_cur_sum [lsum $st] ;# #--- , 0 0, #--- , if {[== 0 $st_cur_sum]} {return {you win}} set a [lindex $st 0] ;# set b [lindex $st 1] ;# #---lindex - , #--- set c [abs [- $a $b]] #--- , #--- , set a1 [min $a [lindex $lAns $b]] set b1 [min $b [lindex $lAns $a]] set cPair1 [lindex $lPair $c] #--- set a2 [random $a] set b2 [random $b] set c2 [random [+ 1 [min $a $b]]] set cPair2 [list [- $a $c2] [- $b $c2]] set st_next1 [list "$a $b1" [+ $a $b1]] set st_next2 [list "$a1 $b" [+ $a1 $b]] set st_next3 [list "$cPair1" [lsum $cPair1]] #--- set lst_next [list $st_next1 $st_next2 $st_next3] #--- set st_next [lindex [lsort -integer -index 1 $lst_next] 0] set st_next_sum [lindex $st_next 1] if {[== 0 $st_next_sum]} {return {i won}} ;# - , #--- , #--- , - , #--- : , , #--- , if {[> $st_cur_sum $st_next_sum]} { return [lindex $st_next 0] } else { #--- - switch [random 3] { 0 {return "$a $b2"} 1 {return "$a2 $b"} 2 {return "$cPair2"} } } }
lAnsとlPairについての簡単な説明。 勝利のリターンムーブは、上記の3つのオプションのいずれかと一致する必要があります。 さらに、最初の2つは、取得するヒープが異なるだけです。 最初のオプションを考えてみましょう。最初のヒープから取得します。つまり、2番目のヒープは変更されず、その中の石の数によって、最初のヒープのサイズを決定できます。 どれだけ取るかではなく、どれだけ去るか。 lAnsの内容は次のとおりです。
0 2 1 5 7 3 10 4 13 15 6 18 20 8 23 9 26 28 11 31 12 34 36 14 39 41 ...
リスト内のインデックスは、変化しないヒープ内のストーンの数です。このインデックスの値は、ヒープ内の新しいストーンの数であり、そこからストーンを取得します。
lPairの内容は、上記のlPair1の内容と変わりません。 この場合のインデックス値は、インデックスに等しい差を持つ石の新しいペアを表します。
次に、ユーザーとの対話を整理する方法を示します。
puts {Enter heap sizes:} #--- , if {[< 0 [gets stdin state]]} { #--- set n_max [lindex [lsort -integer $state] end] #--- genAnsList $n_max lPair lAns #--- set state [turn $state $lAns $lPair] # puts $state #--- while {[< 0 [gets stdin state]]} { set state [turn $state $lAns $lPair] puts $state } }
コード全体はpastebinで見ることができます。
言語の構文は参照によるものです。
リストの操作は重要です。対応するコマンドはドキュメントにあります 。
PS次のパートでは、もしそうであれば、コメント内の建設的なコメントが考慮されます。