Tetris/Java: Difference between revisions

From Rosetta Code
Content added Content deleted
m (turn previewOffsets into EnumMap)
(→‎{{header|Java}}: cleaned up code a bit, calculate preview offsets)
Line 1: Line 1:
==Code==
==Code==
{{works with|java|8}}
{{works with|java|8}}
<lang java>import java.awt.*;
<lang java>package tetris;

import java.awt.*;
import java.awt.event.*;
import java.awt.event.*;
import static java.lang.Math.*;
import static java.lang.String.format;
import static java.lang.String.format;
import java.util.Arrays;
import java.util.*;
import java.util.Random;
import java.util.EnumMap;
import javax.swing.*;
import javax.swing.*;
import static tetris.Config.*;


public class Tetris extends JPanel implements Runnable {
public class Tetris extends JPanel implements Runnable {
enum Dir {
right(1, 0), down(0, 1), left(-1, 0);

Dir(int x, int y) {
this.x = x;
this.y = y;
}
final int x, y;
};

public static final int EMPTY = -1;
public static final int EMPTY = -1;
public static final int BORDER = -2;
public static final int BORDER = -2;


Shape fallingShape;
Shape fallingShape;
Shape preSelectedShape;
Shape nextShape;


// position of falling shape
// position of falling shape
int fallingShapeRow;
int fallingShapeRow;
int fallingShapeCol;
int fallingShapeCol;

final int blockSize = Config.blockSize;
final int nRows = Config.nRows;
final int nCols = Config.nCols;
final int topMargin = Config.topMargin;
final int leftMargin = Config.leftMargin;


final int[][] grid = new int[nRows][nCols];
final int[][] grid = new int[nRows][nCols];
Line 33: Line 39:


public Tetris() {
public Tetris() {
setPreferredSize(Config.dim);
setPreferredSize(dim);
setBackground(Config.bgColor);
setBackground(bgColor);
setFocusable(true);
setFocusable(true);


Line 67: Line 73:


case KeyEvent.VK_LEFT:
case KeyEvent.VK_LEFT:
if (canMove(fallingShape, -1, 0))
if (canMove(fallingShape, Dir.left))
move(fallingShape, -1, 0);
move(fallingShape, Dir.left);
break;
break;


case KeyEvent.VK_RIGHT:
case KeyEvent.VK_RIGHT:
if (canMove(fallingShape, 1, 0))
if (canMove(fallingShape, Dir.right))
move(fallingShape, 1, 0);
move(fallingShape, Dir.right);
break;
break;


Line 79: Line 85:
if (!fastDown) {
if (!fastDown) {
fastDown = true;
fastDown = true;
while (canMove(fallingShape, 0, 1)) {
while (canMove(fallingShape, Dir.down)) {
move(fallingShape, 0, 1);
move(fallingShape, Dir.down);
repaint();
repaint();
}
}
Line 99: Line 105:
fallingShapeRow = 1;
fallingShapeRow = 1;
fallingShapeCol = 5;
fallingShapeCol = 5;
fallingShape = preSelectedShape;
fallingShape = nextShape;
Shape[] shapes = Shape.values();
Shape[] shapes = Shape.values();
preSelectedShape = shapes[rand.nextInt(shapes.length)];
nextShape = shapes[rand.nextInt(shapes.length)];
if (fallingShape != null)
if (fallingShape != null)
fallingShape.reset();
fallingShape.reset();
Line 139: Line 145:
try {
try {
Thread.sleep(scoreboard.getSpeed());
Thread.sleep(scoreboard.getSpeed());
} catch (InterruptedException ignored) {
} catch (InterruptedException e) {
return;
}
}


if (!scoreboard.isGameOver()) {
if (!scoreboard.isGameOver()) {
if (canMove(fallingShape, 0, 1)) {
if (canMove(fallingShape, Dir.down)) {
move(fallingShape, 0, 1);
move(fallingShape, Dir.down);
} else {
} else {
shapeHasLanded();
shapeHasLanded();
Line 154: Line 161:


void drawStartScreen(Graphics2D g) {
void drawStartScreen(Graphics2D g) {
g.setFont(Config.mainFont);
g.setFont(mainFont);


g.setColor(Config.titlebgColor);
g.setColor(titlebgColor);
g.fill(Config.titleRect);
g.fill(titleRect);
g.fill(Config.clickRect);
g.fill(clickRect);


g.setColor(Config.textColor);
g.setColor(textColor);
g.drawString("Tetris", Config.titleX, Config.titleY);
g.drawString("Tetris", titleX, titleY);


g.setFont(Config.smallFont);
g.setFont(smallFont);
g.drawString("click to start", Config.clickX, Config.clickY);
g.drawString("click to start", clickX, clickY);
}
}


void drawSquare(Graphics2D g, int colorIndex, int r, int c) {
void drawSquare(Graphics2D g, int colorIndex, int r, int c) {
g.setColor(Config.colors[colorIndex]);
g.setColor(colors[colorIndex]);
g.fillRect(leftMargin + c * blockSize, topMargin + r * blockSize,
g.fillRect(leftMargin + c * blockSize, topMargin + r * blockSize,
blockSize, blockSize);
blockSize, blockSize);


g.setStroke(Config.smallStroke);
g.setStroke(smallStroke);
g.setColor(Config.squareBorder);
g.setColor(squareBorder);
g.drawRect(leftMargin + c * blockSize, topMargin + r * blockSize,
g.drawRect(leftMargin + c * blockSize, topMargin + r * blockSize,
blockSize, blockSize);
blockSize, blockSize);
Line 180: Line 187:
void drawUI(Graphics2D g) {
void drawUI(Graphics2D g) {
// grid background
// grid background
g.setColor(Config.gridColor);
g.setColor(gridColor);
g.fill(Config.gridRect);
g.fill(gridRect);


// the blocks dropped in the grid
// the blocks dropped in the grid
Line 193: Line 200:


// the borders of grid and preview panel
// the borders of grid and preview panel
g.setStroke(Config.largeStroke);
g.setStroke(largeStroke);
g.setColor(Config.gridBorderColor);
g.setColor(gridBorderColor);
g.draw(Config.gridRect);
g.draw(gridRect);
g.draw(Config.previewRect);
g.draw(previewRect);


// scoreboard
// scoreboard
int x = Config.scoreX;
int x = scoreX;
int y = Config.scoreY;
int y = scoreY;
g.setColor(Config.textColor);
g.setColor(textColor);
g.setFont(Config.smallFont);
g.setFont(smallFont);
g.drawString(format("hiscore %6d", scoreboard.getTopscore()), x, y);
g.drawString(format("hiscore %6d", scoreboard.getTopscore()), x, y);
g.drawString(format("level %6d", scoreboard.getLevel()), x, y + 30);
g.drawString(format("level %6d", scoreboard.getLevel()), x, y + 30);
Line 209: Line 216:


// preview
// preview
int idx = preSelectedShape.ordinal();
int minX = 5, minY = 5, maxX = 0, maxY = 0;
for (int[] p : nextShape.pos) {
int offsetX = Config.previewOffsets.get(preSelectedShape)[0] + 15 * blockSize;
minX = min(minX, p[0]);
int offsetY = Config.previewOffsets.get(preSelectedShape)[1] + 2 * blockSize;
minY = min(minY, p[1]);

g.translate(offsetX, offsetY);
maxX = max(maxX, p[0]);
maxY = max(maxY, p[1]);

}
for (int[] p : preSelectedShape.shape)
drawSquare(g, idx, p[1], p[0]);
double cx = previewCenterX - ((minX + maxX + 1) / 2.0 * blockSize);
double cy = previewCenterY - ((minY + maxY + 1) / 2.0 * blockSize);


g.translate(-offsetX, -offsetY);
g.translate(cx, cy);
for (int[] p : nextShape.shape)
drawSquare(g, nextShape.ordinal(), p[1], p[0]);
g.translate(-cx, -cy);
}
}


Line 279: Line 290:
}
}


void move(Shape s, int xIncr, int yIncr) {
void move(Shape s, Dir dir) {
fallingShapeRow += yIncr;
fallingShapeRow += dir.y;
fallingShapeCol += xIncr;
fallingShapeCol += dir.x;
}
}


boolean canMove(Shape s, int xIncr, int yIncr) {
boolean canMove(Shape s, Dir dir) {
for (int[] p : s.pos) {
for (int[] p : s.pos) {
int newCol = fallingShapeCol + xIncr + p[0];
int newCol = fallingShapeCol + dir.x + p[0];
int newRow = fallingShapeRow + yIncr + p[1];
int newRow = fallingShapeRow + dir.y + p[1];
if (grid[newRow][newCol] != EMPTY)
if (grid[newRow][newCol] != EMPTY)
return false;
return false;
Line 348: Line 359:
});
});
}
}
}</lang>
}

<lang java>package tetris;


class Scoreboard {
class Scoreboard {
Line 455: Line 468:
return score;
return score;
}
}
}</lang>
}

<lang java>package tetris;


enum Shape {
enum Shape {
ZShape(new int[][]{{0, -1}, {0, 0}, {-1, 0}, {-1, 1}}),
ZShape(new int[][]{{0, -1}, {0, 0}, {-1, 0}, {-1, 1}}),
SShape(new int[][]{{0, -1}, {0, 0}, {1, 0}, {1, 1}}),
SShape(new int[][]{{0, -1}, {0, 0}, {1, 0}, {1, 1}}),
Straight(new int[][]{{0, -1}, {0, 0}, {0, 1}, {0, 2}}),
IShape(new int[][]{{0, -1}, {0, 0}, {0, 1}, {0, 2}}),
TShape(new int[][]{{-1, 0}, {0, 0}, {1, 0}, {0, 1}}),
TShape(new int[][]{{-1, 0}, {0, 0}, {1, 0}, {0, 1}}),
Square(new int[][]{{0, 0}, {1, 0}, {0, 1}, {1, 1}}),
Square(new int[][]{{0, 0}, {1, 0}, {0, 1}, {1, 1}}),
Line 479: Line 494:


final int[][] pos, shape;
final int[][] pos, shape;
}</lang>
}

<lang java>package tetris;

import java.awt.*;


final class Config {
final class Config {
final static Color[] colors = {Color.green, Color.red, Color.blue,
final static Color[] colors = {Color.green, Color.red, Color.blue,
Color.pink, Color.orange, Color.cyan, Color.magenta};
Color.pink, Color.orange, Color.cyan, Color.magenta};

// used for centering shapes in the preview pane
final static EnumMap<Shape, int[]> previewOffsets = new EnumMap<>(Shape.class);
static {
previewOffsets.put(Shape.ZShape, new int[]{16, 15});
previewOffsets.put(Shape.SShape, new int[]{-15, 15});
previewOffsets.put(Shape.Straight, new int[]{0, 0});
previewOffsets.put(Shape.TShape, new int[]{0, 0});
previewOffsets.put(Shape.Square, new int[]{-15, 5});
previewOffsets.put(Shape.LShape, new int[]{16, 15});
previewOffsets.put(Shape.JShape, new int[]{-15, 15});
}


final static Font mainFont = new Font("Monospaced", Font.BOLD, 48);
final static Font mainFont = new Font("Monospaced", Font.BOLD, 48);
Line 501: Line 508:


final static Dimension dim = new Dimension(640, 640);
final static Dimension dim = new Dimension(640, 640);

final static Rectangle gridRect = new Rectangle(46, 47, 308, 517);
final static Rectangle previewRect = new Rectangle(387, 47, 200, 200);
final static Rectangle titleRect = new Rectangle(100, 85, 252, 100);
final static Rectangle clickRect = new Rectangle(50, 375, 252, 40);


final static int blockSize = 30;
final static int blockSize = 30;
Line 513: Line 525:
final static int clickX = 120;
final static int clickX = 120;
final static int clickY = 400;
final static int clickY = 400;
final static int previewCenterX = 467;

final static Rectangle gridRect = new Rectangle(46, 47, 308, 517);
final static int previewCenterY = 97;
final static Rectangle previewRect = new Rectangle(387, 47, 200, 200);
final static Rectangle titleRect = new Rectangle(100, 85, 252, 100);
final static Rectangle clickRect = new Rectangle(50, 375, 252, 40);


final static Stroke largeStroke = new BasicStroke(5);
final static Stroke largeStroke = new BasicStroke(5);

Revision as of 14:58, 15 April 2016

Code

Works with: java version 8

<lang java>package tetris;

import java.awt.*; import java.awt.event.*; import static java.lang.Math.*; import static java.lang.String.format; import java.util.*; import javax.swing.*; import static tetris.Config.*;

public class Tetris extends JPanel implements Runnable {

   enum Dir {
       right(1, 0), down(0, 1), left(-1, 0);
       Dir(int x, int y) {
           this.x = x;
           this.y = y;
       }
       final int x, y;
   };
   public static final int EMPTY = -1;
   public static final int BORDER = -2;
   Shape fallingShape;
   Shape nextShape;
   // position of falling shape
   int fallingShapeRow;
   int fallingShapeCol;
   final int[][] grid = new int[nRows][nCols];
   Thread fallingThread;
   final Scoreboard scoreboard = new Scoreboard();
   static final Random rand = new Random();
   public Tetris() {
       setPreferredSize(dim);
       setBackground(bgColor);
       setFocusable(true);
       initGrid();
       selectShape();
       addMouseListener(new MouseAdapter() {
           @Override
           public void mousePressed(MouseEvent e) {
               if (scoreboard.isGameOver()) {
                   startNewGame();
                   repaint();
               }
           }
       });
       addKeyListener(new KeyAdapter() {
           boolean fastDown;
           @Override
           public void keyPressed(KeyEvent e) {
               if (scoreboard.isGameOver())
                   return;
               switch (e.getKeyCode()) {
                   case KeyEvent.VK_UP:
                       if (canRotate(fallingShape))
                           rotate(fallingShape);
                       break;
                   case KeyEvent.VK_LEFT:
                       if (canMove(fallingShape, Dir.left))
                           move(fallingShape, Dir.left);
                       break;
                   case KeyEvent.VK_RIGHT:
                       if (canMove(fallingShape, Dir.right))
                           move(fallingShape, Dir.right);
                       break;
                   case KeyEvent.VK_DOWN:
                       if (!fastDown) {
                           fastDown = true;
                           while (canMove(fallingShape, Dir.down)) {
                               move(fallingShape, Dir.down);
                               repaint();
                           }
                           shapeHasLanded();
                       }
               }
               repaint();
           }
           @Override
           public void keyReleased(KeyEvent e) {
               fastDown = false;
           }
       });
   }
   void selectShape() {
       fallingShapeRow = 1;
       fallingShapeCol = 5;
       fallingShape = nextShape;
       Shape[] shapes = Shape.values();
       nextShape = shapes[rand.nextInt(shapes.length)];
       if (fallingShape != null)
           fallingShape.reset();
   }
   void startNewGame() {
       stop();
       initGrid();
       selectShape();
       scoreboard.reset();
       (fallingThread = new Thread(this)).start();
   }
   void stop() {
       if (fallingThread != null) {
           Thread tmp = fallingThread;
           fallingThread = null;
           tmp.interrupt();
       }
   }
   void initGrid() {
       for (int r = 0; r < nRows; r++) {
           Arrays.fill(grid[r], EMPTY);
           for (int c = 0; c < nCols; c++) {
               if (c == 0 || c == nCols - 1 || r == nRows - 1)
                   grid[r][c] = BORDER;
           }
       }
   }
   @Override
   public void run() {
       while (Thread.currentThread() == fallingThread) {
           try {
               Thread.sleep(scoreboard.getSpeed());
           } catch (InterruptedException e) {
               return;
           }
           if (!scoreboard.isGameOver()) {
               if (canMove(fallingShape, Dir.down)) {
                   move(fallingShape, Dir.down);
               } else {
                   shapeHasLanded();
               }
               repaint();
           }
       }
   }
   void drawStartScreen(Graphics2D g) {
       g.setFont(mainFont);
       g.setColor(titlebgColor);
       g.fill(titleRect);
       g.fill(clickRect);
       g.setColor(textColor);
       g.drawString("Tetris", titleX, titleY);
       g.setFont(smallFont);
       g.drawString("click to start", clickX, clickY);
   }
   void drawSquare(Graphics2D g, int colorIndex, int r, int c) {
       g.setColor(colors[colorIndex]);
       g.fillRect(leftMargin + c * blockSize, topMargin + r * blockSize,
               blockSize, blockSize);
       g.setStroke(smallStroke);
       g.setColor(squareBorder);
       g.drawRect(leftMargin + c * blockSize, topMargin + r * blockSize,
               blockSize, blockSize);
   }
   void drawUI(Graphics2D g) {
       // grid background
       g.setColor(gridColor);
       g.fill(gridRect);
       // the blocks dropped in the grid
       for (int r = 0; r < nRows; r++) {
           for (int c = 0; c < nCols; c++) {
               int idx = grid[r][c];
               if (idx > EMPTY)
                   drawSquare(g, idx, r, c);
           }
       }
       // the borders of grid and preview panel
       g.setStroke(largeStroke);
       g.setColor(gridBorderColor);
       g.draw(gridRect);
       g.draw(previewRect);
       // scoreboard
       int x = scoreX;
       int y = scoreY;
       g.setColor(textColor);
       g.setFont(smallFont);
       g.drawString(format("hiscore  %6d", scoreboard.getTopscore()), x, y);
       g.drawString(format("level    %6d", scoreboard.getLevel()), x, y + 30);
       g.drawString(format("lines    %6d", scoreboard.getLines()), x, y + 60);
       g.drawString(format("score    %6d", scoreboard.getScore()), x, y + 90);
       // preview
       int minX = 5, minY = 5, maxX = 0, maxY = 0;
       for (int[] p : nextShape.pos) {
           minX = min(minX, p[0]);
           minY = min(minY, p[1]);
           maxX = max(maxX, p[0]);
           maxY = max(maxY, p[1]);
       }
       double cx = previewCenterX - ((minX + maxX + 1) / 2.0 * blockSize);
       double cy = previewCenterY - ((minY + maxY + 1) / 2.0 * blockSize);
       g.translate(cx, cy);
       for (int[] p : nextShape.shape)
           drawSquare(g, nextShape.ordinal(), p[1], p[0]);
       g.translate(-cx, -cy);
   }
   void drawFallingShape(Graphics2D g) {
       int idx = fallingShape.ordinal();
       for (int[] p : fallingShape.pos)
           drawSquare(g, idx, fallingShapeRow + p[1], fallingShapeCol + p[0]);
   }
   @Override
   public void paintComponent(Graphics gg) {
       super.paintComponent(gg);
       Graphics2D g = (Graphics2D) gg;
       g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
       drawUI(g);
       if (scoreboard.isGameOver()) {
           drawStartScreen(g);
       } else {
           drawFallingShape(g);
       }
   }
   boolean canRotate(Shape s) {
       if (s == Shape.Square)
           return false;
       int[][] pos = new int[4][2];
       for (int i = 0; i < pos.length; i++) {
           pos[i] = s.pos[i].clone();
       }
       for (int[] row : pos) {
           int tmp = row[0];
           row[0] = row[1];
           row[1] = -tmp;
       }
       for (int[] p : pos) {
           int newCol = fallingShapeCol + p[0];
           int newRow = fallingShapeRow + p[1];
           if (grid[newRow][newCol] != EMPTY) {
               return false;
           }
       }
       return true;
   }
   void rotate(Shape s) {
       if (s == Shape.Square)
           return;
       for (int[] row : s.pos) {
           int tmp = row[0];
           row[0] = row[1];
           row[1] = -tmp;
       }
   }
   void move(Shape s, Dir dir) {
       fallingShapeRow += dir.y;
       fallingShapeCol += dir.x;
   }
   boolean canMove(Shape s, Dir dir) {
       for (int[] p : s.pos) {
           int newCol = fallingShapeCol + dir.x + p[0];
           int newRow = fallingShapeRow + dir.y + p[1];
           if (grid[newRow][newCol] != EMPTY)
               return false;
       }
       return true;
   }
   void shapeHasLanded() {
       addShape(fallingShape);
       if (fallingShapeRow < 2) {
           scoreboard.setGameOver();
           scoreboard.setTopscore();
           stop();
       } else {
           scoreboard.addLines(removeLines());
       }
       selectShape();
   }
   int removeLines() {
       int count = 0;
       for (int r = 0; r < nRows - 1; r++) {
           for (int c = 1; c < nCols - 1; c++) {
               if (grid[r][c] == EMPTY)
                   break;
               if (c == nCols - 2) {
                   count++;
                   removeLine(r);
               }
           }
       }
       return count;
   }
   void removeLine(int line) {
       for (int c = 0; c < nCols; c++)
           grid[line][c] = EMPTY;
       for (int c = 0; c < nCols; c++) {
           for (int r = line; r > 0; r--)
               grid[r][c] = grid[r - 1][c];
       }
   }
   void addShape(Shape s) {
       for (int[] p : s.pos)
           grid[fallingShapeRow + p[1]][fallingShapeCol + p[0]] = s.ordinal();
   }
   public static void main(String[] args) {
       SwingUtilities.invokeLater(() -> {
           JFrame f = new JFrame();
           f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
           f.setTitle("Tetris");
           f.setResizable(false);
           f.add(new Tetris(), BorderLayout.CENTER);
           f.pack();
           f.setLocationRelativeTo(null);
           f.setVisible(true);
       });
   }

}</lang>

<lang java>package tetris;

class Scoreboard {

   static final int MAXLEVEL = 9;
   private int level;
   private int lines;
   private int score;
   private int topscore;
   private boolean gameOver = true;
   void reset() {
       setTopscore();
       level = lines = score = 0;
       gameOver = false;
   }
   void setGameOver() {
       gameOver = true;
   }
   boolean isGameOver() {
       return gameOver;
   }
   void setTopscore() {
       if (score > topscore)
           topscore = score;
   }
   int getTopscore() {
       return topscore;
   }
   int getSpeed() {
       switch (level) {
           case 0:
               return 700;
           case 1:
               return 600;
           case 2:
               return 500;
           case 3:
               return 400;
           case 4:
               return 350;
           case 5:
               return 300;
           case 6:
               return 250;
           case 7:
               return 200;
           case 8:
               return 150;
           case 9:
               return 100;
           default:
               return 100;
       }
   }
   void addScore(int sc) {
       score += sc;
   }
   void addLines(int line) {
       switch (line) {
           case 1:
               addScore(10);
               break;
           case 2:
               addScore(20);
               break;
           case 3:
               addScore(30);
               break;
           case 4:
               addScore(40);
               break;
           default:
               return;
       }
       lines += line;
       if (lines > 10)
           addLevel();
   }
   void addLevel() {
       lines %= 10;
       if (level < MAXLEVEL)
           level++;
   }
   int getLevel() {
       return level;
   }
   int getLines() {
       return lines;
   }
   int getScore() {
       return score;
   }

}</lang>

<lang java>package tetris;

enum Shape {

   ZShape(new int[][]{{0, -1}, {0, 0}, {-1, 0}, {-1, 1}}),
   SShape(new int[][]{{0, -1}, {0, 0}, {1, 0}, {1, 1}}),
   IShape(new int[][]{{0, -1}, {0, 0}, {0, 1}, {0, 2}}),
   TShape(new int[][]{{-1, 0}, {0, 0}, {1, 0}, {0, 1}}),
   Square(new int[][]{{0, 0}, {1, 0}, {0, 1}, {1, 1}}),
   LShape(new int[][]{{-1, -1}, {0, -1}, {0, 0}, {0, 1}}),
   JShape(new int[][]{{1, -1}, {0, -1}, {0, 0}, {0, 1}});
   private Shape(int[][] shape) {
       this.shape = shape;
       pos = new int[4][2];
       reset();
   }
   void reset() {
       for (int i = 0; i < pos.length; i++) {
           pos[i] = shape[i].clone();
       }
   }
   final int[][] pos, shape;

}</lang>

<lang java>package tetris;

import java.awt.*;

final class Config {

   final static Color[] colors = {Color.green, Color.red, Color.blue,
       Color.pink, Color.orange, Color.cyan, Color.magenta};
   final static Font mainFont = new Font("Monospaced", Font.BOLD, 48);
   final static Font smallFont = mainFont.deriveFont(Font.BOLD, 18);
   final static Dimension dim = new Dimension(640, 640);
   final static Rectangle gridRect = new Rectangle(46, 47, 308, 517);
   final static Rectangle previewRect = new Rectangle(387, 47, 200, 200);
   final static Rectangle titleRect = new Rectangle(100, 85, 252, 100);
   final static Rectangle clickRect = new Rectangle(50, 375, 252, 40);
   final static int blockSize = 30;
   final static int nRows = 18;
   final static int nCols = 12;
   final static int topMargin = 50;
   final static int leftMargin = 20;
   final static int scoreX = 400;
   final static int scoreY = 330;
   final static int titleX = 130;
   final static int titleY = 150;
   final static int clickX = 120;
   final static int clickY = 400;
   final static int previewCenterX = 467;
   final static int previewCenterY = 97;
   final static Stroke largeStroke = new BasicStroke(5);
   final static Stroke smallStroke = new BasicStroke(2);
   final static Color squareBorder = Color.white;
   final static Color titlebgColor = Color.white;
   final static Color textColor = Color.black;
   final static Color bgColor = new Color(0xDDEEFF);
   final static Color gridColor = new Color(0xBECFEA);
   final static Color gridBorderColor = new Color(0x7788AA);

}</lang>