简体   繁体   English

初始化2D Java数组

[英]Initializing 2d java array

I am working on an extremely basic game. 我正在开发一个非常基础的游戏。 However when I try to create the array i am running into errors. 但是,当我尝试创建数组时,我遇到了错误。 The error is index out of bounds. 错误是索引超出范围。 However I thought I fixed it by adding the -1 to make sure I don't go out of bounds. 但是我想我通过添加-1来解决这个问题,以确保我不会超出范围。 can someone tell me, or give me a clue as to what I did wrong? 有人可以告诉我,还是给我一个关于我做错了什么的线索?

package gameProject;

public class world {
int numEnemies, numBosses;
int [][] world = new int[10][10];

public world(){
    int[][] world  = createArray(10,10);
    populateWorld(world);
}

private int[][] createArray(int inX, int inY){
    //create the array that holds world values
    int[][] world = new int[inX][inY];
    //initialize the world array
    for(int i = 0; i < world.length - 1; i ++){
        for(int j = 0; j < world[0].length - 1; j++){
            world[i][j] = 0;
        }
    }

    return world;
}

private void populateWorld(int[][] world){
    for(int i = 0; i < world.length - 1; i++){
        for(int j = 0; j < world[0].length - 1; i++){
            world[i][j] = 0;
        }
    }

}
}

In your populateWorld method, change 在您的populateWorld方法中,更改

for(int j = 0; j < world[0].length - 1; i++)

to

for(int j = 0; j < world[0].length - 1; j++)

You keep incrementing the wrong counter, going eventually out of its bounds. 您不断增加错误的计数器,最终超出其范围。 (10) (10)

( PS: you don't need the length - 1 in your loops' condition, just length would do) PS:您不需要length - 1在循环条件下为1,只要length就可以了)

The error is in 错误在

for (int j = 0; j < world[0].length - 1; i++)

you should write 你应该写

for (int j = 0; j < world[0].length - 1; j++)

instead. 代替。

Note that you can reduce your code a little bit: 请注意,您可以减少一些代码:

You create the array for member World.world twice. 您为成员World.world创建数组两次。 Also the elements of an int array are already initialized to 0 so you don't need to do this explicitly. 另外,一个int数组的元素已经被初始化为0,因此您不需要显式地执行此操作。

You should just do 你应该做

private int[][] createArray(int inX, int inY) {
    int[][] world = new int[inX][inY];
    for (int i = 0; i < inX; i++)
        for (int j = 0; j < inY; j++)
            world[i][j] = 0;
    return world;
}

You never actually need to check the length of the world array, because the length was already passed in as a parameter value. 您实际上不需要检查world数组的长度,因为该长度已经作为参数值传递了。

And then also 然后也

private void populateWorld(int[][] world) {
    for (int i = 0; i < world.length; i++)// v     error 'i' should be 'j'
        for (int j = 0; j < world[i].length; j++) // <- error on this line
            world[i][j] = 0;
}

Your basic problem is that you're incrementing the wrong loop variable. 您的基本问题是要增加错误的循环变量。 Why? 为什么? Because you're far off from any clean code. 因为您离任何干净的代码都不远。 Lemme show you how clean coding is done: Lemme向您展示如何完成清晰的编码:

  • class names start with a capital letter, method and variable name with lower case letters 类名以大写字母开头,方法和变量名以小写字母开头
  • you might prefix your variables with their scope ('m' for member, 'p' for parameter, nothing for local variables). 您可以在变量的作用域之前添加前缀(成员为“ m”,参数为“ p”,局部变量为空)。 Saves you the all-time-reference to 'this'. 保存您对“ this”的全部引用。 Strongly depends on your code style. 很大程度上取决于您的代码样式。 I highly suggest doing it, keeps your code clean and really easy to debug. 我强烈建议您这样做,使您的代码保持干净,并且非常容易调试。
  • use the final and private keywords where possible 尽可能使用final和private关键字
  • use descriptive variable names. 使用描述性的变量名。 Here especially x and y for loop variables, as you're abstracting a 2d-plane 在这里,特别是x和y是循环变量,因为您要抽象2d平面

