From 16ee3e5a009380119cf44f3b0235f3e56aa382b5 Mon Sep 17 00:00:00 2001 From: Christopher Bohn <bohn@unl.edu> Date: Fri, 11 Oct 2024 16:38:33 -0500 Subject: [PATCH] Added starter code for Lab 8 --- sort_three_pairs/.gitignore | 62 +++ sort_three_pairs/pom.xml | 36 ++ .../sort_three_pairs/SortThreePairs.java | 77 ++++ .../sort_three_pairs/SortThreePairsTest.java | 167 +++++++++ tetris/.gitignore | 62 +++ tetris/logs/tetris.log | 0 tetris/pom.xml | 36 ++ .../edu/unl/cse/soft160/tetris/Tetris.java | 354 ++++++++++++++++++ 8 files changed, 794 insertions(+) create mode 100644 sort_three_pairs/.gitignore create mode 100644 sort_three_pairs/pom.xml create mode 100644 sort_three_pairs/src/main/java/edu/unl/cse/soft160/sort_three_pairs/SortThreePairs.java create mode 100644 sort_three_pairs/src/test/java/edu/unl/cse/soft160/sort_three_pairs/SortThreePairsTest.java create mode 100644 tetris/.gitignore create mode 100644 tetris/logs/tetris.log create mode 100644 tetris/pom.xml create mode 100644 tetris/src/main/java/edu/unl/cse/soft160/tetris/Tetris.java diff --git a/sort_three_pairs/.gitignore b/sort_three_pairs/.gitignore new file mode 100644 index 0000000..f35f60a --- /dev/null +++ b/sort_three_pairs/.gitignore @@ -0,0 +1,62 @@ +# Mac file finder metadata +.DS_Store +# Windows file metadata +._* +# Thumbnail image caches +Thumbs.db +ethumbs.db +# MS Office temporary file +~* +# Emacs backup file +*~ + +# Common +[Bb]in/ +[Bb]uild/ +[Oo]bj/ +[Oo]ut/ +[Tt]mp/ +[Xx]86/ +[Ii][Aa]32/ +[Xx]64/ +[Xx]86_64/ +[Xx]86-64/ +[Aa]rm +[Aa]32 +[Tt]32 +[Aa]64 +*.tmp +*.bak +*.bk +*.swp + +# Java files +*.class +javadoc/ + +# Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties + +# JetBrains (IntelliJ IDEA, PyCharm, etc) files +.idea/ +cmake-build-*/ +*.iml +*.iws +*.ipr + +# Eclipse files +.settings/ +.project +.classpath +.buildpath +.loadpath +.factorypath +local.properties diff --git a/sort_three_pairs/pom.xml b/sort_three_pairs/pom.xml new file mode 100644 index 0000000..0766594 --- /dev/null +++ b/sort_three_pairs/pom.xml @@ -0,0 +1,36 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>edu.unl.cse.soft160.sort_three_pairs</groupId> + <artifactId>sort_three_pairs</artifactId> + <packaging>jar</packaging> + <version>1.0-SNAPSHOT</version> + <name>sort_three_pairs</name> + <url>http://maven.apache.org</url> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>8</source> + <target>8</target> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.13</version> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/sort_three_pairs/src/main/java/edu/unl/cse/soft160/sort_three_pairs/SortThreePairs.java b/sort_three_pairs/src/main/java/edu/unl/cse/soft160/sort_three_pairs/SortThreePairs.java new file mode 100644 index 0000000..8e56ae3 --- /dev/null +++ b/sort_three_pairs/src/main/java/edu/unl/cse/soft160/sort_three_pairs/SortThreePairs.java @@ -0,0 +1,77 @@ +package edu.unl.cse.soft160.sort_three_pairs; + +public class SortThreePairs { + public static double readArgument(int position, String... arguments) { + return Double.parseDouble(arguments[position]); + } + + public static String formatPair(double x, double y) { + return "(" + x + ", " + y + ")"; + } + + public static int getPositionOfMinimum(double x0, double y0, double x1, double y1, double x2, double y2) { + int result = 0; + double xmin = x0; + double ymin = y0; + if (x1 < xmin || x1 == xmin && y1 < ymin) { + result = result + 1; + xmin = x1; + ymin = y1; + } + if (x2 < xmin || x2 == xmin && y2 < ymin) { + result = result + 1; + xmin = x2; + ymin = y2; + } + return result; + } + + public static void main(String... arguments) { + if (arguments.length != 6) { + System.err.println("Sorts three points by their x coordinates, breaking ties using y coordinates."); + System.err.println( + "Usage: java edu.unl.cse.soft160.sort_three_pairs.SortThreePairs [X0] [Y0] [X1] [Y1] [X2] [Y2]"); + System.exit(1); + } + double x0 = readArgument(0, arguments); + double y0 = readArgument(1, arguments); + double x1 = readArgument(2, arguments); + double y1 = readArgument(3, arguments); + double x2 = readArgument(4, arguments); + double y2 = readArgument(5, arguments); + double x3 = x0; + double y3 = y0; + // move the smallest pair to (x0, y0) + int firstPositionOfMinimum = getPositionOfMinimum(x0, y0, x1, y1, x2, y2); + switch (firstPositionOfMinimum) { + case 2: + x3 = x1; + x1 = x2; + x2 = x3; + y3 = y1; + y1 = y2; + y2 = y3; + case 1: + x3 = x0; + x0 = x1; + x1 = x3; + y3 = y0; + y0 = y1; + y1 = y3; + } + // move the second-smallest pair to (x1, y1) + int secondPositionOfMinimum = getPositionOfMinimum(Double.MAX_VALUE, Double.MAX_VALUE, x1, y1, x2, y2); + switch (secondPositionOfMinimum) { + case 2: + x3 = x1; + x1 = x2; + x2 = x3; + y3 = y1; + y1 = y2; + y2 = y3; + } + System.out.println(formatPair(x1, y1)); + System.out.println(formatPair(x2, y2)); + System.out.println(formatPair(x3, y3)); + } +} diff --git a/sort_three_pairs/src/test/java/edu/unl/cse/soft160/sort_three_pairs/SortThreePairsTest.java b/sort_three_pairs/src/test/java/edu/unl/cse/soft160/sort_three_pairs/SortThreePairsTest.java new file mode 100644 index 0000000..5c425e5 --- /dev/null +++ b/sort_three_pairs/src/test/java/edu/unl/cse/soft160/sort_three_pairs/SortThreePairsTest.java @@ -0,0 +1,167 @@ +package edu.unl.cse.soft160.sort_three_pairs; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.PrintStream; +import java.security.Permission; +import java.io.ByteArrayOutputStream; + +import static org.junit.Assert.*; + +public class SortThreePairsTest { + protected static String assemble(String... lines) { + return String.join("\n", lines) + "\n"; + } + + protected static String runMain(String... arguments) { + InputStream in = System.in; + PrintStream out = System.out; + System.setIn(new ByteArrayInputStream("".getBytes())); + ByteArrayOutputStream collector = new ByteArrayOutputStream(); + System.setOut(new PrintStream(collector)); + SortThreePairs.main(arguments); + System.setIn(in); + System.setOut(out); + return collector.toString(); + } + + @SuppressWarnings("serial") + protected static class ExitException extends SecurityException { + public final int status; + + public ExitException(int status) { + super("Exit with status " + status); + this.status = status; + } + } + + private static class TestingSecurityManager extends SecurityManager { + @Override + public void checkPermission(Permission perm) { + } + + @Override + public void checkPermission(Permission perm, Object context) { + } + + @Override + public void checkExit(int status) { + super.checkExit(status); + throw new ExitException(status); + } + } + + @Before + public void setUp() throws SecurityException { + System.setSecurityManager(new TestingSecurityManager()); + } + + @After + public void tearDown() throws SecurityException { + System.setSecurityManager(null); + } + + protected static String runMainForError(int expectedStatus, String... arguments) { + InputStream in = System.in; + PrintStream err = System.err; + System.setIn(new ByteArrayInputStream("".getBytes())); + ByteArrayOutputStream collector = new ByteArrayOutputStream(); + System.setErr(new PrintStream(collector)); + boolean exited = false; + try { + SortThreePairs.main(arguments); + } catch (ExitException expected) { + assertEquals(expectedStatus, expected.status); + exited = true; + } finally { + System.setIn(in); + System.setErr(err); + } + assertTrue(exited); + return collector.toString(); + } + + @Test + public void testZeros() { + assertEquals(assemble("(0.0, 0.0)", "(0.0, 0.0)", "(0.0, 0.0)"), + runMain("0", "0", "0", "0", "0", "0")); + } + + @Test + public void testAlreadySorted() { + assertEquals(assemble("(0.0, 0.0)", "(1.0, 1.0)", "(2.0, 2.0)"), + runMain("0", "0", "1", "1", "2", "2")); + } + + @Test + public void testReversed() { + assertEquals(assemble("(0.0, 0.0)", "(1.0, 1.0)", "(2.0, 2.0)"), + runMain("2", "2", "1", "1", "0", "0")); + } + + @Test + public void testJumbled() { + assertEquals(assemble("(0.0, 0.0)", "(1.0, 1.0)", "(2.0, 2.0)"), + runMain("1", "1", "2", "2", "0", "0")); + } + + @Test + public void testTieBreaking() { + assertEquals(assemble("(0.0, 1.0)", "(1.0, 2.0)", "(1.0, 3.0)"), + runMain("1", "3", "0", "1", "1", "2")); + } + + @Test + public void testMultipleTieBreaking() { + assertEquals(assemble("(0.0, 0.0)", "(0.0, 1.0)", "(0.0, 3.0)"), + runMain("0", "1", "0", "0", "0", "3")); + } + + @Test + public void testDuplicates() { + assertEquals(assemble("(1.0, 1.0)", "(1.0, 1.0)", "(1.0, 2.0)"), + runMain("1", "1", "1", "2", "1", "1")); + } + + @Test + public void testPermutation1() { + assertEquals(assemble("(0.0, 0.0)", "(1.0, 1.0)", "(2.0, 2.0)"), + runMain("0", "0", "2", "2", "1", "1")); + } + + @Test + public void testPermutation2() { + assertEquals(assemble("(0.0, 0.0)", "(1.0, 1.0)", "(2.0, 2.0)"), + runMain("2", "2", "0", "0", "1", "1")); + } + + @Test + public void testPermutation3() { + assertEquals(assemble("(0.0, 0.0)", "(1.0, 1.0)", "(2.0, 2.0)"), + runMain("2", "2", "1", "1", "0", "0")); + } + + @Test + public void testPermutation16() { + assertEquals(assemble("(0.0, 0.0)", "(1.0, 1.0)", "(2.0, 2.0)"), + runMain("1", "1", "2", "2", "0", "0")); + } + + @Test + public void testPermutation20() { + assertEquals(assemble("(0.0, 0.0)", "(1.0, 1.0)", "(2.0, 2.0)"), + runMain("1", "1", "0", "0", "2", "2")); + } + + @Test + public void testTooFewArguments() { + assertEquals( + assemble("Sorts three points by their x coordinates, breaking ties using y coordinates.", + "Usage: java edu.unl.cse.soft160.sort_three_pairs.SortThreePairs [X0] [Y0] [X1] [Y1] [X2] [Y2]"), + runMainForError(1, "0", "0", "1", "1", "2", "2", "3")); + } +} diff --git a/tetris/.gitignore b/tetris/.gitignore new file mode 100644 index 0000000..f35f60a --- /dev/null +++ b/tetris/.gitignore @@ -0,0 +1,62 @@ +# Mac file finder metadata +.DS_Store +# Windows file metadata +._* +# Thumbnail image caches +Thumbs.db +ethumbs.db +# MS Office temporary file +~* +# Emacs backup file +*~ + +# Common +[Bb]in/ +[Bb]uild/ +[Oo]bj/ +[Oo]ut/ +[Tt]mp/ +[Xx]86/ +[Ii][Aa]32/ +[Xx]64/ +[Xx]86_64/ +[Xx]86-64/ +[Aa]rm +[Aa]32 +[Tt]32 +[Aa]64 +*.tmp +*.bak +*.bk +*.swp + +# Java files +*.class +javadoc/ + +# Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties + +# JetBrains (IntelliJ IDEA, PyCharm, etc) files +.idea/ +cmake-build-*/ +*.iml +*.iws +*.ipr + +# Eclipse files +.settings/ +.project +.classpath +.buildpath +.loadpath +.factorypath +local.properties diff --git a/tetris/logs/tetris.log b/tetris/logs/tetris.log new file mode 100644 index 0000000..e69de29 diff --git a/tetris/pom.xml b/tetris/pom.xml new file mode 100644 index 0000000..47dd09f --- /dev/null +++ b/tetris/pom.xml @@ -0,0 +1,36 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>edu.unl.cse.soft160.tetris</groupId> + <artifactId>tetris</artifactId> + <packaging>jar</packaging> + <version>1.0-SNAPSHOT</version> + <name>tetris</name> + <url>http://maven.apache.org</url> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <build> + <plugins> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.1</version> + <configuration> + <source>8</source> + <target>8</target> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.13</version> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/tetris/src/main/java/edu/unl/cse/soft160/tetris/Tetris.java b/tetris/src/main/java/edu/unl/cse/soft160/tetris/Tetris.java new file mode 100644 index 0000000..4190fb1 --- /dev/null +++ b/tetris/src/main/java/edu/unl/cse/soft160/tetris/Tetris.java @@ -0,0 +1,354 @@ +package edu.unl.cse.soft160.tetris; + +import java.util.Collections; +import java.util.ArrayList; + +import java.awt.Font; +import java.awt.Color; +import java.awt.Graphics; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; + +public class Tetris extends JFrame { + private static final long serialVersionUID = -6851893161385783635L; + + protected static void log(String message) { + try { + Files.write(Paths.get("logs/tetris.log"), (message + "\n").getBytes(), StandardOpenOption.CREATE, + StandardOpenOption.APPEND); + } catch (IOException exception) { + exception.printStackTrace(); + } + } + + protected void logFailedMove(String moveName) { + log("Attempted move failed: " + moveName + " on shape " + shape + " (\"" + SHAPE_NAMES[shape] + "\")"); + } + + protected static int mod(int value, int modulus) { + int result = value % modulus; + return result < 0 ? result + modulus : result; + } + + protected static final int DEFAULT_SQUARE_SIZE = 60; // pixels + + protected static final Font TEXT_FONT = new Font(Font.SANS_SERIF, Font.BOLD, DEFAULT_SQUARE_SIZE / 2); + protected static final Color TEXT_COLOR = new Color(255, 255, 255, 127); + + protected static final String ROWS_CLEARED = "Rows cleared"; + protected static final String FINAL_SCORE = "Final score"; + protected static final String SCORE_SEPARATOR = ": "; + + protected static final int ROTATE_LEFT = KeyEvent.VK_DOWN; + protected static final int ROTATE_RIGHT = KeyEvent.VK_UP; + protected static final int SHIFT_LEFT = KeyEvent.VK_LEFT; + protected static final int SHIFT_RIGHT = KeyEvent.VK_RIGHT; + protected static final int DROP = KeyEvent.VK_SPACE; + protected static final int PAUSE = KeyEvent.VK_P; + protected static final int NEW_GAME = KeyEvent.VK_N; + + protected static final int WIDTH = 7; // squares + protected static final int HEIGHT = 11; // squares + protected static final int START_Y = 1; // squares from top + + protected static final Color EMPTY = new Color(0, 0, 0); + protected static final Color[] COLORS = { new Color(0, 0, 204), new Color(142, 0, 204), new Color(204, 204, 0), + new Color(204, 0, 204), new Color(0, 204, 204), new Color(0, 204, 0), new Color(204, 0, 0), }; + + protected static final String[] SHAPE_NAMES = { "O", "L", "J", "S", "Z", "T", "I", }; + protected static final int[] SHAPE_WIDTHS = { 2, 3, 3, 3, 3, 3, 4, }; + protected static final int[][][][] SHAPES = { + { // O + { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } }, }, + { // L + { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 2, 1 } }, { { 1, -1 }, { 1, 0 }, { 1, 1 }, { 0, 1 } }, + { { 0, -1 }, { 0, 0 }, { 1, 0 }, { 2, 0 } }, { { 1, -1 }, { 2, -1 }, { 1, 0 }, { 1, 1 } }, }, + { // J + { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 0, 1 } }, { { 0, -1 }, { 1, -1 }, { 1, 0 }, { 1, 1 } }, + { { 2, -1 }, { 0, 0 }, { 1, 0 }, { 2, 0 } }, { { 1, -1 }, { 1, 0 }, { 1, 1 }, { 2, 1 } }, }, + { // S + { { 0, 0 }, { 1, 0 }, { 1, 1 }, { 2, 1 } }, { { 1, 0 }, { 0, 1 }, { 1, 1 }, { 0, 2 } }, }, + { // Z + { { 1, 0 }, { 2, 0 }, { 0, 1 }, { 1, 1 } }, { { 0, 0 }, { 0, 1 }, { 1, 1 }, { 1, 2 } }, }, + { // T + { { 1, 0 }, { 0, 1 }, { 1, 1 }, { 2, 1 } }, { { 1, 0 }, { 1, 1 }, { 2, 1 }, { 1, 2 } }, + { { 0, 1 }, { 1, 1 }, { 2, 1 }, { 1, 2 } }, { { 1, 0 }, { 0, 1 }, { 1, 1 }, { 1, 2 } }, }, + { // I + { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 } }, { { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 } }, }, }; + + protected Color[][] board; + protected int score; + + protected boolean isOccupied(int x, int y) { + return x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT || board[x][y] != EMPTY; + } + + protected void emptyBoard() { + board = new Color[WIDTH][HEIGHT]; + for (int x = 0; x < WIDTH; ++x) { + for (int y = 0; y < HEIGHT; ++y) { + board[x][y] = EMPTY; + } + } + } + + protected void clearRows() { + int fallTo = HEIGHT - 1; + for (int y = HEIGHT; y-- > 0;) { + boolean full = true; + for (int x = 0; x < WIDTH; ++x) { + if (board[x][y] == EMPTY) { + full = false; + break; + } + } + if (full) { + ++score; + } else { + for (int x = 0; x < WIDTH; ++x) { + board[x][fallTo] = board[x][y]; + } + --fallTo; + } + } + for (int x = 0; x < WIDTH; ++x) { + for (int y = fallTo; y >= 0; --y) { + board[x][y] = EMPTY; + } + } + } + + protected long getDelay() { + return 20000 / (score + 50); + } + + protected ArrayList<Integer> currentShuffle = new ArrayList<Integer>(); + protected int currentShuffleIndex; + + protected int nextShape() { + if (currentShuffleIndex >= currentShuffle.size()) { + currentShuffleIndex = 0; + currentShuffle.clear(); + for (int i = 0; i < SHAPES.length; ++i) { + currentShuffle.add(i); + } + Collections.shuffle(currentShuffle); + } + return currentShuffle.get(currentShuffleIndex++); + } + + protected int shape; + protected int orientation; + protected int x; + protected int y; + + protected void createShape() { + shape = nextShape(); + orientation = 0; + x = (WIDTH - SHAPE_WIDTHS[shape]) / 2; + y = START_Y; + } + + protected int[][] getFallingSquares() { + int[][] result = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }; + int[][][] entry = SHAPES[shape]; + int[][] offsets = entry[mod(orientation, entry.length)]; + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 2; ++j) { + result[i][j] = (j == 0 ? x : y) + offsets[i][j]; + } + } + return result; + } + + protected boolean shapeCollides() { + for (int[] square : getFallingSquares()) { + if (isOccupied(square[0], square[1])) { + return true; + } + } + return false; + } + + protected void drawShape(Color color) { + for (int[] square : getFallingSquares()) { + board[square[0]][square[1]] = color; + } + } + + protected void placeShape() { + drawShape(COLORS[shape]); + JPanel panel = (JPanel)getContentPane(); + panel.paintImmediately(0, 0, panel.getWidth(), panel.getHeight()); + } + + protected void unplaceShape() { + drawShape(EMPTY); + } + + protected boolean playing = false; + protected boolean paused = false; + + protected boolean isPlaying() { + return playing && !paused; + } + + protected void togglePause() { + paused = !paused; + } + + protected void beginGame() { + emptyBoard(); + createShape(); + placeShape(); + score = 0; + playing = true; + paused = false; + } + + protected void endGame() { + playing = false; + } + + protected boolean maybeAdjustShape(int rotation, int dx, int dy) { + if (!isPlaying()) { + return true; + } + unplaceShape(); + orientation += rotation; + x += dx; + y += dy; + boolean collides = shapeCollides(); + if (collides) { + orientation -= rotation; + x -= dx; + y -= dy; + } + placeShape(); + return collides; + } + + protected boolean sinkShape() { + if (!isPlaying()) { + return true; + } + if (maybeAdjustShape(0, 0, 1)) { + clearRows(); + createShape(); + if (shapeCollides()) { + endGame(); + } else { + placeShape(); + } + return true; + } + return false; + } + + protected void dropShape() { + while (!sinkShape()) + ; + } + + protected void rotateShapeLeft() { + maybeAdjustShape(-1, 0, 0); + } + + protected void rotateShapeRight() { + maybeAdjustShape(1, 0, 0); + } + + protected void shiftShapeLeft() { + maybeAdjustShape(0, -1, 0); + } + + protected void shiftShapeRight() { + maybeAdjustShape(0, 1, 0); + } + + public Tetris(int width, int height) { + super("Tetris"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setSize(width, height); + setContentPane(new JPanel() { + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + int xScale = getWidth() / Tetris.WIDTH; + int yScale = getHeight() / Tetris.HEIGHT; + for (int x = 0; x < Tetris.WIDTH; ++x) { + for (int y = 0; y < Tetris.HEIGHT; ++y) { + graphics.setColor(board[x][y]); + graphics.fillRect(xScale * x, yScale * y, xScale, yScale); + } + } + String scoreString = (playing ? ROWS_CLEARED : FINAL_SCORE) + SCORE_SEPARATOR + String.valueOf(score); + graphics.setFont(TEXT_FONT); + graphics.setColor(TEXT_COLOR); + graphics.drawString(scoreString, (getWidth() - graphics.getFontMetrics().stringWidth(scoreString)) / 2, + (getHeight() / 2 - graphics.getFontMetrics().getHeight()) / 2); + } + }); + addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent event) { + switch (event.getKeyCode()) { + case ROTATE_LEFT: + rotateShapeLeft(); + break; + case ROTATE_RIGHT: + rotateShapeRight(); + break; + case SHIFT_LEFT: + shiftShapeLeft(); + break; + case SHIFT_RIGHT: + shiftShapeRight(); + break; + case DROP: + dropShape(); + break; + case PAUSE: + togglePause(); + break; + case NEW_GAME: + if (playing) { + endGame(); + } + beginGame(); + break; + } + } + + public void keyReleased(KeyEvent e) { + } + + public void keyTyped(KeyEvent e) { + } + }); + new Thread() { + @Override + public void run() { + while (true) { + try { + Thread.sleep(getDelay()); + sinkShape(); + } catch (InterruptedException ignored) { + } + } + } + }.start(); + } + + public static void main(String... arguments) { + Tetris tetris = new Tetris(WIDTH * DEFAULT_SQUARE_SIZE, HEIGHT * DEFAULT_SQUARE_SIZE); + tetris.setVisible(true); + tetris.beginGame(); + } +} -- GitLab