2013-08-26 6 views
1

현재 주변의 모든 셀에있는 데이터에 대해 표 셀을 검사하려고합니다. 위, 아래, 오른쪽, 모든 대각선. 예외 던지기를 사용하면 어떻게면과 모서리를 개별적으로 코딩 할 필요가 없습니까?바운드 예외 예외 발생

이것은 현재 가지고있는 내용입니다. isIsAlive()는 단순히 셀이 "활성"인지 확인합니다. 셀의 이웃은 그 주변의 모든 활성 셀을 포함합니다.

public void calcNeighbors() throws ArrayIndexOutOfBoundsException{ 

    int x =0; 

    int y =0; 
    int neighbors = 0; 



    while(x < 9){ 
     while(y < 9){ 

      if(generation[x+1][y+1].isIsAlive()){ 
       neighbors++; 

      } 
      if(generation[x+1][y].isIsAlive()){ 
       neighbors++; 
      } 
       if(generation[x+1][y-1].isIsAlive()){ 
       neighbors++; 
      } 
       if(generation[x][y-1].isIsAlive()){ 
       neighbors++; 
      } 
       if(generation[x-1][y-1].isIsAlive()){ 
       neighbors++; 
      } 
       if(generation[x-1][y].isIsAlive()){ 
       neighbors++; 
      } 
       if(generation[x-1][y+1].isIsAlive()){ 
       neighbors++; 
      } 
       if(generation[x][y+1].isIsAlive()){ 
       neighbors++; 
      } 
      y++; 
     } 
     x++; 
     neighbors = 0; 
    } 
} 
+3

대답은 다음과 같습니다. 예외적이지 않은 제어 흐름에 대해 예외를 사용하지 마십시오. –

+0

이것은 expections 질문을 통해 비슷한 코드 흐름입니다 : http : // stackoverflow.com/questions/16320014/java-optimization-nitpick-it-faster-to-cast-something-and-let-it-throw-excep/16320082 # 16320082 일반적인 가독성 문제 외에도 다음과 같은 몇 가지 테스트를 수행했습니다. 능률. 그것은 끔찍한 독서를 만듭니다. "너무 오래 읽지 못했습니다"예외는 instanceof보다 20 배 느립니다 (자체적으로 느림) –

+0

일반적 조언; "9"를 사용하는 것은 마법의 숫자입니다; **나쁜**. 배열 크기가 변경되면 array.length를 사용합니다. array [0] .length를 사용하여 두 번째 차원을 얻을 수 있습니다. –

답변

3

가설적인 이웃이 범위를 벗어나는 경우에는 예외를 던져서는 안됩니다. 자바는 어쨌든 ArrayIndexOutOfBoundsException을 던집니다.

배열에 액세스하기 전에 경계를 확인해야합니다. x 또는 y이 범위를 벗어난 경우 어레이에 액세스하지 마십시오.

+0

+1 또한 "범위를 벗어남"을 체크 할 때 코드에서 마술 숫자를 사용하지 말라. '9'), 실제 배열 길이를 사용하십시오. (* 비록 매우 거대한 N/NE/E/SE/S/SW/W/NW 그리드에 있어도 9 명이 될 수 있습니다 - 기다리지 마십 시요, 8 이웃입니까?) –

+0

그래서 제가 할 수 있습니다. 말하자면 ... 오류가 발생하면 버리고, 아무것도하지 못하게하라. 또한 10x10 격자입니다. 이것이 배열이 9 인 이유입니다. – Xenorosth

+0

@ Xenorosth : 너 can *, 너는 * 할 수 없어. 예외는 예외적 인 * 조건을위한 것이며, 던지는 것은 무료가 아닙니다. –

4

블록 추한 경우 귀하의 목록 (무뚝뚝하기) 위험. 대신 중첩 된 for 루프를 사용하지만 for 루프의 상한 및 하한을 계산하여 가장자리를 고려하십시오.

for (int x = 0; x < MAX_X; x++) { 
    for (int y = 0; y < MAX_Y; y++) { 

    int minRow = Math.max(0, x - 1); 
    int maxRow = Math.min(MAX_X - 1, x + 1); 
    int minCol = Math.max(0, y - 1); 
    int maxCol = Math.min(MAX_Y - 1, y + 1); 

    for (int row = minRow; row <= maxRow; row++) { 
     for (int col = minCol; col <= maxCol; col++) { 
     if (row != x || col != y) { 
      if(generation[row][col].isIsAlive()){ 
      neighbors[x, y]++; 
      } 
     } 
     } 
    } 
    } 
} 
+0

