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; } }
Advertisement
Answer
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); }