Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -3,7 +3,7 @@ package chess;
|
||||
import javalib.worldimages.*;
|
||||
|
||||
// The piece types.
|
||||
enum PieceType { PAWN, ROOK, KNIGHT, BISHOP, POPE, QUEEN, KING }
|
||||
enum PieceType { PAWN, ROOK, KNIGHT, BISHOP, POPE, QUEEN, KING, SINGER }
|
||||
|
||||
// A chess piece.
|
||||
abstract class Piece {
|
||||
@@ -14,6 +14,7 @@ abstract class Piece {
|
||||
this.type = type;
|
||||
this.col = col;
|
||||
}
|
||||
|
||||
WorldImage draw() { return new EmptyImage(); };
|
||||
}
|
||||
|
||||
|
303
twentyfortyeight/Main2.java
Normal file
303
twentyfortyeight/Main2.java
Normal file
@@ -0,0 +1,303 @@
|
||||
package twentyfortyeight;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import javalib.impworld.*;
|
||||
import javalib.worldimages.*;
|
||||
import tester.Tester;
|
||||
|
||||
class ImgUtil {
|
||||
static Color color(int n) {
|
||||
int r = (int)Math.min(255, 20 * (int)(Math.log(n) / Math.log(2)));
|
||||
|
||||
return new Color(r, r / 2 + 80, r / 3 + 20);
|
||||
}
|
||||
|
||||
// Create a tile image for a number.
|
||||
static WorldImage mktile(int n) {
|
||||
return new OverlayImage(
|
||||
new TextImage(
|
||||
String.valueOf(n), Game.SCALE / 2, FontStyle.BOLD, Color.BLACK
|
||||
),
|
||||
new RectangleImage(
|
||||
Game.SCALE, Game.SCALE, OutlineMode.SOLID, ImgUtil.color(n)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Create a fee space image.
|
||||
static WorldImage mkfree() {
|
||||
return new RectangleImage(
|
||||
Game.SCALE, Game.SCALE, OutlineMode.OUTLINE, Color.GRAY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// A game of 2048.
|
||||
class Game extends World {
|
||||
static int SCALE = 100;
|
||||
|
||||
int score;
|
||||
Grid grid;
|
||||
Random rand;
|
||||
WorldScene scene;
|
||||
int w, h; // The pixel widths and heights.
|
||||
|
||||
// Convenience constructor for init with default settings.
|
||||
Game() {
|
||||
this.grid = new Grid(4, 4);
|
||||
this.score = 0;
|
||||
this.rand = new Random();
|
||||
this.w = this.grid.w * SCALE;
|
||||
this.h = this.grid.h * SCALE;
|
||||
this.scene = new WorldScene(this.w, this.h);
|
||||
}
|
||||
|
||||
// Convenience constructor for init with custom settings.
|
||||
Game(int w, int h) {
|
||||
this.grid = new Grid(w, h);
|
||||
this.score = 0;
|
||||
this.rand = new Random();
|
||||
this.w = this.grid.w * SCALE;
|
||||
this.h = this.grid.h * SCALE;
|
||||
this.scene = new WorldScene(this.grid.w, this.grid.h);
|
||||
}
|
||||
|
||||
void launchGame() {
|
||||
this.bigBang(this.w, this.h, 0.01);
|
||||
this.grid.set(0, 0, 2).set(0, 2, 2);
|
||||
}
|
||||
|
||||
public WorldScene makeScene() {
|
||||
this.scene = this.getEmptyScene();
|
||||
this.draw();
|
||||
return this.scene;
|
||||
}
|
||||
|
||||
public void onKeyEvent(String key) {
|
||||
if (key.equals("left") || key.equals("h")) this.grid.mv(0);
|
||||
else if (key.equals("down") || key.equals("j")) this.grid.mv(1);
|
||||
else if (key.equals("up") || key.equals("k")) this.grid.mv(2);
|
||||
else if (key.equals("right") || key.equals("l")) this.grid.mv(3);
|
||||
else return; // Don't draw or add tiles if bad key pressed.
|
||||
|
||||
this.draw();
|
||||
|
||||
List<Integer> frees = this.grid.freeCellIdxs();
|
||||
// Add tiles
|
||||
this.grid.buf.set(frees.get(this.rand.nextInt(frees.size())), 2);
|
||||
|
||||
this.draw();
|
||||
}
|
||||
|
||||
// Draw current game state.
|
||||
void draw() { this.scene = this.grid.render(); }
|
||||
}
|
||||
|
||||
// The grid in which the game is played.
|
||||
class Grid {
|
||||
int w; // The width of the grid.
|
||||
int h; // The height of the grid.
|
||||
ArrayList<Integer> buf; // The buffer containing the tiles.
|
||||
int sz; // The size of the buffer -- always w * h.
|
||||
|
||||
Grid(int w, int h) {
|
||||
if (w < 1 || h < 1)
|
||||
throw new IllegalArgumentException("Can't make grid that small.");
|
||||
|
||||
this.w = w;
|
||||
this.h = h;
|
||||
this.sz = this.w * this.h;
|
||||
this.buf = new ArrayList<>(this.sz);
|
||||
|
||||
// Fill with zeros.
|
||||
for (int i = 0; i < this.sz; this.buf.add(i++ * 0));
|
||||
}
|
||||
|
||||
// Get the indexes of all "free" cells -- those whose value in buf is 0,
|
||||
// and are represented as blank tile.
|
||||
List<Integer> freeCellIdxs() {
|
||||
List<Integer> free = new ArrayList<>();
|
||||
for (int i = 0; i < this.sz; i++)
|
||||
if (this.buf.get(i) == 0 && free.add(i)) continue;
|
||||
|
||||
return free;
|
||||
}
|
||||
|
||||
// Get the indexes of all "unfree" cells -- those whose value in buf is not
|
||||
// 0, and represent a used tile.
|
||||
/*
|
||||
List<Integer> unfreeCellIdxs() {
|
||||
List<Integer> unfree = new ArrayList<>();
|
||||
for (int i = 0; i < this.sz; i++)
|
||||
if (this.buf.get(i) != 0 && unfree.add(i)) continue;
|
||||
|
||||
return unfree;
|
||||
}
|
||||
*/
|
||||
|
||||
// Set the tile at the coords.
|
||||
Grid set(int x, int y, int v) {
|
||||
this.buf.set(this.where(x, y), v);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Get the index for the coord.
|
||||
int where(int x, int y) { return this.w * y + x; }
|
||||
|
||||
// Get the value at the coords.
|
||||
int get(int x, int y) { return this.buf.get(this.w * y + x); }
|
||||
|
||||
// Get the x coord for an index.
|
||||
int ix(int i) { return i % this.h; }
|
||||
|
||||
// Get the y coord for an index.
|
||||
int iy(int i) { return i % this.w; }
|
||||
|
||||
void mv(int d) {
|
||||
// For each row / col.
|
||||
for (int i = 0; i < (d % 3 == 0 ? this.h : this.w); i++) {
|
||||
while (this.lnMv(i, d));
|
||||
this.squish(i, d);
|
||||
while (this.lnMv(i, d));
|
||||
}
|
||||
}
|
||||
|
||||
// Get the ith row.
|
||||
List<Integer> getRow(int i) {
|
||||
return this.buf.subList(
|
||||
this.where(0, i), this.where(this.w - 1, i) + 1
|
||||
);
|
||||
}
|
||||
|
||||
// Get the ith col. A bit more complex.
|
||||
List<Integer> getCol(int i) {
|
||||
if (i < 0 || i >= this.w) throw new IndexOutOfBoundsException("No.");
|
||||
|
||||
return new ArrayList<Integer>() {
|
||||
public Integer get(int j) {
|
||||
if (j < 0 || j >= h) throw new IndexOutOfBoundsException("No.");
|
||||
return buf.get(w * j + i);
|
||||
}
|
||||
|
||||
public Integer set(int j, Integer val) {
|
||||
if (j < 0 || j >= h) throw new IndexOutOfBoundsException("No.");
|
||||
int prv = buf.get(w * j + i);
|
||||
buf.set(w * j + i, val);
|
||||
return prv;
|
||||
}
|
||||
|
||||
public int size() { return h; }
|
||||
};
|
||||
}
|
||||
|
||||
// Get the line.
|
||||
List<Integer> getLn(int i, int d) {
|
||||
return d == 0 ? this.getRow(i)
|
||||
: d == 1 ? this.getCol(i).reversed()
|
||||
: d == 2 ? this.getCol(i)
|
||||
: this.getRow(i).reversed();
|
||||
}
|
||||
|
||||
// Move the specified line in the specified direction once. If there is a
|
||||
// combination, return false. If there are no more moves possible, return
|
||||
// false.
|
||||
boolean lnMv(int i, int d) {
|
||||
List<Integer> ln = getLn(i, d);
|
||||
|
||||
int c = 0; // Moves made in line.
|
||||
for (int j = 1; j < ln.size(); j++) {
|
||||
if (ln.get(j - 1) == 0 && ln.get(j) != 0) {
|
||||
ln.set(j - 1, ln.get(j));
|
||||
ln.set(j, 0);
|
||||
} else c++;
|
||||
}
|
||||
|
||||
// If nothing has been done, give up.
|
||||
if (c == ln.size() - 1) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Squish like tiles together.
|
||||
void squish(int i, int d) {
|
||||
List<Integer> ln = getLn(i, d);
|
||||
for (int j = 0; j < ln.size() - 1; j++) {
|
||||
if (ln.get(j) != 0 && ln.get(j) == ln.get(j + 1)) {
|
||||
ln.set(j, 2 * ln.get(j));
|
||||
ln.set(j + 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render the grid.
|
||||
WorldScene render() {
|
||||
WorldScene bg =
|
||||
new WorldScene(Game.SCALE * this.w, Game.SCALE * this.h);
|
||||
for (int i = 0; i < this.w; i++)
|
||||
for (int j = 0; j < this.h; j++) {
|
||||
int n = this.get(i, j);
|
||||
int coordx = i * Game.SCALE + Game.SCALE / 2;
|
||||
int coordy = j * Game.SCALE + Game.SCALE / 2;
|
||||
if (n == 0) bg.placeImageXY(ImgUtil.mkfree(), coordx, coordy);
|
||||
else bg.placeImageXY(ImgUtil.mktile(n), coordx, coordy);
|
||||
}
|
||||
|
||||
return bg;
|
||||
}
|
||||
}
|
||||
|
||||
class Examples {
|
||||
Grid verySmall, small, oblong, regular;
|
||||
|
||||
Game game;
|
||||
|
||||
void init() {
|
||||
verySmall = new Grid(1, 1);
|
||||
small = new Grid(2, 2);
|
||||
oblong = new Grid(1, 3);
|
||||
regular = new Grid(4, 4);
|
||||
}
|
||||
|
||||
void testGridFreeCellIdxs(Tester t) {
|
||||
init();
|
||||
t.checkExpect(
|
||||
small.freeCellIdxs(), new ArrayList<Integer>(List.of(0, 1, 2, 3))
|
||||
);
|
||||
t.checkExpect(
|
||||
verySmall.freeCellIdxs(), new ArrayList<Integer>(List.of(0))
|
||||
);
|
||||
t.checkExpect(
|
||||
oblong.freeCellIdxs(), new ArrayList<Integer>(List.of(0, 1, 2))
|
||||
);
|
||||
}
|
||||
|
||||
void testGridSet(Tester t) {
|
||||
init();
|
||||
small.set(0, 0, 1);
|
||||
t.checkExpect(small.freeCellIdxs(), new ArrayList<>(List.of(1, 2, 3)));
|
||||
small.set(1, 1, 1);
|
||||
t.checkExpect(small.freeCellIdxs(), new ArrayList<>(List.of(1, 2)));
|
||||
}
|
||||
|
||||
void testRegular(Tester t) {
|
||||
init();
|
||||
regular.set(1, 0, 16)
|
||||
.set(2, 0, 16)
|
||||
.set(3, 0, 32)
|
||||
.set(0, 1, 4)
|
||||
.set(1, 1, 4)
|
||||
.set(4, 1, 2);
|
||||
|
||||
t.checkExpect(regular.get(1, 0), 16);
|
||||
t.checkExpect(regular.get(0, 0), 0);
|
||||
t.checkExpect(regular.get(3, 3), 0);
|
||||
}
|
||||
|
||||
void testGame(Tester t) {
|
||||
game = new Game(2, 2);
|
||||
game.launchGame();
|
||||
}
|
||||
}
|
@@ -3,81 +3,79 @@ package twentyfortyeight;
|
||||
import java.awt.Color;
|
||||
import java.time.format.TextStyle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import javalib.impworld.*;
|
||||
import javalib.worldimages.*;
|
||||
import tester.Tester;
|
||||
|
||||
class ImgUtil {
|
||||
static Color color(int n) {
|
||||
int r = (int)Math.min(255, 20 * (int)(Math.log(n) / Math.log(2)));
|
||||
class Examples {
|
||||
void testRun(Tester t) {
|
||||
Game game = new Game();
|
||||
game.board.board.put(new Coord(0, 0), new Tile(2));
|
||||
game.board.board.put(new Coord(0, 1), new Tile(20));
|
||||
game.board.board.put(new Coord(0, 2), new Tile(200));
|
||||
game.board.board.put(new Coord(0, 3), new Tile(2000));
|
||||
game.run();
|
||||
}
|
||||
}
|
||||
|
||||
return new Color(r, r / 2 + 80, r / 3 + 20);
|
||||
// Config constants.
|
||||
class Util {
|
||||
// Game scale.
|
||||
static int scale = 256;
|
||||
|
||||
// Default 2048 game board width.
|
||||
static int defaultWidth = 4;
|
||||
|
||||
// Calculate an appropriate font size for a number.
|
||||
static double fontSize(int n) {
|
||||
// Start scaling numbers down once they pass 2 digits.
|
||||
double x = 0.73 * Math.pow(Math.ceil(Math.log(n) / Math.log(100)), -1);
|
||||
return Util.scale * x;
|
||||
}
|
||||
|
||||
// Create a tile image for a number.
|
||||
static WorldImage mktile(int n) {
|
||||
return new OverlayImage(
|
||||
new TextImage(
|
||||
String.valueOf(n), Game.SCALE / 2, FontStyle.BOLD, Color.BLACK
|
||||
),
|
||||
new RectangleImage(
|
||||
Game.SCALE, Game.SCALE, OutlineMode.SOLID, ImgUtil.color(n)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Create a fee space image.
|
||||
static WorldImage mkfree() {
|
||||
return new RectangleImage(
|
||||
Game.SCALE, Game.SCALE, OutlineMode.OUTLINE, Color.GRAY
|
||||
);
|
||||
// Convert a movement to a displacement vector.
|
||||
Coord moveDisp(Move move) {
|
||||
if (move.equals(Move.LEFT)) return new Coord(-1, 0);
|
||||
else if (move.equals(Move.DOWN)) return new Coord(0, -1);
|
||||
else if (move.equals(Move.UP)) return new Coord(0, 1);
|
||||
else return new Coord(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// A game of 2048.
|
||||
class Game extends World {
|
||||
static int SCALE = 100;
|
||||
int score; // The current score.
|
||||
int sz; // The size of the grid.
|
||||
int width; // The width of the image in pixels.
|
||||
Board board; // The game board.
|
||||
|
||||
int score;
|
||||
Grid grid;
|
||||
Random rand;
|
||||
WorldScene scene;
|
||||
int w, h; // The pixel widths and heights.
|
||||
Game(int score, int sz, int width, Board board) {
|
||||
this.score = score;
|
||||
this.sz = sz;
|
||||
this.width = this.sz * Util.scale;
|
||||
this.board = board;
|
||||
}
|
||||
|
||||
// Convenience constructor for init with default settings.
|
||||
// Convenince constructor with default parameters.
|
||||
Game() {
|
||||
this.grid = new Grid(4, 4);
|
||||
this.score = 0;
|
||||
this.rand = new Random();
|
||||
this.w = this.grid.w * SCALE;
|
||||
this.h = this.grid.h * SCALE;
|
||||
this.scene = new WorldScene(this.w, this.h);
|
||||
}
|
||||
|
||||
// Convenience constructor for init with custom settings.
|
||||
Game(int w, int h) {
|
||||
this.grid = new Grid(w, h);
|
||||
this.score = 0;
|
||||
this.rand = new Random();
|
||||
this.w = this.grid.w * SCALE;
|
||||
this.h = this.grid.h * SCALE;
|
||||
this.scene = new WorldScene(this.grid.w, this.grid.h);
|
||||
}
|
||||
|
||||
void launchGame() {
|
||||
this.bigBang(this.w, this.h, 0.01);
|
||||
this.grid.set(0, 0, 2).set(0, 2, 2);
|
||||
this.sz = Util.defaultWidth;
|
||||
this.width = this.sz * Util.scale;
|
||||
this.board = new Board(this.sz);
|
||||
}
|
||||
|
||||
public WorldScene makeScene() {
|
||||
this.scene = this.getEmptyScene();
|
||||
this.draw();
|
||||
return this.scene;
|
||||
WorldScene scene = new WorldScene(this.width, this.width);
|
||||
scene.placeImageXY(this.board.draw(), this.width / 2, this.width / 2);
|
||||
return scene;
|
||||
}
|
||||
|
||||
public void onKeyEvent(String key) {
|
||||
<<<<<<< HEAD
|
||||
int mv;
|
||||
if (key.equals("left") || key.equals("h")) mv = 0;
|
||||
else if (key.equals("down") || key.equals("j")) mv = 1;
|
||||
@@ -107,38 +105,45 @@ class Game extends World {
|
||||
100, 20
|
||||
);
|
||||
}
|
||||
=======
|
||||
if (key.equals("left") || key.equals("h")) this.board.move(Move.LEFT);
|
||||
else if (key.equals("down") || key.equals("j"))
|
||||
this.board.move(Move.DOWN);
|
||||
else if (key.equals("up") || key.equals("k")) this.board.move(Move.UP);
|
||||
else if (key.equals("right") || key.equals("l"))
|
||||
this.board.move(Move.RIGHT);
|
||||
else return;
|
||||
}
|
||||
|
||||
void run() { this.bigBang(this.width, this.width); }
|
||||
>>>>>>> origin/main
|
||||
}
|
||||
|
||||
// The grid in which the game is played.
|
||||
class Grid {
|
||||
int w; // The width of the grid.
|
||||
int h; // The height of the grid.
|
||||
ArrayList<Integer> buf; // The buffer containing the tiles.
|
||||
int sz; // The size of the buffer -- always w * h.
|
||||
// The possible movements.
|
||||
enum Move { UP, LEFT, RIGHT, DOWN }
|
||||
|
||||
Grid(int w, int h) {
|
||||
if (w < 1 || h < 1)
|
||||
throw new IllegalArgumentException("Can't make grid that small.");
|
||||
// The board on which the game is played.
|
||||
class Board {
|
||||
int sz; // The side length of the board grid square.
|
||||
Map<Coord, Cell> board;
|
||||
|
||||
this.w = w;
|
||||
this.h = h;
|
||||
this.sz = this.w * this.h;
|
||||
this.buf = new ArrayList<>(this.sz);
|
||||
|
||||
// Fill with zeros.
|
||||
for (int i = 0; i < this.sz; this.buf.add(i++ * 0));
|
||||
Board(int sz) {
|
||||
this.sz = sz;
|
||||
this.board = new HashMap<Coord, Cell>();
|
||||
}
|
||||
|
||||
// Get the indexes of all "free" cells -- those whose value in buf is 0,
|
||||
// and are represented as blank tile.
|
||||
List<Integer> freeCellIdxs() {
|
||||
List<Integer> free = new ArrayList<>();
|
||||
for (int i = 0; i < this.sz; i++)
|
||||
if (this.buf.get(i) == 0 && free.add(i)) continue;
|
||||
// Draw the board.
|
||||
WorldImage draw() {
|
||||
ArrayList<WorldImage> rows = new ArrayList<>();
|
||||
|
||||
return free;
|
||||
}
|
||||
// For each row.
|
||||
for (int y = 0; y < this.sz; y++) {
|
||||
ArrayList<WorldImage> row = new ArrayList<>();
|
||||
// For each element in the row.
|
||||
for (int x = 0; x < this.sz; x++)
|
||||
row.add(this.get(new Coord(x, y)).draw());
|
||||
|
||||
<<<<<<< HEAD
|
||||
// Set the tile at the coords.
|
||||
Grid set(int x, int y, int v) {
|
||||
this.buf.set(this.where(x, y), v);
|
||||
@@ -168,35 +173,31 @@ class Grid {
|
||||
|
||||
return add;
|
||||
}
|
||||
=======
|
||||
// Add row to the list.
|
||||
rows.add(row.stream().reduce(
|
||||
new EmptyImage(),
|
||||
(cell1, cell2) -> new BesideImage(cell1, cell2)
|
||||
));
|
||||
}
|
||||
>>>>>>> origin/main
|
||||
|
||||
// Get the ith row.
|
||||
List<Integer> getRow(int i) {
|
||||
return this.buf.subList(
|
||||
this.where(0, i), this.where(this.w - 1, i) + 1
|
||||
// Collapse rows into single image.
|
||||
return rows.stream().reduce(
|
||||
new EmptyImage(), (row1, row2) -> new AboveImage(row1, row2)
|
||||
);
|
||||
}
|
||||
|
||||
// Get the ith col. A bit more complex.
|
||||
List<Integer> getCol(int i) {
|
||||
if (i < 0 || i >= this.w) throw new IndexOutOfBoundsException("No.");
|
||||
// Get the cell at the coords.
|
||||
Cell get(Coord coord) {
|
||||
Cell gotten = this.board.get(coord);
|
||||
|
||||
return new ArrayList<Integer>() {
|
||||
public Integer get(int j) {
|
||||
if (j < 0 || j >= h) throw new IndexOutOfBoundsException("No.");
|
||||
return buf.get(w * j + i);
|
||||
}
|
||||
|
||||
public Integer set(int j, Integer val) {
|
||||
if (j < 0 || j >= h) throw new IndexOutOfBoundsException("No.");
|
||||
int prv = buf.get(w * j + i);
|
||||
buf.set(w * j + i, val);
|
||||
return prv;
|
||||
}
|
||||
|
||||
public int size() { return h; }
|
||||
};
|
||||
// Check if there's something there, otherwise return empty space.
|
||||
if (gotten == null) return new Space();
|
||||
else return gotten;
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
// Get the line.
|
||||
List<Integer> getLn(int i, int d) {
|
||||
return d == 0 ? this.getRow(i)
|
||||
@@ -234,46 +235,53 @@ class Grid {
|
||||
ln.set(j, 2 * ln.get(j));
|
||||
ln.set(j + 1, 0);
|
||||
add += ln.get(j);
|
||||
=======
|
||||
// Move in the given direction.
|
||||
void move(Move move) {
|
||||
for (int x = 0; x < this.sz; x++) {
|
||||
for (int y = 0; y < this.sz; y++) {
|
||||
// Copy logic from old code here.
|
||||
Cell cell = this.get(new Coord(x, y));
|
||||
>>>>>>> origin/main
|
||||
}
|
||||
}
|
||||
|
||||
return add;
|
||||
}
|
||||
}
|
||||
|
||||
// Render the grid.
|
||||
WorldScene render() {
|
||||
WorldScene bg =
|
||||
new WorldScene(Game.SCALE * this.w, Game.SCALE * this.h);
|
||||
for (int i = 0; i < this.w; i++)
|
||||
for (int j = 0; j < this.h; j++) {
|
||||
int n = this.get(i, j);
|
||||
int coordx = i * Game.SCALE + Game.SCALE / 2;
|
||||
int coordy = j * Game.SCALE + Game.SCALE / 2;
|
||||
if (n == 0) bg.placeImageXY(ImgUtil.mkfree(), coordx, coordy);
|
||||
else bg.placeImageXY(ImgUtil.mktile(n), coordx, coordy);
|
||||
}
|
||||
// A cell on the board.
|
||||
abstract class Cell {
|
||||
// Generate the color of the tile.
|
||||
Color col() { return Color.PINK; }
|
||||
|
||||
return bg;
|
||||
// Draw the cell.
|
||||
WorldImage draw() {
|
||||
return new RectangleImage(
|
||||
Util.scale, Util.scale, OutlineMode.SOLID, this.col()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Examples {
|
||||
Grid verySmall, small, oblong, regular;
|
||||
// A moveable tile on the board.
|
||||
class Tile extends Cell {
|
||||
int n;
|
||||
|
||||
Game game;
|
||||
Tile(int n) { this.n = n; }
|
||||
|
||||
void init() {
|
||||
verySmall = new Grid(1, 1);
|
||||
small = new Grid(2, 2);
|
||||
oblong = new Grid(1, 3);
|
||||
regular = new Grid(4, 4);
|
||||
Color col() {
|
||||
int r = (int)Math.min(255, 20 * (int)(Math.log(this.n) / Math.log(2)));
|
||||
return new Color(r, r / 2 + 80, r / 3 + 20);
|
||||
}
|
||||
|
||||
void testGridFreeCellIdxs(Tester t) {
|
||||
init();
|
||||
t.checkExpect(
|
||||
small.freeCellIdxs(), new ArrayList<Integer>(List.of(0, 1, 2, 3))
|
||||
WorldImage draw() {
|
||||
return new OverlayImage(
|
||||
new TextImage(
|
||||
String.valueOf(this.n), Util.fontSize(this.n), Color.BLACK
|
||||
),
|
||||
super.draw()
|
||||
);
|
||||
<<<<<<< HEAD
|
||||
t.checkExpect(
|
||||
verySmall.freeCellIdxs(), new ArrayList<Integer>(List.of(0))
|
||||
);
|
||||
@@ -307,5 +315,33 @@ class Examples {
|
||||
void testGame(Tester t) {
|
||||
game = new Game(4, 4);
|
||||
game.launchGame();
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
}
|
||||
}
|
||||
|
||||
// An empty space on the board.
|
||||
class Space extends Cell {
|
||||
Color col() { return Color.LIGHT_GRAY; }
|
||||
}
|
||||
|
||||
// Board coordinates.
|
||||
class Coord {
|
||||
int x, y;
|
||||
|
||||
Coord(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
Coord add(Coord that) { return that.addHelper(this.x, this.y); }
|
||||
|
||||
Coord addHelper(int x, int y) { return new Coord(this.x + x, this.y + y); }
|
||||
|
||||
public boolean equals(Object that) {
|
||||
if (!(that instanceof Coord)) return false;
|
||||
else return ((Coord)that).x == this.x && ((Coord)that).y == this.y;
|
||||
}
|
||||
|
||||
public int hashCode() { return 31 * Integer.hashCode(this.x + this.y); }
|
||||
}
|
||||
|
Reference in New Issue
Block a user