2011-02-06 4 views
0

私はいくつかのグリッドアイテムをループしていますが、誰かが私が必要なアイテムに到達する方法を見つけるのを助けてくれることを願っていました。おそらく、グリッド。ここにグリッドがあります。javascript grid help

[0] [1] [2] [3] [4] 
[5] [6] [7] [8] [9] 
[10] [11] [12] [13] [14] 
[15] [16] [17] [18] [19] 
[20] [21] [22] [23] [24] 

これは基本的に5x5グリッドですが、どのサイズでも構いませんが、私はこの例で使用しました。私はこれをループしたいと思う2つの方法があります。最初のものは次の順序です:

0,1,2,3,4,9,14,19,24,23,22,21,20,15,10,5,6,7,8,13,18,17,16,11,12 

基本的には、すべて左上から外側に向かっています。私がループしたい次の方法は逆の順序(基本的には外側の代わりに外側にある)を除いて同じ正確な値を通し、実際にこれについて考えています。誰かがこれで私を助けることができるなら、それは素晴らしいだろう。私は本当にこのような狂気の手配でアイテムをループする方法についてもっと学びたいと思っています。

+0

"内側からの出力"とは何ですか?それは0,5,10..etcまたは24,23,22などですか? –

+0

私は前に言ったように、私は逆の順序を除いて1211,16 ...等を除いてリストした正確な値です – ngreenwood6

答えて

1

この機能

function n(i, w, h) 
{ 
    if (i < w) 
     return i; 
    if (i < w + h-1) 
     return w-1 + (i-w+1)*w; 
    if (i < w + h-1 + w-1) 
     return w-1 + (h-1)*w - (i - (w + h-1 - 1)); 
    if (i < w + h-1 + w-1 + h-2) 
     return (h - (i - (w + w-1 + h-1 - 2)))*w; 
    var r = n(i - (w-1)*2 - (h-1)*2, w-2, h-2); 
    var x = r % (w-2); 
    var y = Math.floor(r/(w-2)); 
    return (y+1)*w + (x+1); 
} 

は、入力として受け入れる

  • i:あなたは
  • wを探している項目のインデックス:
  • hグリッドの幅:の高さグリッド

を返し、時計方向のスパイラルトラバーサルを想定してグリッドの対応する要素を返します。

実装では、上辺が(i<w)であるか、下辺右辺が(i<w+h-1)かなどがチェックされます。この場合、セル要素が明示的に計算されます。 スパイラル周りを1回だけ移動すると、内部で(w-2)*(h-2)グリッド内の要素を見つけるために再帰的に呼び出され、元のグリッドサイズを考慮して2つの座標が抽出され、調整されます。

これは、スパイラルウォークの反復とエミュレートだけでなく、グリッドウォークをエミュレートするよりもはるかに高速です。例えば、計算n(123121, 1234, 3012)は即時ですが、グリッド全体には3712808の要素があり、歩数は123121ステップです。

+0

それは素晴らしい作品です。あなたはこれをどのように思いついたかについてもっと詳しく説明できますか?ちょうどこのようなことをしたいと思いますが、私はそのようなロジックを思いつく問題を抱えているようです。 – ngreenwood6

+0

@ ngreenwood6 - 元の問題文からその種のコードに到達する唯一の方法はパターンを観察することです。パターンを手にして、コードに変換できる有限の動作が得られます。あなたが言うように、あなたは「何をすべきか」を知っていますが、それを自動化する必要があります。パターンを口頭で記述することができたら、それを(私の答えのように)書き留めることができ、それをコード化することができます。実装の選択肢があることに注意してください。 @ 6502は再帰を使用することを選択しました。これは良い選択です。 –

0

ここでは「ウォーキング」方法を示します。効率は低下しますが、機能します。

var arr = new Array(); 
for(var n=0; n<25; n++) arr.push(n); 

var coords = new Array(); 

var x = 0; 
var y = 0; 
for(var i=0; i<arr.length; i++) { 
    if(x > 4) { 
      x = 0; 
      y++; 
    } 

    coords[i] = {'x': x, 'y': y}; 

    x++; 
} 

// okay, coords contain the coordinates of each item in arr 

// need to move along the perimeter until a collision, then turn. 

// start at 0,0 and move east. 

var dir = 0; // 0=east, 1=south, 2=west, 3=north. 
var curPos = {'x': 0, 'y': 0}; 
var resultList = new Array(); 

