I have my code as the following.
package net.ferrell.wrathoftuemdaym;
import java.awt.*;
public class Level {
public Block[][] block = new Block[50][50];
public Level() {
for(int x = 0; x < block.length; x++) {
for(int y = 0; y < block[0].length; y++);
block[x][y] = new Block(new Rectangle(x * Tile.tileSize, y * Tile.tileSize, Tile.tileSize, Tile.tileSize), Tile.air);
}
}
public void generateLevel() {
for(int x = 0; x < block.length; x++) {
for(int y = 0; y < block[0].length; y++);
if(x == 0 || y == 0 || x == block.length-1 || y == block[0].length-1) {
block[x][y].id = Tile.earth;
}
}
}
public void tick() {
}
public void render(Graphics g) {
for(int x = 0; x < block.length; x++) {
for(int y = 0; y < block[0].length; y++);
block[x][y].render(g);
}
}
}
In a line that says " block[x][y] ", y cannot be resolved to a variable. I do not know the fix for this and it is only in this class that the problem exists. Please help me. I do not understand because the x CAN be resolved...
this is your culprit
for(int y = 0; y < block[0].length; y++);
it should be
for(int y = 0; y < block[0].length; y++)
Personally I always put braces in code blocks even if it is just one line.
Related
In order to study programming, I am making a game 2048 in java. The game has a class in which there are many repetitive fragments - field iteration loops. The question is, is it possible to create such a method that will accept the values of the enumeration bounds and the executable code?
Something like this both for assignment and comparison.
public void forField(int borderX, int borderY, ??? code){
for (int x = 0; x < borderX; x++)
for (int y = 0; y < borderY; y++)
do code;
}
public boolean checkField(int borderX, int borderY, ??? code, boolean default_answer){
for (int x = 0; x < borderX; x++)
for (int y = 0; y < borderY; y++)
return code;
return default_answer;
}
If not, can you recommend how to make my code better? Thank you for your attention.
public class Field {
private int[][] field;
private int width, heigth;
public Field(int sizeX, int sizeY) {
this.width = sizeX;
this.heigth = sizeY;
this.field = new int[sizeX][sizeY];
}
public int getCell(int x, int y) {
return this.field[x][y];
}
public void setCell(int val, int x, int y) {
this.field[x][y] = val;
}
// for restart
public void reset() {
for (int x = 0; x < width; x++)
for (int y = 0; y < heigth; y++)
this.field[x][y] = 0;
}
// for step cancelling function
public void copyOf(Field f) {
for (int x = 0; x < width; x++)
for (int y = 0; y < heigth; y++)
this.field[x][y] = f.getCell(x, y);
}
// can field changed after pressing a key
public boolean isEqualTo(Field f) {
for (int x = 0; x < width; x++)
for (int y = 0; y < heigth; y++)
if (field[x][y] != f.getCell(x, y))
return false;
return true;
}
private boolean canMergeByY() {
for (int x = 0; x < width; x++)
for (int y = 0; y < heigth - 1; y++)
if (field[x][y] == field[x][y + 1])
return true;
return false;
}
private boolean canMergeByX() {
for (int x = 0; x < width - 1; x++)
for (int y = 0; y < heigth; y++)
if (field[x][y] == field[x + 1][y])
return true;
return false;
}
// checking the possibility of continuing the game
public boolean canMerge() {
return canMergeByX() && canMergeByY();
}
// checking 0 and 2048 cells for different tasks
public boolean contains(int i) {
for (int x = 0; x < width; x++)
for (int y = 0; y < heigth; y++)
if (field[x][y] == i)
return true;
return false;
}
}
The ??? in forField can just be a BiConsumer<Integer, Integer>, or you can declare your own IntBiConsumer interface if you don't like boxing:
interface IntBiConsumer {
void accept(int i, int j);
}
forField can then be declared as:
public void forField(int borderX, int borderY, IntBiConsumer code){
for (int x = 0; x < borderX; x++)
for (int y = 0; y < borderY; y++)
code.accept(x, y);
}
copyOf can then be written as:
public void copyOf(Field f) {
forField(width, height, (x, y) -> {
this.field[x][y] = f.getCell(x, y);
});
}
checkField is a little bit more tricky, your proposed code wouldn't actually work, because you are not checking anything before you return in the inner loop. The loops will only loop once, and return immediately. It should be more like:
public boolean checkField(int borderX, int borderY, ??? condition, boolean default_answer){
for (int x = 0; x < borderX; x++)
for (int y = 0; y < borderY; y++)
if (condition)
return !default_answer;
return default_answer;
}
??? here can be a BiPredicate<Integer, Integer>, or your own interface like this:
interface IntBiPredicate {
boolean test(int i, int j);
}
checkField can then be declared like this:
public boolean checkField(int borderX, int borderY, IntBiPredicate condition, boolean defaultAnswer){
for (int x = 0; x < borderX; x++)
for (int y = 0; y < borderY; y++)
if (condition.test())
return !defaultAnswer;
return defaultAnswer;
}
isEqualTo can be rewritten as:
public boolean isEqualTo(Field f) {
return checkField(width, height, (x, y) -> field[x][y] != f.getCell(x, y), true);
}
I have this method that's able to rotate the array by 90 degrees. I want to be to flip vertically and horizontally (I'm binding them with different buttons). Here's the method.
private void Rotate90() {
String[][] temp = new String[totalX][totalY];
for (int y = 0; y < totalY; y++) {
for (int x = 0; x < totalX; x++) {
temp[x][y] = fields[x][y].getText();
}
}
for (int y = 0; y < totalY; y++) {
for (int x = 0; x < totalX; x++) {
fields[x][y].setText(temp[y][x]);
}
}
Draw();
}
#khriskooper code contains an obvious bug: it flips array twice i.e. effectively does nothing. To flip array you should iterate only half of the indices. Try something like this:
private void flipHorizontally() {
for (int y = 0; y < totalY; y++) {
for (int x = 0; x < totalX/2; x++) {
String tmp = fields[totalX-x-1][y].getText();
fields[totalX-x-1][y].setText(fields[x][y].getText());
fields[x][y].setText(tmp);
}
}
}
private void flipVertically() {
for (int x = 0; x < totalX; x++) {
for (int y = 0; y < totalY/2; y++) {
String tmp = fields[x][totalY - y - 1].getText();
fields[x][totalY - y - 1].setText(fields[x][y].getText());
fields[x][y].setText(tmp);
}
}
}
I'm currently creating a brickbreaker (or breakout, like atari breakout) and for the bricks im using a 2d array:
private Brick bricks[][] = new Brick[10][41];
To destroy a specific Brick (for whatever reason i have to destroy that), i created a method:
public void destroyBrick(Brick brick) {
for(int x = 0; x < bricks[x].length; x++) {
for(int y = 0; y < bricks[y].length; y++) {
if (bricks[x][y].equals(brick)) {
bricks[x][y] = null;
}
}
}
}
The way the array is created is the following:
for(int j=0; j<bricks[0].length; j++){
for(int i=0; i<bricks.length; i++){
bricks[i][j]=new Brick(game,10,Color.GREEN,j*margin,i*margin);
}
}
Now for some reason the counter for x eventually reaches 10 and the counter for y reaches 0 where it crashes, and i can't figure out why.
Is there a different way of iterating a 2d array that has different values for columns and rows?
note
The reason the formatting and my spelling is so rubbish is, that im writing this on the app version. Feel free to correct any mistakes or formatting errors, before i can.
You are referencing y in the loop that iterates on it. This compiles correctly, because y is defined at the point of reference, but it does not do what you need. In addition, the outer loop should stop upon reaching bricks.length, not bricks[x].length.
These two lines
for(int x = 0; x < bricks[x].length; x++) {
for(int y = 0; y < bricks[y].length; y++) {
should be
for(int x = 0; x < bricks.length; x++) {
// ^
for(int y = 0; y < bricks[x].length; y++) {
// ^
The first int x doesn't refer to what you need, I think.
x ranges from 0 to the length of the array indexed with x, that is 41.
for (int x = 0; x < bricks.length; x++)
for (int y = 0; y < bricks[x].length; y++)
Should work (at least I wrote this without testing)
Try iterating with any of this
public void destroyBrick(Brick brick) {
for(int x = 0; x < bricks.length; x++) {
for(int y = 0; y < bricks[0].length; y++) {
if (bricks[x][y].equals(brick)) {
bricks[x][y] = null;
}
}
}
}
or
public void destroyBrick(Brick brick) {
for(int x = 0; x < bricks.length; x++) {
for(int y = 0; y < bricks[x].length; y++) {
if (bricks[x][y].equals(brick)) {
bricks[x][y] = null;
}
}
}
}
if there's any other error, use your debugger to find out where exactly
I am new to Java programming and would like to seek your help.
I'm trying to develop a simple minesweeper game using Java. However, I keep getting the error "Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1 at practice.week.pkg4.PracticeWeek4.main(PracticeWeek4.java:55)"
This occurs when I'm trying to place digits around the square which has a bomb. I understand that perhaps the 1 has went out of the array, causing the exception to occur. However, I'm not sure how to go about catching the error. Would appreciate any kind help.
Eg: Sample Output
1 1 1
1 B 1
1 1 1
Here is my code snippet:
public static void main(String[] args) {
// TODO code application logic here
int rows = 9;
int cols = 9;
char[][] map = new char[rows][cols];
int count = 0;
for(int i = 0; i<map.length; i++)
{
for(int j = 0; j<map[i].length; j++)
{
map[i][j] = '.';
}
}
Random rnd = new Random();
do
{
int x = rnd.nextInt(rows);
int y = rnd.nextInt(cols);
for(int i = 0; i<map.length; i++)
{
for(int j = 0; j<map[i].length; j++)
{
if(map[x][y] != 'B' && x > 0 & y > 0)
{
map[x][y] = 'B';
map[x-1][y-1] = '1';
map[x-1][y] = '1';
map[x-1][y+1] = '1';
map[x][y-1] = '1';
map[x][y+1] = '1';
map[x+1][y-1] = '1';
map[x+1][y] = '1';
map[x+1][y+1] = '1';
count++;
}
}
}
}
while(count < 10);
for(int x = 0; x<map.length; x++)
{
for(int y = 0; y <map[x].length; y++)
{
}
}
for(int x = 0; x<map.length; x++)
{
for(int y = 0; y<map[x].length; y++)
{
System.out.print(map[x][y] + " ");
}
System.out.println("");
}
}
The do-while loop for setting the mines is on the right track, but the way you are updating the counts for surrounding blocks is causing the IndexOutOfBoundsException. And these two loops
for(int i = 0; i < map.length; i++)
{
for(int j = 0; j < map[i].length; j++)
serve no purpose. You need to rearrange it to handle multiple mines, etc, so why not set all the mines first:
do
{
int x = rnd.nextInt(rows);
int y = rnd.nextInt(cols);
if (map[x][y] != 'B')
{
map[x][y] = 'B';
count++;
}
} while(count < 10);
Then go through the map, and count the number of mines surrounding each block:
for (int x = 0; x < map.length; x++)
{
for (int y = 0; y < map[x].length; y++)
{
if (map[x][y] == 'B')
continue;
// Count the number of mines around map[x][y]
int mines = 0;
for (int xOffset = -1; xOffset <= 1; xOffset++)
{
// This is an important step - without it, we will access elements off the edge of the map
if (x + xOffset < 0 || x + xOffset >= map.length)
continue;
for (int yOffset = -1; yOffset <= 1; yOffset++)
{
// Another check for the edge of the map
if (y + yOffset < 0 || y + yOffset >= map[x].length)
continue;
if (map[x + xOffset][y + yOffset] == 'B')
mines++;
}
}
map[x][y] = "012345678".charAt(mines); // Get the number as a character
}
}
For some reason the blocks keep being rendered in the same position. Can anybody help me?
Block[][] chunk = new Block[Chunk.CHUNK_WIDTH_BLOCKS][Chunk.CHUNK_HEIGHT_BLOCKS];
float[][] positions = new float[Chunk.CHUNK_WIDTH_BLOCKS][Chunk.CHUNK_HEIGHT_BLOCKS];
float frequency = 1.0f / (float) chunk.length;
for (int x = 0; x < chunk.length - 1; x++)
{
for (int y = 0; y < chunk[x].length - 1; y++)
{
positions[x][y] = SimplexNoise.Generate((float) x * frequency, (float) y * frequency);
g.drawRect(positions[x][0], positions[0][y], Block.BLOCK_WIDTH, Block.BLOCK_HEIGHT);
}
}
for (int x = 0; x < Chunk.CHUNK_WIDTH_BLOCKS; x++)
{
for (int y = 0; y < Chunk.CHUNK_HEIGHT_BLOCKS; y++)
{
if (positions[x][y] < 0f)
chunk[x][y] = new Block();
if (positions[x][y] >= -0f)
chunk[x][y] = new Block();
}
}
You have multiple problems with your code. For instance:
for (int x = 0; x < chunk.length - 1; x++)
That should be:
for (int x = 0; x < chunk.length; x++)
Also, consider the following:
g.drawRect(positions[x][0], positions[0][y], Block.BLOCK_WIDTH, Block.BLOCK_HEIGHT);
That will not use all values in "positions[x][y]".... I think that what you will want is for the array to be 3d... for instance:
float[][][] positions = new float[Chunk.CHUNK_WIDTH_BLOCKS][Chunk.CHUNK_HEIGHT_BLOCKS][2];
That way: posistions[x][y][0] is the value for x, and positions[x][y][1] is the value for y....
g.drawRect(positions[x][y][0], positions[x][y][1], Block.BLOCK_WIDTH, Block.BLOCK_HEIGHT);
I am not sure I understand your code exactly, but it does seem to have issues.