Compare commits

...

4 Commits

Author SHA1 Message Date
Jacob Signorovitch
31e83a33fb halshadshafds 2025-05-28 08:44:53 -04:00
Jacob Signorovitch
473a3f7cb8 hahhfasd 2025-05-28 08:17:46 -04:00
Jacob Signorovitch
5b8ce38723 h 2025-05-28 08:04:52 -04:00
Jacob Signorovitch
83e80a48e2 h 2025-05-28 08:02:46 -04:00
3 changed files with 230 additions and 51 deletions

View File

@@ -57,15 +57,13 @@ class Sudoku {
for (int[] col : transposed)
if (isRepetitive(col)) return false;
/*
// Check there'ren't any repeats in a square.
for (int i = 0; i < 9; i++) {
int[] square = new int[3][3];
for (int j = i; j < i + 3; j++) {
// for (int k = i; k < i + 3; k++) { square[i][k] }
}
}
*/
// Check all 3x3 squares.
for (int squareRow = 0; squareRow < 3; squareRow++) {
for (int squareCol = 0; squareCol < 3; squareCol++) {
if (squareCheck(puz, squareRow * 3, squareCol * 3))
return false;
}
}
return true;
}
@@ -91,6 +89,20 @@ class Sudoku {
return transposed;
}
// Check if a 3x3 square repeats values.
static boolean squareCheck(int[][] puz, int startRow, int startCol) {
HashMap<Integer, Boolean> seen = new HashMap<>();
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++) {
int val = puz[startRow + i][startCol + j];
if (seen.containsKey(val)) return true;
else seen.put(val, true);
}
return false;
}
}
class Examples {
@@ -166,6 +178,7 @@ class Examples {
t.checkExpect(Sudoku.solved(testPuz6), false);
t.checkExpect(Sudoku.solved(testPuz7), false);
}
void testSieve(Tester t) {
Sieve sieve = new Sieve(29);
t.checkExpect(sieve.hasNext(), true);

View File

@@ -2,7 +2,6 @@ package streams;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;

View File

@@ -4,6 +4,7 @@ import java.awt.Color;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import javalib.impworld.*;
import javalib.worldimages.*;
import tester.Tester;
@@ -11,10 +12,6 @@ import tester.Tester;
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(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();
}
}
@@ -50,6 +47,7 @@ class Game extends World {
int sz; // The size of the grid.
int width; // The width of the image in pixels.
Board board; // The game board.
boolean gameOver;
Game(int score, int sz, int width, Board board) {
this.score = score;
@@ -64,23 +62,74 @@ class Game extends World {
this.sz = Util.defaultWidth;
this.width = this.sz * Util.scale;
this.board = new Board(this.sz);
this.gameOver = false;
this.board.randGen();
this.board.randGen();
}
Game(int w) {
this.score = 0;
this.sz = w;
this.width = this.sz * Util.scale;
this.board = new Board(this.sz);
this.gameOver = false;
this.board.randGen();
this.board.randGen();
}
public WorldScene makeScene() {
WorldScene scene = new WorldScene(this.width, this.width);
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
);
// Display loss message.
if (this.gameOver)
scene.placeImageXY(
new TextImage(
"Game over. Score: " + this.score + ". [R] to restart.", 20,
Color.RED
),
this.width / 2, this.width / 2
);
return scene;
}
public void onKeyEvent(String key) {
System.out.println("got key" + key);
if (key.equals("left") || key.equals("h")) this.board.move(Move.LEFT);
// If game over, ignore movement keys.
if (this.gameOver) {
// Restart game with 'r'.
if (key.equals("r")) {
this.score = 0;
this.board = new Board(this.sz);
this.gameOver = false;
this.board.randGen();
this.board.randGen();
}
return;
}
int score = 0;
if (key.equals("left") || key.equals("h"))
score = 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);
score = this.board.move(Move.DOWN);
else if (key.equals("up") || key.equals("k"))
score = this.board.move(Move.UP);
else if (key.equals("right") || key.equals("l"))
this.board.move(Move.RIGHT);
score = this.board.move(Move.RIGHT);
else return;
this.score += score;
// Check if game over after move.
this.gameOver = this.board.isGameOver();
}
void run() { this.bigBang(this.width, this.width, 0.01); }
@@ -90,10 +139,14 @@ class Game extends World {
class Board {
int sz; // The side length of the board grid square.
Map<Coord, Cell> board;
Random rand;
boolean boardChanged;
Board(int sz) {
this.sz = sz;
this.board = new HashMap<Coord, Cell>();
this.rand = new Random();
this.boardChanged = false;
}
// Draw the board.
@@ -130,9 +183,7 @@ class Board {
}
// Set the cell at the coords.
void set(Coord coord, Cell cell) {
this.board.put(coord, cell);
}
void set(Coord coord, Cell cell) { this.board.put(coord, cell); }
// Try to move the cell at the coords to the coords.
void tryCellMove(Coord coord, Coord dest) {
@@ -142,48 +193,160 @@ class Board {
if (cell.isMoveable() && destCell.isReplaceable()) {
this.set(dest, cell);
this.set(coord, new Space());
boardChanged = true; // It did move.
}
}
// Move cell as much as possible.
void fullCellMove(Coord coord, Move move) {
// Try to combine two tiles.
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);
Coord disp = Util.moveDisp(move);
if (!cell.isMoveable()) return;
if (!cell.isMoveable()) return 0;
for () {
this.tryCellMove(coord, coord.add(disp));
Coord current = coord;
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);
}
// Check if can combine next tile.
if (next.x >= 0 && next.x < this.sz && next.y >= 0 && next.y < this.sz)
return this.tryCombine(current, next);
return 0;
}
// Move in the given direction.
void move(Move move) {
System.out.println("moving");
for (int i = 0; i < this.sz; i ++) {
this.moveLine(i, move);
}
// Move in the given direction. Returns the generated score.
int move(Move move) {
// Reset flags for all tiles and change tracker.
resetFlags();
this.boardChanged = false;
int score = 0;
for (int i = 0; i < this.sz; i++) score += this.moveLine(i, move);
if (this.boardChanged) this.randGen();
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.
void moveLine(int i, Move move) {
if (move.equals(Move.LEFT)) {
for (int x = 1; x < this.sz; x++) {
this.fullCellMove(new Coord(x, i), move);
int moveLine(int i, Move move) {
int score = 0;
if (move.equals(Move.LEFT))
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;
}
// Adds new tile (2 @ 80% chance, or 4 @ 20%) to random empty space on
// board.
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);
}
if (!emptySpaces.isEmpty()) {
Coord chosenSpace =
emptySpaces.get(rand.nextInt(emptySpaces.size()));
int value = rand.nextDouble() < 0.8 ? 2 : 4;
this.set(chosenSpace, new Tile(value));
}
}
// Check if game over.
boolean isGameOver() {
for (int x = 0; x < this.sz; x++)
for (int y = 0; y < this.sz; y++)
if (this.get(new Coord(x, y)).isReplaceable())
return false; // There's an empty space, game not over.
// Check if any adjacent tiles can be combined.
for (int x = 0; x < this.sz; x++) {
for (int y = 0; y < this.sz; y++) {
Cell current = this.get(new Coord(x, y));
// Skip if not tile.
if (!(current instanceof Tile)) continue;
Tile currentTile = (Tile)current;
if (x < this.sz - 1) {
Cell right = this.get(new Coord(x + 1, y));
if (right instanceof Tile &&
((Tile)right).n == currentTile.n) {
return false; // Can combine horizontally.
}
}
if (y < this.sz - 1) {
Cell bottom = this.get(new Coord(x, y + 1));
if (bottom instanceof Tile &&
((Tile)bottom).n == currentTile.n) {
return false; // Can combine vertically.
}
}
}
}
else if (move.equals(Move.RIGHT)) {
for (int x = this.sz - 2; x >= 0; x--) {
this.fullCellMove(new Coord(x, i), move);
}
}
else if (move.equals(Move.DOWN)) {
for (int y = this.sz - 2; y > 0; y--) {
this.tryCellMove(new Coord(i, y), new Coord(i , y + 1));
}
}
return true; // Game over.
}
}
@@ -204,14 +367,18 @@ abstract class Cell {
// Is this moveable?
boolean isMoveable() { return false; }
boolean isReplaceable() { return false;}
boolean isReplaceable() { return false; }
}
// A moveable tile on the board.
class Tile extends Cell {
int n;
boolean flag;
Tile(int n) { this.n = n; }
Tile(int n) {
this.n = n;
this.flag = false;
}
Color col() {
int r = (int)Math.min(255, 20 * (int)(Math.log(this.n) / Math.log(2)));
@@ -227,8 +394,8 @@ class Tile extends Cell {
);
}
boolean isMoveable() { return true;}
boolean isReplaceable() {return false;}
boolean isMoveable() { return true; }
boolean isReplaceable() { return false; }
}
// An empty space on the board.