4

この質問と私の別の質問は、いくつかのことを理解した後、1 つに統合されたので、この質問を修正しました。

私が自分の機能で達成しようとしていることは、以下に概説されています。

  1. すべてのスポットを繰り返します。開いている場合は、現在のプレーヤーのシンボルがあるスポットを選択します。
  2. この動きによってゲームに勝利し、コンピューター プレイヤーの番になった場合、スポット (整数) とスポットのスコア (整数、この場合は 1) のキーと値のペアをscored-spotsハッシュ マップに追加します。
  3. この同じ関数を再帰して呼び出し、新しい scored-spotsハッシュマップ、移動したばかりのボード、同じプレーヤー、および同じシンボルを渡します。
  4. ただし、ゲームに勝てなかった場合は、次の条件ステートメントに進み、それを確認します。
  5. 次の条件文も同じように、スコアが異なるだけです (コンピューターのターンでの勝利は 1、人間のターンでの勝利は -1、引き分けは 0)。
  6. どの条件ステートメントも true と評価されない場合は、とにかく再帰します (scored-spotsこの場合、ハッシュ マップに違いはありません)。

これが私が試したコードですが、これは私が期待している値を返しません。

注:
boardは次のようなハッシュ マップです: {0 "0", 1 "1", 2 "2"}(スポット位置 - スポット値)
symは "X" や "O" などの記号、または次
current-playerのようなハッシュ マップです::computer:human
scored-spots{}

(defn score-spots [board sym current-player scored-spots]
  (for [spot (keys board)]
    (if (some #(= % (.toString spot)) (filter #(not= "O" %) (filter #(not= "X" %) (vals board))))
      (let [board (assoc board spot sym)]
        (cond
          (and (game-won board) (= current-player :computer))
            (score-spots board sym current-player (assoc scored-spots spot 1))
          (and (game-won board) (= current-player :human))
            (score-spots board sym current-player (assoc scored-spots spot -1))
          (game-tied board)
            (score-spots board (switch-symbol sym) (switch-player current-player) (assoc scored-spots spot 0))
          :else
            (score-spots board (switch-symbol sym) (switch-player current-player) scored-spots)))
  scored-spots))))

戻り値として期待しているのは、各オープン スポットがスコア付けされたハッシュ マップです。たとえば、{1 0, 4 1, 5 -1, 6 -1, 8 0}.

代わりに、この board: を渡す
{1 "X" 2 "X" 3 "O" 4 "4" 5 "5" 6 "6" 7 "7" 8 "X" 9 "O"}
、多数listのハッシュ マップを含む戻り値が得られます。

4

1 に答える 1

2

私はClojureとFP全般に比較的慣れていません。再帰について考えるときはいつでも、それがmapおよび/またはの機会であるかどうかを最初に考えようとしますreduce

この場合、あなたはスポットを獲得しようとしています。一緒に集められた各スポットはボードです。ですから、各スポットをスコアリングしてまとめることができれば、目の前のタスクを達成することができます。つまりreduce、コレクション内のアイテム(スポット)に対して何かを実行してから、その値を1つの値にマージできます(ボード-技術的には、以下のコードの「X」または「O」のないスポットのみ)。

これが私の書き直しです:

(defn score-spot [scored-spot current-player board]
  (let [[spot score] scored-spot]
    (cond
      (and (game-won board) (= current-player :computer)) {spot 1}
      (and (game-won board) (= current-player :human)) {spot -1} 
      (game-tied board)  {spot 0}
      :else {spot score})))

(defn score-board [board current-player]
  (let [spots-to-score (filter #(and (not= "X" (second %))
                                     (not= "O" (second %))) board)]
    (reduce #(into %1 (score-spot %2 current-player board)) {} spots-to-score)))

これはあなたの結果を与えるでしょう例えば{1 0, 4 1, 5 -1, 6 -1, 8 0}


編集:

再帰の必要性に関しては、基本的に相互再帰を使用したいと考えています。そのためには、declareを使用して宣言関数を転送し、実際の再帰にトランポリンここに簡単なチュートリアルがあります)を使用できます。

于 2012-11-13T18:25:53.920 に答える