2010-01-13 3 views
1

J'ai un tableau (de 9 éléments, disons) que je dois traiter comme un carré (3 par 3). Pour simplifier la question, il s'agit d'un tableau à base unique (c'est-à-dire que l'indexation commence à 1 au lieu de 0).Détermination de cellules adjacentes valides d'un carré stocké sous forme de tableau

Mon but est de déterminer les carrés adjacents valides par rapport à un point de départ.

En d'autres termes, comment il est stocké dans la mémoire: 1 2 3 4 5 6 7 8 9

Comment je traiter:
7 8 9
4 5 6
1 2 3

Je sais déjà comment déplacer vers le haut et vers le bas et le test pour sortir des limites (1> = current_index < = 9)

edit: Je sais que le test ci-dessus est trop général mais c'est simple et ça marche. Comment puis-je tester pour une condition hors limites lorsque je vais à gauche ou à droite? Conceptuellement je sais que cela implique de déterminer si 3 (par exemple) est sur la même rangée que 4 (ou si 10 est même dans le même carré que 9, comme un autre exemple, étant donné que plusieurs carrés sont dans le même tableau dos à dos) , mais je ne peux pas comprendre comment le déterminer. J'imagine qu'il y a un modulo quelque part, mais où?

Merci beaucoup,
Geoff

Additif:
Voici le code résultant, modifié pour être utilisé avec un réseau de base zéro (I nettoyé le présent code de décalage dans le projet) qui marche adjacente carrés.

bool IsSameSquare(int index0, int index1, int square_size) { 
    //Assert for square_size != 0 here 
    return (!((index0 < 0) || (index1 < 0)) 
     && ((index0 < square_size) && (index1 < square_size))) 
     && (index0/square_size == index1/square_size); 
} 
bool IsSameRow(int index0, int index1, int row_size) { 
    //Assert for row_size != 0 here 
    return IsSameSquare(index0, index1, row_size * row_size) 
    && (index0/row_size == index1/row_size); 
} 
bool IsSameColumn(int index0, int index1, int row_size) { 
    //Assert for row_size != 0 here 
    return IsSameSquare(index0, index1, row_size * row_size) 
     && (index0 % row_size == index1 % row_size); 
} 

//for all possible adjacent positions 
for (int row_step = -1; row_step < 2; ++row_step) { 
    //move up, down or stay put. 
    int row_adjusted_position = original_position + (row_size * row_step); 
    if (!IsSameSquare(original_position, row_adjusted_position, square_size)) { 
    continue; 
    } 
    for (int column_step = -1; column_step < 2; ++column_step) { 
    if ((row_step == 0) & (column_step == 0)) { continue; } 
    //hold on to the position that has had its' row position adjusted. 
    int new_position = row_adjusted_position; 

    if (column_step != 0) { 
     //move left or right 
     int column_adjusted_position = new_position + column_step; 
     //if we've gone out of bounds again for the column. 
     if (IsSameRow(column_adjusted_position, new_position, row_size)) { 
     new_position = column_adjusted_position; 
     } else { 
     continue;       
     } 
    } //if (column_step != 0) 
    //if we get here we know it's safe, do something with new_position 
    //... 
    } //for each column_step 
} //for each row_step 

Répondre

3

Ceci est plus facile si vous avez utilisé l'indexation 0. Ces règles fonctionnent si vous soustrayez 1 de tous vos index:

  • Deux indices sont dans le même carré si (a/9) == (b/9) et> = 0 et b> = 0.
  • Deux index sont dans la même ligne s'ils sont dans le même carré et (a/3) == (b/3).
  • Deux index sont dans la même colonne s'ils sont dans le même carré et (a% 3) == (b% 3).
+0

J'utilisais un tableau basé sur un seul pour simplifier, mais en réalité c'est un tableau basé sur zéro. La cellule zéro représente un nœud source distinct qui est exclu de la marche de la cellule carrée. Merci pour votre réponse, je vais voir ce que je peux faire avec ça. :) – Geoff

+0

Je veux juste souligner que cela repose sur la division entière, pas un problème. Et sacrément pour m'avoir battu au coup de poing! – cmaynard

+0

Hmm. Y a-t-il un moyen d'éviter la division entière? Le point de kramthegram ne m'était pas venu à l'esprit avant de l'avoir testé. Apparemment -1/3 et 0/3 sont en quelque sorte égaux (je connais les détails de pourquoi, ils ne m'avaient tout simplement pas traversé l'esprit). – Geoff

-1

Vous devriez utiliser un tableau multidimensionnel pour cela.

Si votre classe de tableau ne supporte pas les choses multidimensionnelles, vous devriez écrire un wrapper rapide qui le fait.

+0

L'utilisation d'un tableau multidimensionnel n'est pas une option, mais merci pour votre réponse toutefois. – Geoff

+0

Pourquoi n'est-ce pas une option? Vous pouvez écrire un wrapper léger et accéder au tableau linéaire sous-jacent si vous avez quelque chose qui doit y accéder. –

+0

Si vous êtes après la performance avec quelque chose qui bouge autour du tableau ou vérifie les voisins, 2D n'est pas une option. Regarder la grille [pos + offset] est beaucoup plus rapide que la grille [pos_x + offset_x] [pos_y + offset_y]. – phkahler

0

Il y a plusieurs façons de le faire, j'en choisis une bizarre juste pour m'amuser. Utilisez le module. A12 vos lignes sont de taille 3, utilisez simplement le module de 3 et deux règles simples.

If currPos mod 3 = 0 and (currPos+move) mod 3 = 1 then invalid 
If currPos mod 3 = 1 and (currPos+move) mod 3 = 0 then invalid 

cette vérification pour vous sauter deux une nouvelle ligne, vous pouvez également faire une règle comme cette

if (currPos mod 3)-((currPos+move) mod 3)> 1 then invalid 

Vive

Questions connexes