for(var x=0; x<arr.length; x++) { 
    // record the current position in results 
    var resultIndex = indexOfCoords(curPos, coords); 

    if(resultIndex > -1) { 
     resultList[x] = arr[resultIndex]; 
    } 
    else { 
     resultList[x] = null; 
    } 

    // move the cursor to a valid position 
    var tempCurPos = movePos(curPos, dir); 

    var outOfBounds = isOutOfBounds(tempCurPos, coords); 
    var itemAtTempPos = arr[indexOfCoords(tempCurPos, coords)]; 
    var posInList = resultList.indexOf(itemAtTempPos); 

    if(outOfBounds || posInList > -1) { 
      dir++; 
      if(dir > 3) dir=0; 
      curPos = movePos(curPos, dir); 
    } 
    else { 
      curPos = tempCurPos; 
    } 
} 


/* int indexOfCoords 
* 
* Searches coordList for a match to myCoords. If none is found, returns -1; 
*/ 
function indexOfCoords(myCoords, coordsList) { 
    for(var i=0; i<coordsList.length; i++) { 
     if(myCoords.x == coordsList[i].x && myCoords.y == coordsList[i].y) return i; 
    } 
    return -1; 
} 

/* obj movePos 
* 
* Alters currentPosition by incrementing it 1 in the direction provided. 
* Valid directions are 0=east, 1=south, 2=west, 3=north 
* Returns the resulting coords as an object with x, y. 
*/ 
function movePos(currentPosition, direction) { 
    var newPosition = {'x':currentPosition.x, 'y':currentPosition.y}; 
    if(direction == 0) { 
     newPosition.x++; 
    } 
    else if(direction == 1) { 
     newPosition.y++; 
    } 
    else if(direction == 2) { 
     newPosition.x--; 
    } 
    else if(direction == 3) { 
     newPosition.y--; 
    } 

    return newPosition; 
} 

/* bool isOutOfBounds 
* 
* Compares the x and y coords of a given position to the min/max coords in coordList. 
* Returns true if the provided position is outside the boundaries of coordsList. 
* 
* NOTE: This is just one, lazy way of doing this. There are others. 
*/ 
function isOutOfBounds(position, coordsList) { 
    // get min/max 
    var minx=0, miny=0, maxx=0, maxy=0; 
    for(var i=0; i<coordsList.length; i++) { 
     if(coordsList[i].x > maxx) maxx = coordsList[i].x; 
     else if(coordsList[i].x < minx) minx = coordsList[i].x; 

     if(coordsList[i].y > maxy) maxy = coordsList[i].y; 
     else if(coordsList[i].y < miny) miny = coordsList[i].y; 
    } 

    if(position.x < minx || position.x > maxx || position.y < miny || position.y > maxy) return true; 
    else return false; 
} 

既に結果アレイ内の境界又は項目に当たるまで、これは方向のグリッドを介して移動し、その後、時計回りに回します。それはかなり初歩的ですが、私はそれが仕事をすると思います。あなたはそれをかなり単純に逆にすることができます。

はここで働い例です:http://www.imakewidgets.com/test/walkmatrix.html

+0

私はこれをテストしませんでしたが、私の問題にあなたの解決策を追加してくれてありがとう、機能が欠落している)。 – ngreenwood6

+0

欠落している機能は簡単に書くことができますが、通常のコンピュータを使用しているときに追加することがあります。難しい部分はコンセプトです、私はそれをカバーしています。 – Craig

+0

すべてを含めるようにコードを変更しました。実際のリンク例も提供されています。 – Craig

0

あなただけのトラバーサルパターンを表現する方法が必要です。

(例えば5×5)N×M個の行列が与えられると、パターンは、これは右に5を移動言う

GENERAL  5x5 
-------  ------- 
N right  5 
M-1 down  4 
N-1 left  4 
M-2 up   3 
N-2 right  3 
M-3 down  2 
N-3 left  2 
M-4 up   1 
N-4 right  1 

あり、図4は、ダウン、4左、3まで、3右、2ダウン、2左側、1アップ、1右。ステップサイズは、各2回反復後にシフトする。

したがって、現在の「ステップサイズ」と現在の方向を追跡し、最後に到達するまでN、Mを減らすことができます。

重要:同じパターンが適用されるかどうかを確認するには、非正方行列のパターンを必ず書き留めてください。

+0

申し訳ありませんが、私はすでに最終結果に到達する方法を理解できなかった何が必要なのかを知っていたので、この回答は非常に役に立ちませんでした。 – ngreenwood6

+1

これは "what"と "how"のリンクです。パターンに変換してコードに変換することができます。誰かがあなたのプログラムを書くことを期待していましたか? –

+0

これは、私よりもコンパクトで効率的な解決策に終わるだろうと思いますが、あなたが言うように、非正方行列の方が関与している可能性があります。興味深い問題: – Craig