@TJCrowder : 근본적인 문제는 Java가 그 이후로 어려운 일을하지 않도록합니다. 그가 사용해야하는 모든 것은 그가 한계를 넘지 않는다는 것을 테스트하는 가장 기본적인 논리입니다. 위의 예제에서 위의 for 루프는 for ** while ** 루프가 아닌 ** inner ** two for 루프입니다. –

+0

네,하지만 내가 언급했을 때 그 루프는 없었습니다. 다시 편집 : 두 번 계산하지 않습니까? –

+0

@ T.J.Crowder : 아니, 나는 그렇게 생각하지 않는다. 나는 삶의 게임의 게임과 나의 지뢰 찾기 프로그램과 함께 이런 종류의 코드를 사용했다. –

1

이 용도로 예외를 사용하지 않는 것이 좋습니다. 그러나 당신이 주장한다면, 당신은 다음과 같은 방법으로 그것을 할 수 있습니다. 첫째, 방법을

public boolean isAlive(int x,int y) { 
    try { 
     return this.generation[x][y].isIsAlive() ; 
    } catch(IndexOutOfBoundsException ex) { 
     return false ; // Or whatever you want to be the default 
    } 
} 

을 정의 그리고 등등 isAlive(x+1,y+1) 대신 generation[x+1][y+1].isIsAlive() 등을 사용합니다.

또한 로컬 변수 int neighbors = 0;을 잘못 선언 한 것 같습니다. 마지막에 0으로 설정하고 있기 때문에 이것을 말하고 있지만 어디에도 저장하지 않습니다. 개인적으로, 나는 generation의 기본 클래스 무엇이든의 필드 neighbors을 정의하고 다음과 같습니다 많은 if들과

for(int x= 0 ; x < generation.length ; x++) { 
    for(int y= 0 ; y < generation[x].length ; y++) { 
     generation[x][y].neighbors= 0 ; 
     for(int dx= -1 ; dx <= 1 ; dx++) { 
      for(int dy= -1 ; dy <= 1 ; dy++) { 
       if(! (dx == 0 && dy == 0) && isAlive(x+dx,y+dx)) { 
        generation[x][y].neighbors++; 
       } 
     } 
    } 
} 

내 관심사는 3이다 : 1. 실수를하는 것은 매우 쉽습니다. 2. if 안에 다른 코드를 추가하는 데 시간이 오래 걸리고 오류가 발생하기 쉽습니다. 3. 논리를 이해하기 쉽습니다. 이웃을 확인하겠다고 설명하는 주석을 추가 할 수도 있지만 인접 셀은 모두 8 개의 셀로 구성되어 있습니다. 행 또는 열은 현재 셀의 +1 또는 -1입니다.

또한

, 지금 우리는 if의 수를 줄일 것을, 우리는 또한 위의 함수를 인라인 수있는 다음과 같은 쓰기 : 가장 지금까지 어떤 ( 남용 예외없이 지금

for(int x= 0 ; x < generation.length ; x++) { 
    for(int y= 0 ; y < generation[x].length ; y++) { 
     generation[x][y].neighbors= 0 ; 
     for(int dx= -1 ; dx <= 1 ; dx++) { 
      for(int dy= -1 ; dy <= 1 ; dy++) { 
       try { 
        if(! (dx == 0 && dy == 0) && isAlive(x+dx,y+dx)) { 
         generation[x][y].neighbors++; 
        } 
       } catch(IndexOutOfBoundsException ex) { 
        // Do whatever you want in this case 
       } 
      } 
     } 
    } 
} 

, 을 권장), I는 함수

public boolean isValidNeighbor(int i,int j) { 
    return 0 <= i && i < generation.length && 0 <= j && j < generation[i].length ; 
} 

를 추가 말할 것입니다 그리고 당신의 코드가된다 :

for(int x= 0 ; x < generation.length ; x++) { 
    for(int y= 0 ; y < generation[x].length ; y++) { 
     generation[x][y].neighbors= 0 ; 
     for(int dx= -1 ; dx <= 1 ; dx++) { 
      for(int dy= -1 ; dy <= 1 ; dy++) { 
       if(! (dx == 0 && dy == 0) && isValidNeighbor(x+dx,y+dx) && isAlive(x+dx,y+dx)) { 
        generation[x][y].neighbors++; 
       } 
      } 
     } 
    } 
} 

훨씬 더 좋습니다. 그리고, 주된 이유가 아닐지라도, 예외가있는 것보다 적은 코드와 복잡성 !!!