这是一个使用java swing实现的小游戏,和之前的贪吃蛇以及五子棋类似,闲来无聊的作品,不过,这次的作品相较于前两个游戏在代码水平有很大的提高,结论是,编程能力的提高是写更多的代码写出来的,不是看一系列的书籍看出来的。
代码部分经过一天的清明节假期,只是雏形渐渐出现,还有很多的细节需要推敲。比如,消行的这个问题,遍历数据,原则上从下边一行开始消除,也就是逆向,然后将上边的内容依次下移。
如果使用二维数组的遍历,需要每次都要访问全局数据,鄙人采用了传入局部数据方法。
使用了工厂设计模式,对多种形状做继承处理。
提取一些简易的数据结构,作为辅助类(工具类使用)。
实际的开发工作所用时间从周末到周三的晚上,大约四天的功夫,当然不是说完整的四天都在编写代码。毕竟还要上班,只是闲暇的时间来做这部分工作。
关于上边提到的问题的解决,采用的方式是循环扫描,这种最简单的方案,如果有一行扫描需要消行,在消行之后需要重新进行扫描,这是最关键的一点。
代码部分少不了对诸多方块图形的描述,也就是需要很多枚举类型的参与,并且需要对某一类图形的子状态作进一步的描述,也就是需要一种“继承”的枚举类型,参照了《Java编程思想》关于枚举这一部分的讲述。
关于图形的移动,需要判定是否可以作相应的移动,包括向左,向右,以及向下,判断需要考虑俄罗斯方块最外边的框,以及现有的图形是否对能移动的图形有遮挡。
图形的类使用了继承的方法,也就是使用工厂的模式。
关于图形子状态的相互转换,使用了策略模式,也就对不同的图形采用差异化的变形方法。
图形子状态的改变可以考虑设计模式的职责链,或者状态模式,本代码没有采用相应的实现。
完整的代码可以看文章最后的博客地址。
代码还不完整,只能实现一些基本的功能,并且没有经过完整,全面的测试,另外俄罗斯方块的所有形状还没有添加完全。希望读者斧正。感谢有你。
代码已经完整了。剩下的就是重构代码。加入一些新的图形极其子状态。
Teris.java
package com.game;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import com.game.shape.Shape;
import com.game.state.ShapeEnum;
import com.game.util.Enums;
import com.game.util.SameRow;
import com.game.util.Utils;
public class Teris extends JFrame {
/** * This is the main GUI of Teris, which the code executed. */
private static final long serialVersionUID = 1L;
private int row;
private int column;
private JPanel mainframe;
private JPanel control;
private BorderLayout border;
private FlowLayout flow;
private JButton start;
private JButton exit;
private TerisPanel board;
private List<Point> data;
private ActionListener actionlistener;
private KeyAdapter keylistener;
private ActionListener timelistener;
private Timer time;
private int speed;
private JTextField score;
private Shape shape;
private int limitTop;
private SameRow sameRow;
public Teris(String title, int row, int column) {
super(title);
this.row = row;
this.column = column;
initial();
setSize(300, (int) (300 * this.row * 1.0 / this.column));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationByPlatform(true);
this.setVisible(true);
this.requestFocus();
}
private void initial() {
data = new ArrayList<Point>();
speed = 1000;
limitTop = row;
sameRow = new SameRow();
loadShape();
createComponent();
layOut();
listeners();
}
private void createComponent() {
start = new JButton("Start");
exit = new JButton("Exit");
mainframe = new JPanel();
control = new JPanel();
border = new BorderLayout();
board = new TerisPanel(data, row, column);
flow = new FlowLayout();
score = new JTextField();
score.setEditable(false);
}
private void layOut() {
getContentPane().add(mainframe);
mainframe.setLayout(border);
mainframe.add(control, BorderLayout.NORTH);
control.setLayout(flow);
control.add(start);
control.add(score);
control.add(exit);
score.setPreferredSize(new Dimension(70, 30));
score.setText("0");
mainframe.add(board, BorderLayout.CENTER);
}
private void listeners() {
/* * action listener for the button of start)(for start) and end(for exit) */
actionlistener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command.equals("Exit")) {
System.exit(0);
} else if (command.equals("Start")) {
time.start();
requestFocus();
}
}
};
/* * The keyboard listener to direction key(the key in here is you can not * get the reverse direction) and speed key(w for high speed, s for low * speed). */
keylistener = new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_LEFT) {
shiftLeft();
} else if (code == KeyEvent.VK_RIGHT) {
shiftRight();
} else if (code == KeyEvent.VK_UP) {
speed += 100;
time.setDelay(speed);
System.out.println(speed);
} else if (code == KeyEvent.VK_DOWN) {
speed -= 100;
speed = 0 == speed ? 100 : speed;
time.setDelay(speed);
System.out.println(speed);
} else if (code == KeyEvent.VK_SPACE) {
changeShape();
} else {
}
}
};
timelistener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
move();
repaint();
}
};
/** * here set the timer to the speed of 1 grid/sec */
time = new Timer(speed, timelistener);
this.addKeyListener(keylistener);
start.addActionListener(actionlistener);
exit.addActionListener(actionlistener);
}
protected boolean shiftLeft() {
shape.ShiftLeft();
boolean canShiftLeft = !Utils.hasSamePoint(data);
if (!canShiftLeft) {
shape.ShiftRight();
}
return canShiftLeft;
}
protected boolean shiftRight() {
shape.ShiftRight();
boolean canShiftRight = !Utils.hasSamePoint(data);
if (!canShiftRight) {
shape.ShiftLeft();
}
return canShiftRight;
}
protected boolean changeShape() {
try {
shape.changeShape();
} catch (Exception e) {
e.printStackTrace();
}
boolean canChangeShape = !Utils.hasSamePoint(data);
for (Point item : shape.getData()) {
if (item.x >= row || item.y >= column || item.x < 0 || item.y < 0) {
canChangeShape = false;
System.out.println("Care");
break;
}
}
if (!canChangeShape) {
try {
shape.unChangeShape();
} catch (Exception e) {
e.printStackTrace();
}
}
return canChangeShape;
}
private void move() {
if (isAlive()) {
if (isMoveFinished()) {
updateLimitTop();
updateScore(); // 消方块
loadShape();
speed = 1000;
time.setDelay(speed);
} else {
shape.ShiftDown();
}
} else {
time.stop();
// JOptionPane.showMessageDialog(this, "You Lose! Come on!");
int choice = JOptionPane.showConfirmDialog(this, "try again!", "Message", JOptionPane.YES_NO_OPTION);
if (JOptionPane.YES_OPTION == choice) {
/** * ready for the restart the game. */
score.setText("0");
}
}
}
private void updateScore() {
int counter = 0;
for (int i = row - 1; i >= 0; i--) {
for (Point item : data) {
if (i == item.x) {
counter++;
}
}
if (column == counter) {
sameRow.setRow(i);
data.removeIf(sameRow);
score.setText(String.valueOf(Integer.valueOf(score.getText()) + 1));
moveTopToBelow(i);
/* * here need to Re-scanning the row of i to be sure whether * there is exist another row can collapsed. */
i++;
}
counter = 0;
}
}
private void updateLimitTop() {
for (Point item : data) {
limitTop = Math.min(limitTop, item.x);
}
}
private void moveTopToBelow(int i) {
for (Point item : data) {
if (item.x < i) {
item.x++;
}
}
}
/* * This method should check whether the game can go on. same with * canShiftDown function. */
private boolean isAlive() {
return limitTop > 0;
}
/* * This method will check whether single move is overd. no data overlapped. */
private boolean isMoveFinished() {
boolean flag = false;
if (shape.ShiftDown()) {
flag = Utils.hasSamePoint(data);
shape.ShiftUp();
} else {
flag = true;
}
return flag;
}
private void loadShape() {
shape = Utils.makeShape(Enums.random(ShapeEnum.class), row, column);
int shiftToCenter = column / 2 - shape.getCenterOfShape();
for (int i = 0; i < shiftToCenter; i++) {
shape.ShiftRight();
}
data.addAll(shape.getData());
}
public static void main(String[] args) {
new Teris("test", 50, 25);
}
}
TerisPanel.java
package com.game;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.util.List;
import javax.swing.JPanel;
/** * in this file draw the background and the moving snake. */
public class TerisPanel extends JPanel {
/** * */
private static final long serialVersionUID = 1L;
private int row;
private int column;
private List<Point> data;
public TerisPanel() {
this(null, 20, 10);
}
public TerisPanel(List<Point> data, int row, int column) {
if (data == null) {
try {
throw new Exception("The List<Point> should not be null, which can be empty.");
} catch (Exception e) {
e.printStackTrace();
}
}
this.data = data;
this.row = row;
this.column = column;
}
@Override
public void paint(Graphics g) {
Graphics2D gg = (Graphics2D) g;
int squre = (this.getWidth() - 50) / column;
/** * from the point (25, 10) draw the game's background. */
/* * below draw the background gird. */
int x = 25;
int y = 10;
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
gg.setStroke(new BasicStroke(0.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f,
new float[] { 5f, 5f }, 0f));
gg.setColor(Color.yellow);
gg.drawRect(x + j * squre, y + i * squre, squre, squre);
}
}
/* * draw the russia squre which meaningful to game. */
for (Point item : data) {
gg.setColor(Color.GREEN);
gg.fillRect(x + item.y * squre, y + item.x * squre, squre, squre);
}
gg.setStroke(new BasicStroke(5f));
gg.setColor(Color.blue);
gg.drawRect(24, 9, squre * column + 2, squre * row + 2);
gg.dispose();
}
}
Shape.java
package com.game.shape;
import java.awt.Point;
import java.util.List;
public abstract class Shape {
protected List<Point> data;
private int limitLeft;
private int limitRight;
private int limitBelow;
private int limitTop;
private int row;
private int column;
private int centerOfShape;
public Shape(List<Point> data, int row, int column) {
this.data = data;
this.row = row;
this.column = column;
initialLimits();
getLimits();
}
public void initialLimits() {
limitLeft = column;
limitRight = -1;
limitBelow = -1;
limitTop = row;
}
public void getLimits() {
int sum = 0;
for (Point item : data) {
limitLeft = Math.min(limitLeft, item.y);
limitRight = Math.max(limitRight, item.y);
limitTop = Math.min(limitTop, item.x);
limitBelow = Math.max(limitBelow, item.x);
sum += item.y;
}
centerOfShape = sum / data.size();
}
public boolean ShiftLeft() {
if (0 == limitLeft) {
return false;
}
limitLeft--;
limitRight--;
for (Point item : data) {
item.y = item.y - 1;
}
return true;
}
public boolean ShiftRight() {
if (column - 1 == limitRight) {
return false;
}
limitLeft++;
limitRight++;
for (Point item : data) {
item.y = item.y + 1;
}
return true;
}
public boolean ShiftDown() {
if (row - 1 == limitBelow) {
return false;
}
limitTop++;
limitBelow++;
for (Point item : data) {
item.x = item.x + 1;
}
return true;
}
public boolean ShiftUp() {
limitTop--;
limitBelow--;
for (Point item : data) {
item.x = item.x - 1;
}
return true;
}
public List<Point> getData() {
return data;
}
public void setData(List<Point> data) {
this.data = data;
}
public int getCenterOfShape() {
return centerOfShape;
}
abstract public boolean changeShape() throws Exception;
abstract public boolean unChangeShape() throws Exception;
}
SqureShape.java
package com.game.shape;
import java.awt.Point;
import java.util.List;
public class SqureShape extends Shape {
/* * The shape is below: ** ** */
public SqureShape(List<Point> data, int row, int column) {
super(data, row, column);
}
@Override
public boolean changeShape() {
return true;
}
@Override
public boolean unChangeShape() {
return true;
}
}
LongShape.java
package com.game.shape;
import java.awt.Point;
import java.util.List;
import com.game.state.ShapeInterface.LONG;
public class LongShape extends Shape {
private LONG state;
public LongShape(List<Point> data, int row, int column) {
super(data, row, column);
state = LONG.HORIZONTAL;
}
@Override
public boolean changeShape() throws Exception {
Point point = data.get(2);
switch (state) {
case HORIZONTAL:
data.get(0).setLocation(point.x - 2, point.y);
data.get(1).setLocation(point.x - 1, point.y);
data.get(3).setLocation(point.x + 1, point.y);
state = LONG.VERTICAL;
break;
case VERTICAL:
data.get(0).setLocation(point.x, point.y - 2);
data.get(1).setLocation(point.x, point.y - 1);
data.get(3).setLocation(point.x, point.y + 1);
state = LONG.HORIZONTAL;
break;
default:
throw new Exception("sth wrong here LongShape");
}
initialLimits();
getLimits();
return true;
}
@Override
public boolean unChangeShape() throws Exception {
try {
changeShape();
return false;
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
}
TriangleShape.java
package com.game.shape;
import java.awt.Point;
import java.util.List;
import com.game.state.ShapeInterface.TRIANGLE;
public class TriangleShape extends Shape {
private TRIANGLE state;
public TriangleShape(List<Point> data, int row, int column) {
super(data, row, column);
state = TRIANGLE.TOP;
}
@Override
public boolean changeShape() throws Exception {
Point point = data.get(2);
switch (state) {
case TOP:
data.get(0).setLocation(point.x, point.y + 1);
data.get(1).setLocation(point.x - 1, point.y);
data.get(3).setLocation(point.x + 1, point.y);
state = TRIANGLE.RIGHT;
break;
case RIGHT:
data.get(0).setLocation(point.x + 1, point.y);
data.get(1).setLocation(point.x, point.y + 1);
data.get(3).setLocation(point.x, point.y - 1);
state = TRIANGLE.DOWN;
break;
case DOWN:
data.get(0).setLocation(point.x, point.y - 1);
data.get(1).setLocation(point.x + 1, point.y);
data.get(3).setLocation(point.x - 1, point.y);
state = TRIANGLE.LEFT;
break;
case LEFT:
data.get(0).setLocation(point.x - 1, point.y);
data.get(1).setLocation(point.x, point.y - 1);
data.get(3).setLocation(point.x, point.y + 1);
state = TRIANGLE.TOP;
break;
default:
throw new Exception("sth wrong here : TriangleShape");
}
initialLimits();
getLimits();
return true;
}
@Override
public boolean unChangeShape() throws Exception {
Point point = data.get(2);
switch (state) {
case TOP:
data.get(0).setLocation(point.x, point.y - 1);
data.get(1).setLocation(point.x + 1, point.y);
data.get(3).setLocation(point.x - 1, point.y);
state = TRIANGLE.LEFT;
break;
case RIGHT:
data.get(0).setLocation(point.x - 1, point.y);
data.get(1).setLocation(point.x, point.y - 1);
data.get(3).setLocation(point.x, point.y + 1);
state = TRIANGLE.TOP;
break;
case DOWN:
data.get(0).setLocation(point.x, point.y + 1);
data.get(1).setLocation(point.x - 1, point.y + 1);
data.get(3).setLocation(point.x + 1, point.y - 1);
state = TRIANGLE.RIGHT;
break;
case LEFT:
data.get(0).setLocation(point.x + 1, point.y);
data.get(1).setLocation(point.x, point.y + 1);
data.get(3).setLocation(point.x, point.y - 1);
state = TRIANGLE.DOWN;
break;
default:
throw new Exception("sth wrong here : TriangleShape");
}
initialLimits();
getLimits();
return true;
}
}
SevenShape.java
package com.game.shape;
import java.awt.Point;
import java.util.List;
import com.game.state.ShapeInterface.SEVEN;
public class SevenShape extends Shape {
private SEVEN state;
public SevenShape(List<Point> data, int row, int column) {
super(data, row, column);
state = SEVEN.LEFT;
}
@Override
public boolean changeShape() throws Exception {
Point point = data.get(2);
switch (state) {
case LEFT:
data.get(0).setLocation(point.x - 1, point.y + 1);
data.get(1).setLocation(point.x, point.y + 1);
data.get(3).setLocation(point.x, point.y - 1);
state = SEVEN.TOP;
break;
case TOP:
data.get(0).setLocation(point.x + 1, point.y + 1);
data.get(1).setLocation(point.x + 1, point.y);
data.get(3).setLocation(point.x - 1, point.y);
state = SEVEN.RIGHT;
break;
case RIGHT:
data.get(0).setLocation(point.x + 1, point.y - 1);
data.get(1).setLocation(point.x, point.y - 1);
data.get(3).setLocation(point.x, point.y + 1);
state = SEVEN.DOWN;
break;
case DOWN:
data.get(0).setLocation(point.x - 1, point.y - 1);
data.get(1).setLocation(point.x - 1, point.y);
data.get(3).setLocation(point.x + 1, point.y);
state = SEVEN.LEFT;
break;
default:
throw new Exception("sth wrong here SevenShape");
}
initialLimits();
getLimits();
return true;
}
@Override
public boolean unChangeShape() throws Exception {
Point point = data.get(2);
switch (state) {
case LEFT:
data.get(0).setLocation(point.x + 1, point.y - 1);
data.get(1).setLocation(point.x, point.y - 1);
data.get(3).setLocation(point.x, point.y + 1);
state = SEVEN.DOWN;
break;
case TOP:
data.get(0).setLocation(point.x - 1, point.y - 1);
data.get(1).setLocation(point.x - 1, point.y);
data.get(3).setLocation(point.x + 1, point.y);
state = SEVEN.LEFT;
break;
case RIGHT:
data.get(0).setLocation(point.x - 1, point.y + 1);
data.get(1).setLocation(point.x, point.y + 1);
data.get(3).setLocation(point.x, point.y - 1);
state = SEVEN.TOP;
break;
case DOWN:
data.get(0).setLocation(point.x + 1, point.y + 1);
data.get(1).setLocation(point.x + 1, point.y);
data.get(3).setLocation(point.x - 1, point.y);
state = SEVEN.RIGHT;
break;
default:
throw new Exception("sth wrong here SevenShape");
}
initialLimits();
getLimits();
return true;
}
}
ReverseSevenShape.java
package com.game.shape;
import java.awt.Point;
import java.util.List;
import com.game.state.ShapeInterface.REVERSESEVEN;
public class ReverseSevenShape extends Shape {
private REVERSESEVEN state;
public ReverseSevenShape(List<Point> data, int row, int column) {
super(data, row, column);
state = REVERSESEVEN.LEFT;
}
@Override
public boolean changeShape() throws Exception {
Point point = data.get(2);
switch (state) {
case RIGHT:
data.get(0).setLocation(point.x, point.y + 1);
data.get(1).setLocation(point.x + 1, point.y + 1);
data.get(3).setLocation(point.x, point.y - 1);
state = REVERSESEVEN.DOWN;
break;
case DOWN:
data.get(0).setLocation(point.x + 1, point.y);
data.get(1).setLocation(point.x + 1, point.y - 1);
data.get(3).setLocation(point.x - 1, point.y);
state = REVERSESEVEN.LEFT;
break;
case LEFT:
data.get(0).setLocation(point.x, point.y - 1);
data.get(1).setLocation(point.x - 1, point.y - 1);
data.get(3).setLocation(point.x, point.y + 1);
state = REVERSESEVEN.TOP;
break;
case TOP:
data.get(0).setLocation(point.x - 1, point.y);
data.get(1).setLocation(point.x - 1, point.y + 1);
data.get(3).setLocation(point.x + 1, point.y);
state = REVERSESEVEN.RIGHT;
break;
default:
throw new Exception("sth wrong here ReverseSevenShape");
}
initialLimits();
getLimits();
return true;
}
@Override
public boolean unChangeShape() throws Exception {
Point point = data.get(2);
switch (state) {
case RIGHT:
data.get(0).setLocation(point.x, point.y - 1);
data.get(1).setLocation(point.x - 1, point.y - 1);
data.get(3).setLocation(point.x, point.y + 1);
state = REVERSESEVEN.TOP;
break;
case DOWN:
data.get(0).setLocation(point.x - 1, point.y);
data.get(1).setLocation(point.x - 1, point.y + 1);
data.get(3).setLocation(point.x + 1, point.y);
state = REVERSESEVEN.RIGHT;
break;
case LEFT:
data.get(0).setLocation(point.x, point.y + 1);
data.get(1).setLocation(point.x + 1, point.y + 1);
data.get(3).setLocation(point.x, point.y - 1);
state = REVERSESEVEN.DOWN;
break;
case TOP:
data.get(0).setLocation(point.x + 1, point.y);
data.get(1).setLocation(point.x + 1, point.y - 1);
data.get(3).setLocation(point.x - 1, point.y);
state = REVERSESEVEN.LEFT;
break;
default:
throw new Exception("sth wrong here ReverseSevenShape");
}
initialLimits();
getLimits();
return true;
}
}
ChairShape.java
package com.game.shape;
import java.awt.Point;
import java.util.List;
import com.game.state.ShapeInterface.CHAIR;
public class ChairShape extends Shape {
private CHAIR state;
public ChairShape(List<Point> data, int row, int column) {
super(data, row, column);
state = CHAIR.HORIZONTAL;
}
@Override
public boolean changeShape() throws Exception {
Point point = data.get(2);
switch (state) {
case HORIZONTAL:
data.get(0).setLocation(point.x - 1, point.y + 1);
data.get(1).setLocation(point.x - 1, point.y);
data.get(3).setLocation(point.x, point.y - 1);
state = CHAIR.VERTICAL;
break;
case VERTICAL:
data.get(0).setLocation(point.x - 1, point.y - 1);
data.get(1).setLocation(point.x, point.y - 1);
data.get(3).setLocation(point.x + 1, point.y);
state = CHAIR.HORIZONTAL;
break;
default:
throw new Exception("sth wrong here : TriangleShape");
}
initialLimits();
getLimits();
return true;
}
@Override
public boolean unChangeShape() throws Exception {
try {
changeShape();
return false;
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
}
ReverseChairShpae.java
package com.game.shape;
import java.awt.Point;
import java.util.List;
import com.game.state.ShapeInterface.REVERSECHAIR;
public class ReverseChairShpae extends Shape {
private REVERSECHAIR state;
public ReverseChairShpae(List<Point> data, int row, int column) {
super(data, row, column);
state = REVERSECHAIR.HORIZONTAL;
}
@Override
public boolean changeShape() throws Exception {
Point point = data.get(2);
switch (state) {
case HORIZONTAL:
data.get(0).setLocation(point.x, point.y + 1);
data.get(1).setLocation(point.x - 1, point.y);
data.get(3).setLocation(point.x - 1, point.y - 1);
state = REVERSECHAIR.VERTICAL;
break;
case VERTICAL:
data.get(0).setLocation(point.x - 1, point.y);
data.get(1).setLocation(point.x, point.y - 1);
data.get(3).setLocation(point.x + 1, point.y - 1);
state = REVERSECHAIR.HORIZONTAL;
break;
default:
throw new Exception("sth wrong here : ReverseChairShpae");
}
initialLimits();
getLimits();
return true;
}
@Override
public boolean unChangeShape() throws Exception {
try {
changeShape();
return false;
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
}
ShapeEnum.java
package com.game.state;
public enum ShapeEnum {
SQURE(ShapeInterface.SQURE.class), LONG(ShapeInterface.LONG.class), TRIANGLE(ShapeInterface.TRIANGLE.class), SEVEN(
ShapeInterface.SEVEN.class), REVERSESEVEN(ShapeInterface.REVERSESEVEN.class), CHAIR(
ShapeInterface.CHAIR.class), REVERSECHAIR(ShapeInterface.REVERSECHAIR.class);
ShapeInterface[] values;
ShapeEnum(Class<? extends ShapeInterface> kind) {
values = kind.getEnumConstants();
}
}
ShapeInterface.java
package com.game.state;
public interface ShapeInterface {
enum SQURE implements ShapeInterface {
SQURE
}
enum LONG implements ShapeInterface {
HORIZONTAL, VERTICAL
}
enum TRIANGLE implements ShapeInterface {
TOP, RIGHT, DOWN, LEFT
}
enum SEVEN implements ShapeInterface {
LEFT, TOP, RIGHT, DOWN
}
enum REVERSESEVEN implements ShapeInterface {
RIGHT, DOWN, LEFT, TOP
}
enum CHAIR implements ShapeInterface {
HORIZONTAL, VERTICAL
}
enum REVERSECHAIR implements ShapeInterface {
HORIZONTAL, VERTICAL
}
}
Enums.java
package com.game.util;
import java.util.Random;
public class Enums {
private static Random rand = new Random();
public static <T extends Enum<T>> T random(Class<T> ec) {
return random(ec.getEnumConstants());
}
public static <T> T random(T[] values) {
return values[rand.nextInt(values.length)];
}
}
SameRow.java
package com.game.util;
import java.awt.Point;
import java.util.function.Predicate;
public class SameRow implements Predicate<Point> {
/* * This class used for to check whether the Point in same row. predict * function. */
private int row;
public SameRow() {
this(10);
}
public SameRow(int row) {
this.row = row;
}
public void setRow(int row) {
this.row = row;
}
@Override
public boolean test(Point t) {
return t.x == row;
}
}
ShapeData.java
package com.game.util;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import com.game.state.ShapeEnum;
public class ShapesData {
private static List<Point> data;
public static List<Point> makeShapeData(ShapeEnum shape) {
switch (shape) {
case SQURE:
data = new ArrayList<Point>();
data.add(new Point(-2, 0));
data.add(new Point(-2, 1));
data.add(new Point(-1, 0));
data.add(new Point(-1, 1));
break;
case LONG:
data = new ArrayList<Point>();
data.add(new Point(-1, 0));
data.add(new Point(-1, 1));
data.add(new Point(-1, 2));
data.add(new Point(-1, 3));
break;
case TRIANGLE:
data = new ArrayList<Point>();
data.add(new Point(-2, 1));
data.add(new Point(-1, 0));
data.add(new Point(-1, 1));
data.add(new Point(-1, 2));
break;
case SEVEN:
data = new ArrayList<Point>();
data.add(new Point(-3, 0));
data.add(new Point(-3, 1));
data.add(new Point(-2, 1));
data.add(new Point(-1, 1));
break;
case REVERSESEVEN:
data = new ArrayList<Point>();
data.add(new Point(-3, 0));
data.add(new Point(-3, 1));
data.add(new Point(-2, 0));
data.add(new Point(-1, 0));
break;
case CHAIR:
data = new ArrayList<Point>();
data.add(new Point(-3, 0));
data.add(new Point(-2, 0));
data.add(new Point(-2, 1));
data.add(new Point(-1, 1));
break;
case REVERSECHAIR:
data = new ArrayList<Point>();
data.add(new Point(-3, 1));
data.add(new Point(-2, 1));
data.add(new Point(-2, 0));
data.add(new Point(-1, 0));
break;
default:
return null;
}
return data;
}
}
Utils.java
package com.game.util;
import java.awt.Point;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.game.shape.ChairShape;
import com.game.shape.LongShape;
import com.game.shape.ReverseChairShpae;
import com.game.shape.ReverseSevenShape;
import com.game.shape.SevenShape;
import com.game.shape.Shape;
import com.game.shape.SqureShape;
import com.game.shape.TriangleShape;
import com.game.state.ShapeEnum;
public class Utils {
public static Shape makeShape(ShapeEnum shape, int row, int column) {
switch (shape) {
case SQURE:
return new SqureShape(ShapesData.makeShapeData(shape), row, column);
case LONG:
return new LongShape(ShapesData.makeShapeData(shape), row, column);
case TRIANGLE:
return new TriangleShape(ShapesData.makeShapeData(shape), row, column);
case SEVEN:
return new SevenShape(ShapesData.makeShapeData(shape), row, column);
case REVERSESEVEN:
return new ReverseSevenShape(ShapesData.makeShapeData(shape), row, column);
case CHAIR:
return new ChairShape(ShapesData.makeShapeData(shape), row, column);
case REVERSECHAIR:
return new ReverseChairShpae(ShapesData.makeShapeData(shape), row, column);
default:
return null;
}
}
public static boolean hasSamePoint(List<Point> data) {
Set<Point> set = new HashSet<Point>();
set.addAll(data);
return set.size() != data.size();
}
}
TestSqure.java
package com.game.test;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.game.shape.SqureShape;
import com.game.state.ShapeEnum;
import com.game.util.ShapesData;
public class TestSqure {
private SqureShape squre;
@Before
public void setUp() throws Exception {
squre = new SqureShape(ShapesData.makeShapeData(ShapeEnum.SQURE), 20,
10);
Assert.assertNotNull(squre);
}
@After
public void tearDown() throws Exception {
}
@Test
public void testchangeShape() {
Assert.assertTrue(squre.changeShape());
}
@Test
public void testunChangeShape() {
Assert.assertTrue(squre.unChangeShape());
}
}
最新的源码在GitHub地址