This commit is contained in:
Jacob Signorovitch
2025-05-28 08:02:46 -04:00
parent 0b30c851e4
commit 83e80a48e2

View File

@@ -4,6 +4,7 @@ import java.awt.Color;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Random;
import javalib.impworld.*; import javalib.impworld.*;
import javalib.worldimages.*; import javalib.worldimages.*;
import tester.Tester; import tester.Tester;
@@ -11,10 +12,6 @@ import tester.Tester;
class Examples { class Examples {
void testRun(Tester t) { void testRun(Tester t) {
Game game = new Game(); Game game = new Game();
game.board.board.put(new Coord(0, 0), new Tile(2));
game.board.board.put(new Coord(3, 1), new Tile(20));
game.board.board.put(new Coord(3, 2), new Tile(200));
game.board.board.put(new Coord(2, 3), new Tile(2000));
game.run(); game.run();
} }
} }
@@ -64,23 +61,36 @@ class Game extends World {
this.sz = Util.defaultWidth; this.sz = Util.defaultWidth;
this.width = this.sz * Util.scale; this.width = this.sz * Util.scale;
this.board = new Board(this.sz); this.board = new Board(this.sz);
this.board.randGen();
this.board.randGen();
} }
public WorldScene makeScene() { public WorldScene makeScene() {
WorldScene scene = new WorldScene(this.width, this.width); WorldScene scene = new WorldScene(this.width, this.width);
scene.placeImageXY(this.board.draw(), this.width / 2, this.width / 2); scene.placeImageXY(this.board.draw(), this.width / 2, this.width / 2);
scene.placeImageXY(
new TextImage("Score: " + this.score, 20, Color.RED),
this.width / 2, 20
);
return scene; return scene;
} }
public void onKeyEvent(String key) { public void onKeyEvent(String key) {
System.out.println("got key" + key); System.out.println("got key" + key);
if (key.equals("left") || key.equals("h")) this.board.move(Move.LEFT);
int score = 0;
if (key.equals("left") || key.equals("h"))
score = this.board.move(Move.LEFT);
else if (key.equals("down") || key.equals("j")) else if (key.equals("down") || key.equals("j"))
this.board.move(Move.DOWN); score = this.board.move(Move.DOWN);
else if (key.equals("up") || key.equals("k")) this.board.move(Move.UP); else if (key.equals("up") || key.equals("k"))
score = this.board.move(Move.UP);
else if (key.equals("right") || key.equals("l")) else if (key.equals("right") || key.equals("l"))
this.board.move(Move.RIGHT); score = this.board.move(Move.RIGHT);
else return; else return;
this.score += score;
} }
void run() { this.bigBang(this.width, this.width, 0.01); } void run() { this.bigBang(this.width, this.width, 0.01); }
@@ -90,10 +100,14 @@ class Game extends World {
class Board { class Board {
int sz; // The side length of the board grid square. int sz; // The side length of the board grid square.
Map<Coord, Cell> board; Map<Coord, Cell> board;
Random rand;
boolean boardChanged;
Board(int sz) { Board(int sz) {
this.sz = sz; this.sz = sz;
this.board = new HashMap<Coord, Cell>(); this.board = new HashMap<Coord, Cell>();
this.rand = new Random();
this.boardChanged = false;
} }
// Draw the board. // Draw the board.
@@ -130,9 +144,7 @@ class Board {
} }
// Set the cell at the coords. // Set the cell at the coords.
void set(Coord coord, Cell cell) { void set(Coord coord, Cell cell) { this.board.put(coord, cell); }
this.board.put(coord, cell);
}
// Try to move the cell at the coords to the coords. // Try to move the cell at the coords to the coords.
void tryCellMove(Coord coord, Coord dest) { void tryCellMove(Coord coord, Coord dest) {
@@ -142,47 +154,123 @@ class Board {
if (cell.isMoveable() && destCell.isReplaceable()) { if (cell.isMoveable() && destCell.isReplaceable()) {
this.set(dest, cell); this.set(dest, cell);
this.set(coord, new Space()); this.set(coord, new Space());
boardChanged = true; // It did move.
} }
} }
// Move cell as much as possible. // Try to combine two tiles if they have the same value
void fullCellMove(Coord coord, Move move) { int tryCombine(Coord source, Coord target) {
Cell sourceCell = this.get(source);
Cell targetCell = this.get(target);
// Check if both cells are tiles.
if (sourceCell instanceof Tile && targetCell instanceof Tile) {
Tile sourceTile = (Tile)sourceCell;
Tile targetTile = (Tile)targetCell;
// Check they've the same n and haven't yet been combined.
if (sourceTile.n == targetTile.n && !targetTile.flag) {
Tile newTile = new Tile(sourceTile.n * 2);
int score = sourceTile.n;
newTile.flag = true;
this.set(target, newTile);
this.set(source, new Space());
boardChanged = true;
return score;
}
}
return 0;
}
// Move cell as much as possible. Return score.
int fullCellMove(Coord coord, Move move) {
Cell cell = this.get(coord); Cell cell = this.get(coord);
Coord disp = Util.moveDisp(move); Coord disp = Util.moveDisp(move);
if (!cell.isMoveable()) return; if (!cell.isMoveable()) return 0;
for () { Coord current = coord;
this.tryCellMove(coord, coord.add(disp)); Coord next = current.add(disp);
}
// Keep moving until edge or a non-replaceable cell hit.
while (next.x >= 0 && next.x < this.sz && next.y >= 0 &&
next.y < this.sz && this.get(next).isReplaceable()) {
this.tryCellMove(current, next);
current = next;
next = current.add(disp);
} }
// Move in the given direction. // Check if can combine next tile.
void move(Move move) { if (next.x >= 0 && next.x < this.sz && next.y >= 0 && next.y < this.sz)
return this.tryCombine(current, next);
// Only generate new tile if changed.
if (boardChanged) this.randGen();
return 0;
}
// Move in the given direction. Returns the generated score.
int move(Move move) {
System.out.println("moving"); System.out.println("moving");
for (int i = 0; i < this.sz; i ++) {
this.moveLine(i, move); // Reset flags for all tiles and change tracker.
resetFlags();
int score = 0;
for (int i = 0; i < this.sz; i++) { score += this.moveLine(i, move); }
return score;
}
// Reset flags of all tiles.
void resetFlags() {
for (int x = 0; x < this.sz; x++)
for (int y = 0; y < this.sz; y++) {
Cell cell = this.get(new Coord(x, y));
if (cell instanceof Tile) ((Tile)cell).flag = false;
} }
} }
// Move a line of tiles. // Move a line of tiles.
void moveLine(int i, Move move) { int moveLine(int i, Move move) {
if (move.equals(Move.LEFT)) { int score = 0;
for (int x = 1; x < this.sz; x++) { if (move.equals(Move.LEFT))
this.fullCellMove(new Coord(x, i), move); for (int x = 1; x < this.sz; x++)
} score += this.fullCellMove(new Coord(x, i), move);
else if (move.equals(Move.RIGHT))
for (int x = this.sz - 2; x >= 0; x--)
score += this.fullCellMove(new Coord(x, i), move);
else if (move.equals(Move.DOWN))
for (int y = this.sz - 2; y >= 0; y--)
score += this.fullCellMove(new Coord(i, y), move);
else if (move.equals(Move.UP))
for (int y = 1; y < this.sz; y++)
score += this.fullCellMove(new Coord(i, y), move);
return score;
} }
else if (move.equals(Move.RIGHT)) { // Adds new tile (2 @ 80% chance, or 4 @ 20%) to random empty space on
for (int x = this.sz - 2; x >= 0; x--) { // board.
this.fullCellMove(new Coord(x, i), move); void randGen() {
} ArrayList<Coord> emptySpaces = new ArrayList<>();
for (int x = 0; x < this.sz; x++)
for (int y = 0; y < this.sz; y++) {
Coord coord = new Coord(x, y);
if (this.get(coord).isReplaceable()) emptySpaces.add(coord);
} }
else if (move.equals(Move.DOWN)) { if (!emptySpaces.isEmpty()) {
for (int y = this.sz - 2; y > 0; y--) { Coord chosenSpace =
this.tryCellMove(new Coord(i, y), new Coord(i , y + 1)); emptySpaces.get(rand.nextInt(emptySpaces.size()));
} int value = rand.nextDouble() < 0.8 ? 2 : 4;
this.set(chosenSpace, new Tile(value));
} }
} }
} }
@@ -210,8 +298,12 @@ abstract class Cell {
// A moveable tile on the board. // A moveable tile on the board.
class Tile extends Cell { class Tile extends Cell {
int n; int n;
boolean flag;
Tile(int n) { this.n = n; } Tile(int n) {
this.n = n;
this.flag = false;
}
Color col() { Color col() {
int r = (int)Math.min(255, 20 * (int)(Math.log(this.n) / Math.log(2))); int r = (int)Math.min(255, 20 * (int)(Math.log(this.n) / Math.log(2)));