This site requires JavaScript, please enable it in your browser!
Greenfoot back
Daylend
Daylend wrote ...

2013/3/14

Using getObjectsAt()

1
2
Daylend Daylend

2013/3/14

#
I'm currently trying to make a function that grabs an object at a random coordinate. The function is within a World subclass, so I cannot use getOneObjectAtOffset() (It's protected). The problem is that after I grab it from the list, it's stuck as an "Object" instead of type "block" (my Actor subclass), so trying to grab or assign values to variables doesn't work properly. Can I somehow convert my Object to an actor subclass? Or is there some other method? I'm stuck!
    public void spawnMines()
    {
        for(int mines=10;mines>0;mines--)
        {
            int x = Greenfoot.getRandomNumber(9);
            int y = Greenfoot.getRandomNumber(9);
            List lBlock;
            lBlock = getObjectsAt(x, y, null);
            Object block = lBlock.get(0);
            if(block.blockStatus!=6)
            {
                block.blockStatus=6;
                block.updateBlock();
            }
            else
            {
                mines++;
            }
        }
    }
I appreciate any help, thanks.
danpost danpost

2013/3/14

#
Do you have 81 blocks in the world (one in each cell)? And, are blocks the only objects you have in the world?
Daylend Daylend

2013/3/14

#
Yes, and yes. Every cell is filled with one block.
danpost danpost

2013/3/14

#
Then, the following would be more telling as to what you are trying to do:
public void spawnMines()
{
    for (int mines=0; mines<10; mines++)
    {
        boolean found = false;
        while (!found)
        {
            int x = Greenfoot.getRandomNumber(9);
            int y = Greenfoot.getRandomNumber(9);
            block b = (block)getObjectsAt(x, y, null).get(0);
            if (b.blockStatus != 6)
            {
                b.blockStatus = 6;
                b.updateBlock();
                found = true;
            }
        }
    }
}
Notice how line 10 casts the item from the returned list as a 'block' object.
Daylend Daylend

2013/3/14

#
Thank you for this. Your method looks much nicer too. Would you mind explaining what "(block)" does? I'm a noob still, only a few hours of coding experience in Java. :)
davmac davmac

2013/3/14

#
Would you mind explaining what "(block)" does?
It's called a "cast" or more properly a "type cast". It tells the compiler that you are certain that the Object is really, in fact, a Block; once you've cast something to a certain type, you can then use the methods belonging to that type, or assign it to a variable of the same type. You could re-write your original code to use a cast:
    public void spawnMines()  
    {  
        for(int mines=10;mines>0;mines--)  
        {  
            int x = Greenfoot.getRandomNumber(9);  
            int y = Greenfoot.getRandomNumber(9);  
            List lBlock;  
            lBlock = getObjectsAt(x, y, null);  
            block block = (block) lBlock.get(0);  
            if(block.blockStatus!=6)  
            {  
                block.blockStatus=6;  
                block.updateBlock();  
            }  
            else  
            {  
                mines++;  
            }  
        }  
    }  
Note that in Java, the convention is to have class names start with capitals, and variables and methods start with lower-case. So your class should really be called 'Block' not 'block'!
Daylend Daylend

2013/3/14

#
Ahh now I get it, thank you. :)
davmac wrote...
Note that in Java, the convention is to have class names start with capitals, and variables and methods start with lower-case. So your class should really be called 'Block' not 'block'!
Heh, yeah I noticed that after I saw some examples online. Oops! I think I'm going to leave it though, just this one time. I'd have to update some of my other code. Thanks for everything guys, I'll update this if I need help with the same project.
Daylend Daylend

2013/3/16

#
Alright so now I'm in an actor subclass, trying to use getOneObjectAtOffset. On run time it's giving me a "NullPointerException" error. I'm 99% certain it has to do with the OneObject function. It returns an actor, but I'm using a type cast to change it to a block so it can check blockStatus. Probably why it's not working properly. Help!
           for(int x=0; x<3; x++)
            {
                for(int y=0; y<3; y++)
                {
                    int iBlockx = this.getX() + x - 1;
                    int iBlocky = this.getY() + y - 1;
                    if(iBlockx>=0&&iBlocky>=0&&iBlockx<=8&&iBlocky<=8)
                    {
                        block b = (block)getOneObjectAtOffset(iBlockx, iBlocky, null);
                        if(b.blockStatus==0)
                        {
                            b.onClick();
                            b.updateBlock();
                        }
                    }
                }
            }