Some more considerations: 更多注意事项:

  • usually games grow more complex. 通常游戏变得越来越复杂。 Usually simple primitives (like your int-array) will not suffice for long to store all relevant information. 通常,简单的原语(例如您的int数组)将不足以长时间存储所有相关信息。 Use classes like Cell 使用像Cell这样的类
  • use enums so you can lose magic numbers => coding, reading and debugging made a lot easier 使用枚举,这样就可以避免丢失幻数=>编码,读取和调试变得容易得多

So - after a lot of talk - here's the final code: 因此-经过大量讨论-这是最终代码:

package gameproject;

/**
 * Use comments like this to describe what the classes purpose is.
 * Class comment is the most important one. If you can't tell what a method/variable is doing by its name, you should also comment methods and/or variables!
 * @author JayC667
 */
public class World {

    /*
     * STATIC part of the class - keep separated from object code
     */

    // you could/should also put these static classes to their separate files and make em non-static
    /**
     * Denotes, what a {@linkplain Cell} is occupied with
     */
    static public enum CellType {
        EMPTY, //
        BOSS, //
        ENEMY
    }

    /**
     * Represents a single cell within the world. Stores information about its coodrinates (redundant) and its occupator (see {@linkplain CellType})
     * @author JayC667
     */
    static private class Cell { // use cell to store data for you
        public final int    mX;                         // x and y are actually not useful at the moment, you could also remove them
        public final int    mY;
        private CellType    mCellType   = CellType.EMPTY;

        public Cell(final int pX, final int pY) {
            mX = pX;
            mY = pY;
        }

        public CellType getCellType() {
            return mCellType;
        }
        public void setCellType(final CellType pCellType) {
            mCellType = pCellType;
        }
    }

    // when possible, make methods static, unless you unnecessarily blow up the parameter list
    // this is a typical demo for a factory method
    static private Cell[][] createWorld(final int pWidth, final int pHeight) {
        final Cell[][] newWorld = new Cell[pWidth][pHeight];
        for (int y = 0; y < pHeight - 1; y++) {
            for (int x = 0; x < pWidth - 1; x++) {
                newWorld[y][x] = new Cell(x, y);
            }
        }
        return newWorld;
    }

    /*
     * OBJECT part of the class - keep separated from static code
     */

    private final Cell[][]  mWorld;
    private final int       mWorldWidth;
    private final int       mWorldHeight;
    private final int       mNumberOfEnemies;
    private final int       mNumberOfBosses;

    public World(final int pWidth, final int pHeight, final int pNumberOfEnemies, final int pNumberOfBosses) {
        if (pWidth < 1 || pHeight < 1) throw new IllegalArgumentException("World width and height must be greater than 0!");
        if (pNumberOfEnemies < 0 || pNumberOfBosses < 0) throw new IllegalArgumentException("Enemy and boss counts must not be negative!");
        if (pWidth * pHeight < pNumberOfEnemies + pNumberOfBosses) throw new IllegalArgumentException("World is too small for all the bad guys!");

        mWorldWidth = pWidth;
        mWorldHeight = pHeight;
        mNumberOfEnemies = pNumberOfEnemies;
        mNumberOfBosses = pNumberOfBosses;
        mWorld = createWorld(pWidth, pHeight);
        populateWorld();
    }

    // refers to many member variables, so not static (would only blow up parameter list)
    private void populateWorld() {
        for (int i = 0; i < mNumberOfBosses; i++) {
            final Cell c = getRandomCell(CellType.EMPTY);
            mWorld[c.mY][c.mX].setCellType(CellType.BOSS);
        }
        for (int i = 0; i < mNumberOfEnemies; i++) {
            final Cell c = getRandomCell(CellType.EMPTY);
            mWorld[c.mY][c.mX].setCellType(CellType.ENEMY);
        }
    }

    private Cell getRandomCell(final CellType pCellType) {
        while (true) { // TODO not a good, but simple solution; might run infinite loops
            final int randomX = (int) (mWorldWidth * Math.random());
            final int randomY = (int) (mWorldHeight * Math.random());
            if (mWorld[randomY][randomX].getCellType() == pCellType) return new Cell(randomX, randomY);
        }
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM