これは、簡単な試行錯誤のアルゴリズムで解決できます。上から下への要件は、配列の一番上の行から開始する必要があることがわかっているので便利です。そのため、その1つの行でtrue
開始する値を検索するだけです。
を見つけたらtrue
、隣接するセルを確認します。(正確に隣接するセルは、対角線がカウントされるかどうか、およびパスがシンクの下のトラップパイプのように上向きに曲がることができるかどうかによって異なります。)
(ウィキペディアからの画像)
を含む別のセルを見つけた場合true
、そのセルが「現在の」セルになり、その隣接セルを調べます。true
最後の行のセルに到達するまでこれを続けます。または、隣接セルが見つからない場合はtrue
、前のセルに戻って隣接セルを続行します。
これを行う1つの方法は、再帰とごくわずかなコードを使用します。次のようなことをするだけです
// pseudocode only
for(Cell foo : all cells in top row)
checkCell(foo);
boolean checkCell(Cell current) {
if(current == false)
return false;
if(current == true && current.isInLastRow == true)
return true;
// if we reach here, the cell is true but we're not done
for(Cell foo : all valid neighbors of this cell except the "parent")
return checkCell(foo);
}
別の方法はより多くのメモリを使用しますが、より効率的です。元の配列と同じサイズの2番目の配列を作成します。元の配列からセルをテストするときは、新しい配列で対応するセルにマークを付けます。次に、ネイバーをテストするときに、新しいアレイをチェックして、特定のネイバーにすでにアクセスしたことがあるかどうかを確認します。持っている場合は、それをスキップしてください。成功につながることはありません(可能であれば、すでに完了して戻ってきているので、これを知っています)。true
これにより、配列に次のように多数の値が隣り合って含まれている場合に、時間を大幅に節約できます。
F T T T F
F T T T F
F T T T F
F T T T F
F T T T F
編集:
パス内のセルの座標を記録する必要があるという更新コメントを見逃しました。問題ありません。これまでに行ったことを記録するオブジェクトのスタックを作成するだけです。間違った道をたどってしまった場合は、「レベルを上げる」たびにスタックから1回ポップするだけです。Point