danpost danpost

2013/3/17

#
Please supply the code for the 'onClick' method. Also, give what line the error occurs on (if you do not know, supply the whole error message, complete with trace, and the complete actor class code). Thanks.
Daylend Daylend

2013/3/17

#
    public void onClick()
    {
        this.isClicked = true;
        //If you clicked on a mine, you lose. Otherwise keep playing.
        if(this.blockStatus==6)
        {
            this.updateBlock();
            initMinesweeper minesweeper = new initMinesweeper();
            minesweeper.loseGame();
        }
        else if(this.blockStatus==0)
        {
            for(int x=0; x<3; x++)
            {
                for(int y=0; y<3; y++)
                {
                    int iBlockx = this.getX() + x - 1;
                    int iBlocky = this.getY() + y - 1;
                    if(iBlockx>=0&&iBlocky>=0&&iBlockx<=8&&iBlocky<=8)
                    {
                        block b = (block)getOneObjectAtOffset(iBlockx, iBlocky, null);
                        if(b.blockStatus==0)
                        {
                            b.onClick();
                            b.updateBlock();
                        }
                    }
                }
            }
        }
        else
        {
            this.updateBlock();
        }
    }
Error on line 22. I think that's everything. Thanks.
danpost danpost

2013/3/17

#
Now that I see what you are trying to do, I would suggest that you use 'getNeighbours' instead of a double 'for' with 'getOneObjectAtOffset'. This would eliminate the need to verify if the possible location has a block, as well as avoid any nasty exceptions. The whole 'onClick' method could be reduced to:
public void onClick()
{
    this.isClicked = true;
    //If you clicked on a mine, you lose. Otherwise keep playing.
    if(this.blockStatus==6)
    {
        this.updateBlock();
        initMinesweeper minesweeper = new initMinesweeper();
        minesweeper.loseGame();
    }
    else if(this.blockStatus==0)
    {
        for (Object obj : getNeighbours(1, true, block.class))
        {
            block b = (block) obj;
            if(b.blockStatus==0)
            {
                b.onClick();
                b.updateBlock();
            }
        }
    }
    else
    {
        this.updateBlock();
    }
}
Daylend Daylend

2013/3/17

#
Alright, thank you. Do you think you'd be able to explain that for statement? It's different from anything I've seen.
       for (Object obj : getNeighbours(1, true, block.class))  
Hmm the code seems to be giving me a stack over flow error on this line now ^, as well as line 18.
danpost danpost

2013/3/17

#
Sure. Instead of iterating through numbers, it iterates through a list of objects. The list is returned from the 'getNeighbours' call, which returns all block objects within a distance of one, including diagonals. Each object returned in the list will be placed in the 'obj' field when the loop is executed for that object, which later is type-cast to a 'block' object within the 'for' block.
danpost danpost

2013/3/17

#
I was thinking that you may end up with some other type of error. Try changing line 16 to
if (!this.isClicked && b.blockStatus == 0)
Report back as to results.
Daylend Daylend

2013/3/17

#
danpost wrote...
I was thinking that you may end up with some other type of error. Try changing line 16 to
if (!this.isClicked && b.blockStatus == 0)
Report back as to results.
With this.isClicked, when a block with a status of 0 was clicked, nothing happened. I changed it to b.isClicked and it worked, except for the original block that was clicked. It doesn't update. So I added this.updateBlock(), but now it's returning a null pointer error because it's removing the block before the for loop is finished, so I removed it. Any ideas?
public void onClick()
{
    this.isClicked = true;
    //If you clicked on a mine, you lose. Otherwise keep playing.
    if(this.blockStatus==6)
    {
        this.updateBlock();
        initMinesweeper minesweeper = new initMinesweeper();
        minesweeper.loseGame();
    }
    else if(this.blockStatus==0)
    {
        for (Object obj : getNeighbours(1, true, block.class))
        {
            block b = (block) obj;
            if(!b.isClicked && b.blockStatus==0)
            {
                b.onClick();
                b.updateBlock();
            }
        }
    }
    else
    {
        this.updateBlock();
    }
}
There are more replies on the next page.
1
2