10
votes

Manière plus efficace de vérifier les voisins dans un tableau bidimensionnel en Java

Hey tout, pour quelques-uns de mes affectations collégiales, j'ai trouvé la nécessité de vérifier les cellules voisines dans des tableaux à 2 dimensions (grilles). La solution que j'ai utilisée est un peu un piratage en utilisant des exceptions et je cherche un moyen de le nettoyer sans avoir des charges de si Des déclarations telles que certaines de mes camarades de classe. Ma solution actuelle est xxx i

​​i frisson de penser à l'inefficacité à l'aide d'exceptions pour que mon code fonctionne des causes, donc je cherche des suggestions sur la manière dont je pourrais supprimer la dépendance à partir de Mon code sans sacrifier la lisibilité s'il est possible et à quoi je puisse faire ce segment de code généralement plus efficace. Merci d'avance.


2 commentaires

Ne pas chier trop, mais des exceptions devraient être exceptionnelles. Il est presque toujours préférable de valider la contribution à l'avance, en particulier dans des cas triviaux. Sinon, vous pouvez couvrir des exceptions importantes et cacher des défauts avec l'algorithme.


Autant plus de raisons pour lesquelles je veux me débarrasser des exceptions. Encore une fois, c'était juste un piratage rapide pour terminer la mission, mais je ne suis pas satisfait de le laisser comme ça.


7 Réponses :


3
votes

Pourquoi ne pouvez-vous pas vérifier la ligne + Rowmod et Col + Colmod pour validité avant l'accès au tableau?

Quelque chose comme: xxx

continue (non continuer ): xxx


3 commentaires

Une bonne solution, beaucoup plus efficace que la mienne, mais je le considérerais toujours un peu hacky depuis que j'ai appris à éviter pause et continuer . Merci beaucoup pour la réponse.


Si vous avez peur de continuer simplement inverser la condition et de l'ajouter à votre si


J'aime vraiment ça; C'est petit et ne sort pas des limites.



2
votes

Le principe de base n'est pas d'accéder à des choses hors limites - donc de protéger les limites ou ne sortez pas de limites en premier lieu. C'est-à-dire commencer à un endroit où vous ne sortirez pas immédiatement des limites et de vous arrêter avant de sortir des limites.

for ( int row = 1; row < grid.length - 1; row++ ) {
    for ( int col = 1; col < grid.length - 1; col++ ) {
        // this section will usually be in a function
        // checks neighbours of the current "cell"
        for ( int rowMod = -1; rowMod <= 1; rowMod++ ) {
            for ( int colMod = -1; colMod <= 1; colMod++ ) {
                if ( someVar == grid[row+rowMod][col+colMod] ) {
                    // do something
                }
            }
        }
        // end checking neighbours
    }
}


2 commentaires

Également appelé "garde". Habituellement, les cellules "garde" (les cellules de la colonne 0, par exemple) contiendront une valeur spéciale qui entraînera une nouvelle opération ou être facile à traiter.


Oui, ce serait une solution pour, disons, mon programme de ConnectFour, où je veux juste vérifier les voisins connectés, mais cela ne calculerait pas correctement les voisins dans un programme de gameflife. Je n'ai pas besoin de vérifier chaque cellule nécessairement, mais trouvez le nombre de voisins de chaque cellule (spécifiant une condition). Merci pour la réponse cependant.



1
votes

Si je comprends votre code correctement et que vous devinez correctement vos préoccupations, vous essayez d'éviter de vérifier un voisin inexistant lorsque la cellule d'intérêt est sur un bord de la grille. Une approche, qui peut ne pas convenir à votre application ou non, est de mettre une bordure à 1 cellule tout autour autour de votre grille. Vous courez ensuite vos boucles à travers l'intérieur de cette grille expansée et toutes les cellules que vous vérifiez ont 4 voisins (ou 8 si vous comptez les cellules voisines de la diagonale).


1 commentaires

Ceci, en combinaison avec la solution de Mark E, ferait une solution parfaite, merci.



24
votes

Vous pouvez essayer ceci. D'abord décider la taille de la grille permet de dire son 8 x 8 et assigner min_x = 0, min_y = 0, max_x = 7, max_y = 7

Votre position curren est représentée par cet appartement, cette appartement, puis essayez ceci: P >

int startPosX = (thisPosX - 1 < MIN_X) ? thisPosX : thisPosX-1;
int startPosY = (thisPosY - 1 < MIN_Y) ? thisPosY : thisPosY-1;
int endPosX =   (thisPosX + 1 > MAX_X) ? thisPosX : thisPosX+1;
int endPosY =   (thisPosY + 1 > MAX_Y) ? thisPosY : thisPosY+1;


// See how many are alive
for (int rowNum=startPosX; rowNum<=endPosX; rowNum++) {
    for (int colNum=startPosY; colNum<=endPosY; colNum++) {
        // All the neighbors will be grid[rowNum][colNum]
    }
}


1 commentaires

Oui, j'ai réfléchi à ce problème pendant un moment et la meilleure solution que je pense que je connaisse est très comme celle-ci, sauf plutôt que de faire des comparaisons / missions explicites que j'utilise Math.Max ​​et Math.min.



7
votes

SO ligne et col contient actuellement la coordonnée de la cellule que je veux vérifier les voisins de. Donc, si j'ai une variable de classe appelée start_of_grid qui contient 0 , ma solution serait la suivante: xxx


1 commentaires

Pour une raison quelconque (peut être je le fais mal), la solution de Vivek ne fonctionne pas pour moi (il ne vérifie que 4 cellules au lieu de 8). Ton travaille bien! Merci.



1
votes

Que diriez-vous de cela:

private static void printNeighbours(int row, int col, int[][] Data, int rowLen, int colLen)
{
    for(int nextR=row-1; nextR<=row+1; nextR++)
    {
        if(nextR<0 || nextR>=rowLen)
            continue;  //row out of bound
        for(int nextC=col-1; nextC<=col+1; nextC++)
        {
            if(nextC<0 || nextC>=colLen)
                continue;  //col out of bound
            if(nextR==row && nextC==col)
                continue;    //current cell
            System.out.println(Data[nextR][nextC]);
        }
    }
}


0 commentaires

0
votes
private void fun(char[][] mat, int i, int j){
    int[] ith = { 0, 1, 1, -1, 0, -1 ,-1, 1};
    int[] jth = { 1, 0, 1, 0, -1, -1 ,1,-1};
     // All neighbours of cell
     for (int k = 0; k < 8; k++) {
            if (isValid(i + ith[k], j + jth[k], mat.length)) {
                //do something here 
            }
        }
}

private boolean isValid(int i, int j, int l) {
        if (i < 0 || j < 0 || i >= l || j >= l)
            return false;
        return true;
}

2 commentaires

Veuillez ajouter une description à la réponse. @ Vikas Tiwari


Code mis à jour. Vous pouvez accéder à tous les voisins dans la zone commentée à l'aide de tapis [i + ith [k]] [J + JTH [K]].