更快找到邻居索引的方法

时间:2015-04-22 05:31:59

标签: java math arraylist

我正在创建一个扫雷游戏,我真的需要一种快速有效的计算矿井邻居的方法,实际上我将我的瓷砖存放在Arraylist中,所以我可以在gridview中使用它们,所以位置是直线但渲染将是矩阵n * n。我有办法做到这一点,但我认为有人可以采用更有效的方式。

我想要实现的目标:

0 1 1 1
0 1 * 1
0 1 1 1
0 0 0 0

因此,如果矩阵具有直线列表中的索引,则位置应如下:

1  2  3  4
5  6  7  8
9  10 11 12
13 14 15 16

所以我需要一种有效的方法来获得2,3,4,6,8,10,11,12,得到指数7.

生成炸弹的代码:

public void plantMines(){
    Random rand = new Random();
    //Used set so we dont get duplicates
    Set<Integer> mineCoords = new LinkedHashSet<>(mDifficulty.mines);
    //First we randomly select all coordenates
    while (mineCoords.size() < mDifficulty.mines){
        Integer coord = rand.nextInt(mListCap) + 1;
        mineCoords.add(coord);
    }
    //Now we can set the mines accordingly
    for (Integer coord: mineCoords){
        mTiles.get(coord).setMine(true);
    }
}

查找邻居的实际代码:

for (int row = 0; row < ROW_SIZE; row++) {
        for (int col = 0; col < COL_SIZE; col++) {
            int neighbourBombSize = 0;

            // TOP ROW
            if ((row-1) >= 0 && (col-1) >= 0) {
                if (getTile(row-1, col-1).hasBomb()) {
                    neighbourBombSize++;
                }
            }

            if ((row-1) >= 0) {
                if (getTile(row-1, col).hasBomb()) {
                    neighbourBombSize++;
                }
            }

            if ((row-1) >= 0 && (col+1) < COL_SIZE) {
                if (getTile(row-1, col+1).hasBomb()) {
                    neighbourBombSize++;
                }
            }

            // SAME ROW
            if ((col-1) >= 0) {
                if (getTile(row, col-1).hasBomb()) {
                    neighbourBombSize++;
                }
            }

            if ((col+1) < COL_SIZE) {
                if (getTile(row, col+1).hasBomb()) {
                    neighbourBombSize++;
                }
            }

            // BOTTOM ROW
            if ((row+1) < ROW_SIZE && (col-1) >= 0) {
                if (getTile(row+1, col-1).hasBomb()) {
                    neighbourBombSize++;
                }
            }

            if ((row+1) < ROW_SIZE) {
                if (getTile(row+1, col).hasBomb()) {
                    neighbourBombSize++;
                }
            }

            if ((row+1) < ROW_SIZE && (col+1) < COL_SIZE) {
                if (getTile(row+1, col+1).hasBomb()) {
                    neighbourBombSize++;
                }
            } 

            getTile(row, col).setNeighbourBombSize(neighbourBombSize);
        }
    }

感谢帮助,谢谢。

2 个答案:

答案 0 :(得分:0)

警告:我已将您的代码作为起始点,但您的索引开始为1,但在java数组索引中从0开始,因此它可能无效。

我会做那样的事情:

int neighbourBombSize = 0;
// Compute currentCell row / col
int currentCellCol = ((currentCellIndex - 1) % COL_SIZE) + 1;
int currentCellRow = ((currentCellIndex - 1) / COL_SIZE) + 1;
System.out.println("Neighbors of " + currentCellIndex + " (" + currentCellRow + ", " + currentCellCol + ")");
for (int x = -1; x <= 1; x++) {
    for (int y = -1; y <= 1; y++) {
        if (x == 0 && y == 0) {
            continue; // Current cell index
        }
        int neighborCol = currentCellCol + y;
        int neighborRow = currentCellRow + x;
        if (neighborCol > 0 && neighborRow > 0 && neighborCol <= COL_SIZE && neighborRow <= ROW_SIZE ) {
            int computedNeighborIndex = neighborCol + ((neighborRow - 1) * COL_SIZE);
            if (getTile(neighborRow , neighborCol ).hasBomb()) {
                neighbourBombSize++;
            }
        }
    }
}

您可以在此处查看正在运行的示例(计算所有案例的邻居索引):Running example

答案 1 :(得分:0)

您打算使用这个基于1的线性索引来编写整个游戏吗?如果是这样,您将需要隔离与坐标之间的转换。否则你最终会陷入困境。

尝试这样的事情:

class Board {

    final int rows;
    final int cols;

    Board(int cols, int rows) {
        this.rows = rows;
        this.cols = cols;
    }

    int col(int index) {
        assert index > 0 && index <= rows * cols;
        return (index - 1) % cols;  // -1 because you are using 1-based indexing. 
    }

    int row(int index) {
        assert index > 0 && index <= rows * cols;
        return (index - 1) / cols;
    }

    int index(int x, int y) {
        assert x >= 0 && x < cols && y >= 0 && y < rows;
        return y * cols + x + 1;
    }

    int[] neighbors(int point) {
        int x = col(point);
        int y = row(point);

        int[] result = new int[8];
        int cnt = 0;

        // go over possible neighbors and collect valid ones
        for (int ny = max(y - 1, 0); ny < min(y + 2, rows); ny++) {
            for (int nx = max(x - 1, 0); nx < min(x + 2, cols); nx++) {
                if (nx != x || ny != y) {
                    result[cnt++] = index(nx, ny);
                }
            }
        }
        return Arrays.copyOf(result, cnt);
    }
}

Board brd = new Board(4, 4);
int colOf7 = brd.col(7);  // 2  (0-based from left)
int rowOf7 = brd.row(7);  // 1  (0-based from top)
int[] neighborsOf7 = brd.neighbors(7);   // [2, 3, 4, 6, 8, 10, 11, 12]
int index = brd.index(2,1); // 7 (1-based linear index)