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 격자이지만 모든 크기가 될 수 있지만 방금 예를 들어 설명했습니다. 이 과정을 반복하고 싶습니다. 첫 번째 순서는 다음과 같습니다.

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 등입니까? 아니면 24,23,22 등입니까? –

+0

내가 전에 말했듯이 정확한 값은 12,11,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)이고,이 경우 셀 요소를 명시 적으로 계산합니다. 나선형 주위를 한 번 한 번 여행하면 내부적으로 (w-2)*(h-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 오른쪽. 단계 크기는 두 번 반복 될 때마다 바뀝니다.

따라서 현재 "단계 크기"와 현재 방향을 추적하면서 끝까지 도달 할 때까지 N, M을 감소시킬 수 있습니다.

중요 : 동일한 패턴이 적용되는지 확인하려면 비 정방 행렬에 대한 패턴을 적어 두십시오.

+0

미안하지만 나는이 결과를 찾지 못했고, 최종 결과에 도달하는 방법을 알아낼 수 없다는 것을 이미 알고 있었기 때문에 매우 도움이되었습니다. – ngreenwood6

+1

이것은 "what"과 "how"사이의 링크입니다. 코드로 변환 할 수있는 방식으로 패턴을 정의합니다. 누군가 당신을 위해 프로그램을 작성하기를 기대 했습니까? –

+0

이것은 내 것보다 더 콤팩트하고 효율적인 해결책이 될 것이라고 생각합니다.하지만 여러분이 말했듯이 그것은 비 - 정방 행렬에 더 관련 될 수 있습니다. 흥미로운 문제 : – Craig