俄罗斯方块游戏是一个上手简单,老小皆宜的游戏,它的基本规则是移动、旋转和摆放游戏自动产生的各类方块,使之排列成完整的一行或多行而且消除得分。java
经过本文的阅读,读者能够对Swing版俄罗斯方块游戏的自己,对游戏中的关键点,如图形变换、键盘事件处理、游戏进度保存、满行和消行等都会有较好的理解。数组
游戏界面有四个部分组成:app
- 游戏面板区 -- 游戏主面板
- 下一个图形预览区 -- 呈现下一个图形
- 分数显示区 -- 显示目前的得分
- 菜单栏 -- 具有帮助、游戏设置、进度保存等功能
通常来说,一个图形有四个点,能够表示出经常使用的“一字型”,“T字型”,“Z字型”以及“L字型”方块。dom
若是将四个点的一个或者多个重叠,或者不采用经常使用的“一字型”,“T字型”,“Z字型”以及“L字型”方块,那么能够演变出更多的图形出来。若是想要更加丰富和复杂的图形,可使用更多的点去表示想要的图形。ide
四个点组成的图形有以下几种:ui
若是将四个点中的一个或者多个点重合,就能够有以下几种类型的图形:this
若是四个点不重合,还能够有以下几种比较诡异的图形,能够为游戏增长难度。spa
图形对象类表示code
格子类( Grid.java ) ,俄罗斯方块游戏中的图形由四个格子组成。每一个格子类有下x , y两个坐标位置, 颜色,以及格子图形绘制方法等。orm
如:
package my.games.russia.model; import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.io.Serializable; import my.games.russia.constants.RussiaGameConstant; /** * 格子,俄罗斯方块游戏中的图形由四个格子组成 * @author wangmengjun * */ public class Grid implements Serializable { private static final long serialVersionUID = -3722886719784770741L; /**x位置*/ private int x; /**y位置*/ private int y; /**格子的颜色*/ private Color color; public Grid() { } public Grid(int x, int y, Color color) { this.x = x; this.y = y; this.color = color; } public void draw(Graphics2D g2) { //TODO: } }
图形抽象类 ( AbstractRussiaSquare .java )。抽象类包含一些公用的属性(如:每一个图形由四个方块组成)、公用的方法(如向左移动、向右移动)、抽象方法(如图形变换须要子类实现细节)。
如:
package my.games.russia.model; import java.awt.Color; import java.awt.Graphics2D; import java.io.Serializable; import my.games.russia.constants.RussiaGameConstant; /** * 俄罗斯方块游戏,图形的抽象类 * @author wangmengjun * */ public abstract class AbstractRussiaSquare implements Serializable { private static final long serialVersionUID = 192398482620404584L; /**每个图形都是有四个小方块Grid组成*/ protected Grid[] grids = { null, null, null, null }; /**xLocations*/ protected int[] xLocations = { 0, 0, 0, 0 }; /**yLocations*/ protected int[] yLocations = { 0, 0, 0, 0 }; /**图形是否alive,便是否还能变换*/ protected boolean alive; /**图形格子的颜色*/ protected Color color; /**图形初始状态,图形转换的状态*/ public int state; public AbstractRussiaSquare() { int r = (int) (Math.random() * 256); int g = (int) (Math.random() * 256); int b = (int) (Math.random() * 256); this.color = new Color(r, g, b); grids[0] = new Grid(0, 0, color); grids[1] = new Grid(0, 0, color); grids[2] = new Grid(0, 0, color); grids[3] = new Grid(0, 0, color); alive = true; } /** * 图形绘制 */ public void draw(Graphics2D g2) { for(Grid grid : grids) { grid.draw(g2); } } /** * 往左移动 * * @param flag */ protected void moveLeft(int[][] flags) { if (!alive) { return; } //TODO:坐标变化 } /** * 往右移动 * * @param flag */ protected void moveLeft(int[][] flags) { if (!alive) { return; } //TODO:坐标变化 } /** * 往下移动 * * @param flag */ protected void moveDown(int[][] flags) { if (!alive) { return; } //TODO:坐标变化 } protected void isStateChangeAllowed(int[][] flags, int state) { //TODO } /** /** * 每一个图形的图形变化各不相同,须要子类实现细节 */ protected abstract void changeState(int[][] flags); }
每一个子类,只要继承了该抽象父类便可拥有公有的方法和属性,实现父类定义的抽象方法就能够拥有自身的实现细节。
图形变换或者图形旋转是俄罗斯方块游戏中比较关键的一个部分。
图形变换的思想?
由于一个图形有四个点来表示,能够先肯定其中的一个点的变换位置,而后其它的三个点根据这个肯定的基点进行位置调整就能够了。
好比,
以一字型的图形为例,只要第二号格子为固定点,相继算出其它格子的位置便可。
package my.games.russia.model; import java.util.Random; /** * 一字型 * @author wangmengjun * */ public class RussiaSquare_2 extends AbstractRussiaSquare { private static final long serialVersionUID = -4746450405460864752L; public RussiaSquare_2() { initGrids(); } /* (non-Javadoc) * @see my.games.russia.model.AbstractRussiaSquare#changeState(int[][]) */ @Override public void changeState(int[][] flags) { int fixedXLocation = grids[1].getX(); int fixedYLocation = grids[1].getY(); switch (state) { case 0: /** * 横向到竖直方向转换 */ /** * 第二个点保持不变 */ xLocations[1] = fixedXLocation; yLocations[1] = fixedYLocation; xLocations[0] = fixedXLocation; yLocations[0] = fixedYLocation - 1; xLocations[2] = fixedXLocation; yLocations[2] = fixedYLocation + 1; xLocations[3] = fixedXLocation; yLocations[3] = fixedYLocation + 2; isAllowChangeState(flags, 2); break; case 1: xLocations[1] = fixedXLocation; yLocations[1] = fixedYLocation; /** * 竖直到横向转换 */ xLocations[0] = fixedXLocation - 1; yLocations[0] = fixedYLocation; xLocations[2] = fixedXLocation + 1; yLocations[2] = fixedYLocation; xLocations[3] = fixedXLocation + 2; yLocations[3] = fixedYLocation; isAllowChangeState(flags, 2); break; default: break; } } /* (non-Javadoc) * @see my.games.russia.model.AbstractRussiaSquare#initGrids() */ @Override public void initGrids() { state = new Random().nextInt(2); switch (state) { case 0: /** * 竖直 */ grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX()); grids[1].setY(grids[0].getY() + 1); grids[2].setX(grids[0].getX()); grids[2].setY(grids[0].getY() + 2); grids[3].setX(grids[0].getX()); grids[3].setY(grids[0].getY() + 3); break; case 1: /** * 横向 */ grids[0].setX(8); grids[0].setY(0); grids[1].setX(grids[0].getX() + 1); grids[1].setY(grids[0].getY()); grids[2].setX(grids[0].getX() + 2); grids[2].setY(grids[0].getY()); grids[3].setX(grids[0].getX() + 3); grids[3].setY(grids[0].getY()); break; default: break; } } }
采用相似的方法,能够写出T字形的方块转换:
package my.games.russia.model; import java.util.Random; /** * T字型方块 * @author wangmengjun * */ public class RussiaSquare_3 extends AbstractRussiaSquare { private static final long serialVersionUID = -8336206016924545562L; public RussiaSquare_3() { initGrids(); } /* (non-Javadoc) * @see my.games.russia.model.AbstractRussiaSquare#changeState(int[][]) */ @Override public void changeState(int[][] flags) { switch (state) { case 0: xLocations[0] = grids[0].getX(); yLocations[0] = grids[0].getY(); xLocations[1] = xLocations[0]; yLocations[1] = yLocations[0] + 1; xLocations[2] = xLocations[0] + 1; yLocations[2] = yLocations[0] + 1; xLocations[3] = xLocations[0]; yLocations[3] = yLocations[0] + 2; isAllowChangeState(flags, 4); break; case 1: xLocations[0] = grids[0].getX() - 1; yLocations[0] = grids[0].getY() + 1; xLocations[1] = xLocations[0] + 1; yLocations[1] = yLocations[0]; xLocations[2] = xLocations[0] + 2; yLocations[2] = yLocations[0]; xLocations[3] = xLocations[0] + 1; yLocations[3] = yLocations[0] + 1; isAllowChangeState(flags, 4); break; case 2: xLocations[0] = grids[0].getX() + 1; yLocations[0] = grids[0].getY() - 1; xLocations[1] = xLocations[0] - 1; yLocations[1] = yLocations[0] + 1; xLocations[2] = xLocations[0]; yLocations[2] = yLocations[0] + 1; xLocations[3] = xLocations[0]; yLocations[3] = yLocations[0] + 2; isAllowChangeState(flags, 4); break; case 3: xLocations[0] = grids[0].getX(); yLocations[0] = grids[0].getY(); xLocations[1] = xLocations[0] - 1; yLocations[1] = yLocations[0] + 1; xLocations[2] = xLocations[0]; yLocations[2] = yLocations[0] + 1; xLocations[3] = xLocations[0] + 1; yLocations[3] = yLocations[0] + 1; isAllowChangeState(flags, 4); break; default: break; } } /* (non-Javadoc) * @see my.games.russia.model.AbstractRussiaSquare#initGrids() */ @Override public void initGrids() { state = new Random().nextInt(4); switch (state) { case 0: grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX() - 1); grids[1].setY(grids[0].getY() + 1); grids[2].setX(grids[0].getX()); grids[2].setY(grids[0].getY() + 1); grids[3].setX(grids[0].getX() + 1); grids[3].setY(grids[0].getY() + 1); break; case 1: grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX()); grids[1].setY(grids[0].getY() + 1); grids[2].setX(grids[0].getX() + 1); grids[2].setY(grids[0].getY() + 1); grids[3].setX(grids[0].getX()); grids[3].setY(grids[0].getY() + 2); break; case 2: grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX() + 1); grids[1].setY(grids[0].getY()); grids[2].setX(grids[0].getX() + 2); grids[2].setY(grids[0].getY()); grids[3].setX(grids[0].getX() + 1); grids[3].setY(grids[0].getY() + 1); break; case 3: grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX() - 1); grids[1].setY(grids[0].getY() + 1); grids[2].setX(grids[0].getX()); grids[2].setY(grids[0].getY() + 1); grids[3].setX(grids[0].getX()); grids[3].setY(grids[0].getY() + 2); break; default: break; } } }
键盘事件主要有以下几个部分
- 向左
- 向右
- 向下
- 按向上键变换图形
- 按空格键直接到最底部
向左
/** * 往左移动 * */ public void moveLeft(int[][] flags) { if (!alive) { return; } /** * 将现有的点赋值到xLocation和yLocation上去 */ for (int i = 0; i < grids.length; i++) { xLocations[i] = grids[i].getX() - 1; yLocations[i] = grids[i].getY(); } if (xLocations[0] >= RussiaGameConstant.LEFT && flags[xLocations[0]][yLocations[0]] == 0 && xLocations[1] >= RussiaGameConstant.LEFT && flags[xLocations[1]][yLocations[1]] == 0 && xLocations[2] >= RussiaGameConstant.LEFT && flags[xLocations[2]][yLocations[2]] == 0 && xLocations[3] >= RussiaGameConstant.LEFT && flags[xLocations[3]][yLocations[3]] == 0) { for (int i = 0; i < grids.length; i++) { grids[i].setX(xLocations[i]); } } }
向右以及向下都和向左操做相似。
向右
/** * 往右移动 */ public void moveRight(int flags[][]) { if (!alive) { return; } for (int i = 0; i < grids.length; i++) { xLocations[i] = grids[i].getX() + 1; yLocations[i] = grids[i].getY(); } if (xLocations[0] <= RussiaGameConstant.RIGHT && flags[xLocations[0]][yLocations[0]] == 0 && xLocations[1] <= RussiaGameConstant.RIGHT && flags[xLocations[1]][yLocations[1]] == 0 && xLocations[2] <= RussiaGameConstant.RIGHT && flags[xLocations[2]][yLocations[2]] == 0 && xLocations[3] <= RussiaGameConstant.RIGHT && flags[xLocations[3]][yLocations[3]] == 0) { for (int i = 0; i < grids.length; i++) { grids[i].setX(xLocations[i]); } } }
向下
/** * 往下移动 */ public void moveDown(int[][] flags) { for (int i = 0; i < grids.length; i++) { xLocations[i] = grids[i].getX(); yLocations[i] = grids[i].getY() + 1; } if (yLocations[0] <= RussiaGameConstant.DOWN && flags[xLocations[0]][yLocations[0]] == 0 && yLocations[1] <= RussiaGameConstant.DOWN && flags[xLocations[1]][yLocations[1]] == 0 && yLocations[2] <= RussiaGameConstant.DOWN && flags[xLocations[2]][yLocations[2]] == 0 && yLocations[3] <= RussiaGameConstant.DOWN && flags[xLocations[3]][yLocations[3]] == 0) { for (int i = 0; i < grids.length; i++) { grids[i].setY(yLocations[i]); ; } } else { alive = false; } }
变换图形
每一个图形,或有一种变换,或者有2种或者有四种变换,能够根据图形的特性进行处理。
好比,将“T字型”图型按照顺时针旋转,拥有四种变换,建立对象的时候已经肯定了state是多少(state肯定初始的位置是哪里),此后的变换只要对state加1并对4求余就能够知道怎么变换。
/* (non-Javadoc) * @see my.games.russia.model.AbstractRussiaSquare#changeState(int[][]) */ @Override public void changeState(int[][] flags) { switch (state) { case 0: xLocations[0] = grids[0].getX(); yLocations[0] = grids[0].getY(); xLocations[1] = xLocations[0]; yLocations[1] = yLocations[0] + 1; xLocations[2] = xLocations[0] + 1; yLocations[2] = yLocations[0] + 1; xLocations[3] = xLocations[0]; yLocations[3] = yLocations[0] + 2; isAllowChangeState(flags, 4); break; case 1: xLocations[0] = grids[0].getX() - 1; yLocations[0] = grids[0].getY() + 1; xLocations[1] = xLocations[0] + 1; yLocations[1] = yLocations[0]; xLocations[2] = xLocations[0] + 2; yLocations[2] = yLocations[0]; xLocations[3] = xLocations[0] + 1; yLocations[3] = yLocations[0] + 1; isAllowChangeState(flags, 4); break; case 2: xLocations[0] = grids[0].getX() + 1; yLocations[0] = grids[0].getY() - 1; xLocations[1] = xLocations[0] - 1; yLocations[1] = yLocations[0] + 1; xLocations[2] = xLocations[0]; yLocations[2] = yLocations[0] + 1; xLocations[3] = xLocations[0]; yLocations[3] = yLocations[0] + 2; isAllowChangeState(flags, 4); break; case 3: xLocations[0] = grids[0].getX(); yLocations[0] = grids[0].getY(); xLocations[1] = xLocations[0] - 1; yLocations[1] = yLocations[0] + 1; xLocations[2] = xLocations[0]; yLocations[2] = yLocations[0] + 1; xLocations[3] = xLocations[0] + 1; yLocations[3] = yLocations[0] + 1; isAllowChangeState(flags, 4); break; default: break; } }
一键到底
按下空格键一直向下的操做,其实就是在能够动的范围下,一直调用moveDown()方法
case KeyEvent.VK_SPACE: while (sr1.isAlive()) { sr1.moveDown(flag); }
针对键盘的操做,你们能够定义一个内部的事件处理器。
private class KeyHandler implements KeyListener { public void keyPressed(KeyEvent event) { if (!gameState.isRunState()) { return; } int keyCode = event.getKeyCode(); switch (keyCode) { case KeyEvent.VK_LEFT: sr1.moveLeft(flag); break; case KeyEvent.VK_RIGHT: sr1.moveRight(flag); break; case KeyEvent.VK_UP: sr1.changeState(flag); break; case KeyEvent.VK_DOWN: sr1.moveDown(flag); break; case KeyEvent.VK_SPACE: while (sr1.isAlive()) { sr1.moveDown(flag); } default: break; } repaint(); } public void keyReleased(KeyEvent event) { } public void keyTyped(KeyEvent event) { } }
而后,在游戏Panel建立的时候,添加上去便可。
addKeyListener(new KeyHandler());
用一个二维数组记录当前屏幕上的方块状态,0表示没有方块,1表示有方块。
满行条件?
满行的判断就归结到某一行1的个数是否等于该行列的总数,若是是就知足满行条件。
当有满行状况出现的时候,须要进行消除和计分操做。
如何消行?
消除行的一个作法就是将该行以上的行统统往下移,移动以后在将第一行的flag所有置为0。
for (int i = RussiaGameConstant.UP; i <= RussiaGameConstant.DOWN; i++) { int count = 0; for (int j = RussiaGameConstant.LEFT; j <= RussiaGameConstant.RIGHT; j++) { count += flag[j][i]; } /* * flag[i][j] =1 表示这个位置有小方块,若是一行的位置都有小方块,那么满行的个数num加1. * 而且消除行。 */ if (count == RussiaGameConstant.GRID_COLUMN_NUMBER) { num++; /** * 消除行操做。 */ for (int m = i; m > RussiaGameConstant.UP; m--) { for (int n = RussiaGameConstant.LEFT; n <= RussiaGameConstant.RIGHT; n++) { flag[n][m] = flag[n][m - 1]; color[n][m] = color[n][m - 1]; } } /* * 从新将第一行的flag[s][0]置为0 */ for (int s = RussiaGameConstant.LEFT; s <= RussiaGameConstant.RIGHT; s++) { flag[s][RussiaGameConstant.UP] = 0; } } }
/** * @param num * 方块满行的个数 */ private void calculateScore(int num) { switch (num) { case 1: score += 10; break; case 2: score += 20; break; case 3: score += 50; break; case 4: score += 100; break; default: break; } }
俄罗斯方块游戏结束的判断其实很简单,只要判断第一行的标记位是否有1便可。
/** * 若是是top touched 则执行Game Over的相关操做 * */ private void judgeGameOver() { if (isTopTouched()) { gameState = GameState.OVER; writeScore(); int result = JOptionPane.showConfirmDialog(frame, "Game over! Continue?", "俄罗斯方块", JOptionPane.YES_NO_OPTION); if (result == JOptionPane.YES_OPTION) { for (int i = RussiaGameConstant.LEFT; i <= RussiaGameConstant.RIGHT; i++) { for (int j = RussiaGameConstant.UP; j <= RussiaGameConstant.DOWN; j++) { flag[i][j] = 0; } } gameState = GameState.RUN; score = 0; timer.start(); } else { System.exit(0); } } }
private boolean isTopTouched() { for (int i = RussiaGameConstant.LEFT; i <= RussiaGameConstant.RIGHT; i++) { if (flag[i][RussiaGameConstant.UP] == 1) { return true; } } return false; }
游戏进度的保存和加载功能是经过序列化和反序列化来完成的。
经过序列化的方式将当前游戏运行状态中用到的一些重要对象属性序列化到文件中加以保存,从而达到记录当前游戏状态的效果。
经过反序列化的方式将序列化后的对象读取出来,从而达到恢复以前游戏保存时的状态的效果。用户能够在此基础上继续进行游戏。
(一)编写保存游戏进度、加载游戏进度的事件监听器
private class LoadAction implements ActionListener { public void actionPerformed(ActionEvent event) { FileDialog dialog = new FileDialog(RussiaGameFrame.this, "Open", FileDialog.LOAD); dialog.setVisible(true); String dir = dialog.getDirectory(); String fileName = dialog.getFile(); String filePath = dir + fileName; if (fileName != null && fileName.trim().length() != 0) { File file = new File(filePath); panel.readSelfFromFile(file); startMI.setEnabled(false); pauseMI.setEnabled(true); } else { JOptionPane.showConfirmDialog(RussiaGameFrame.this, "文件名为空\n装载游戏进度失败", "俄罗斯方块", JOptionPane.DEFAULT_OPTION); } } } private class SaveAction implements ActionListener { public void actionPerformed(ActionEvent event) { if (panel.gameState == GameState.INITIALIZE) { JOptionPane .showConfirmDialog(RussiaGameFrame.this, "游戏没有运行\n不能保存游戏进度", "俄罗斯方块", JOptionPane.DEFAULT_OPTION); return; } FileDialog dialog = new FileDialog(RussiaGameFrame.this, "Save", FileDialog.SAVE); dialog.setVisible(true); String dir = dialog.getDirectory(); String fileName = dialog.getFile(); String filePath = dir + fileName; if (fileName != null && fileName.trim().length() != 0) { File file = new File(filePath); panel.writeSelfToFile(file); } else { JOptionPane.showConfirmDialog(RussiaGameFrame.this, "文件名为空\n保存游戏进度失败", "俄罗斯方块", JOptionPane.DEFAULT_OPTION); } } }
(二)添加用于保存和加载功能的MenuItem, 并为它们添加ActionListenser
private JMenuItem loadMI = new JMenuItem("Open"); public JMenuItem saveMI = new JMenuItem("Save");
setMenu.add(loadMI); setMenu.add(saveMI);
loadMI.addActionListener(new LoadAction()); saveMI.addActionListener(new SaveAction());
(三)编写具体的业务逻辑
public void writeSelfToFile(File file) { try { FileOutputStream fileStream = new FileOutputStream(file); ObjectOutputStream objectStream = new ObjectOutputStream(fileStream); objectStream.writeObject(flag); objectStream.writeObject(color); objectStream.writeObject(sr1); objectStream.writeObject(sr2); objectStream.writeObject(new Integer(score)); objectStream.close(); fileStream.close(); JOptionPane.showConfirmDialog(frame, "保存游戏进度成功", "俄罗斯方块", JOptionPane.DEFAULT_OPTION); } catch (Exception e) { JOptionPane.showConfirmDialog(frame, e.toString() + "\n保存游戏进度失败", "俄罗斯方块", JOptionPane.DEFAULT_OPTION); } } public void readSelfFromFile(File file) { try { int[][] f; AbstractRussiaSquare s1, s2; Integer integer; Color[][] c; FileInputStream fileStream = new FileInputStream(file); ObjectInputStream objectStream = new ObjectInputStream(fileStream); f = (int[][]) objectStream.readObject(); c = (Color[][]) objectStream.readObject(); s1 = (AbstractRussiaSquare) objectStream.readObject(); s2 = (AbstractRussiaSquare) objectStream.readObject(); integer = (Integer) objectStream.readObject(); objectStream.close(); fileStream.close(); if (f != null && c != null && s1 != null && s2 != null && integer != null) { flag = f; color = c; sr1 = s1; sr2 = s2; score = integer.intValue(); gameState = GameState.RUN; frame.saveMI.setEnabled(true); if (!timer.isRunning()) { timer.start(); } repaint(); JOptionPane.showConfirmDialog(frame, "装载游戏进度成功", "俄罗斯方块", JOptionPane.DEFAULT_OPTION); } } catch (Exception e) { JOptionPane.showConfirmDialog(frame, e.toString() + "\n装载游戏进度失败", "俄罗斯方块", JOptionPane.DEFAULT_OPTION); } }
得分排行榜上列出Top 10的记录信息,包括玩家名称,得分和名次。
该功能能够经过以下几个步骤完成:
(一)建立游戏记录类和比较器
package my.games.russia.model; import java.io.Serializable; /** * 记录玩家的信息 * @author wangmengjun * */ public class Record implements Serializable { private static final long serialVersionUID = 9143467974370981697L; /**玩家姓名*/ private String player = null; /**玩家得分*/ private int score = 0; public Record(String player, int score) { this.player = player; this.score = score; } /** * @return the player */ public String getPlayer() { return player; } /** * @param player the player to set */ public void setPlayer(String player) { this.player = player; } /** * @return the score */ public int getScore() { return score; } /** * @param score the score to set */ public void setScore(int score) { this.score = score; } }
先经过分数比较,若是分数一致,则比较玩家名字。
package my.games.russia.compare; import java.util.Comparator; import my.games.russia.model.Record; /** * 俄罗斯记录的比较器 * @author wangmengjun * */ public class RecordComparator implements Comparator<Record> { public int compare(Record o1, Record o2) { Record r1 = (Record) o1; Record r2 = (Record) o2; int compareScore = compareScore(r1, r2); return (0 == compareScore) ? compareScore : compareName(r1, r2); } private int compareScore(Record r1, Record r2) { return r2.getScore() - r1.getScore(); } private int compareName(Record r1, Record r2) { return r1.getPlayer().compareTo(r2.getPlayer()); } }
(二)完成游戏结束后对记录文件更新的操做。
private void writeScore() { if (score == 0) { return; } File file = new File("file.dat"); RussiaGameRecords records = new ReadRecord().readRecordsFromFile(file); if (records == null || records.isEmpty() || !records.isFull() || (records.getLastAvailableRecord().getScore() < score && records.isFull())) { String playerName = JOptionPane.showInputDialog("Please input your name"); if (playerName == null || playerName.length() == 0) { playerName = "无名英雄"; } Record record = new Record(playerName, score); records.addRecordToTopTen(record); new WriteRecord().writeRecordToFile(records, file); } }
/** * 若是是top touched 则执行Game Over的相关操做 * */ private void judgeGameOver() { if (isTopTouched()) { gameState = GameState.OVER; writeScore(); int result = JOptionPane.showConfirmDialog(frame, "Game over! Continue?", "俄罗斯方块", JOptionPane.YES_NO_OPTION); if (result == JOptionPane.YES_OPTION) { for (int i = RussiaGameConstant.LEFT; i <= RussiaGameConstant.RIGHT; i++) { for (int j = RussiaGameConstant.UP; j <= RussiaGameConstant.DOWN; j++) { flag[i][j] = 0; } } gameState = GameState.RUN; score = 0; timer.start(); } else { System.exit(0); } } }
(三)完成点击Record相关的MenuItem,读取记录信息,并用ScrollPane展现出来。
package my.games.russia.ui; import java.io.File; import javax.swing.JScrollPane; import javax.swing.JTable; import my.games.russia.model.Record; import my.games.russia.model.RussiaGameRecords; /** * * @author wangmengjun * */ public class ReadScrollPane { public JScrollPane getReadScrollPane(RussiaGameRecords records, File recordFile) { Object[][] data = new Object[records.getNumberInRecord()][3]; for (int i = 0; i < records.getNumberInRecord(); i++) { Record record = records.getRecords()[i]; data[i][0] = String.valueOf(i + 1); data[i][1] = record.getPlayer(); data[i][2] = String.valueOf(record.getScore()); } Object[] columnNames = new Object[3]; columnNames[0] = "ID"; columnNames[1] = "Name"; columnNames[2] = "Score"; JTable table = new JTable(data, columnNames); table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); JScrollPane pane = new JScrollPane(table); return pane; } }
为了游戏更具随机性,随机产生方块主要包含两个部分的随机性。
编写一个工厂类,随机产生方块:如产生一字型的方块、T字形的方块等。
package my.games.russia.util; import java.util.Random; import my.games.russia.model.AbstractRussiaSquare; import my.games.russia.model.RussiaSquare_1; import my.games.russia.model.RussiaSquare_2; import my.games.russia.model.RussiaSquare_3; /** * * @author wangmengjun * */ public class RussiaSquareFactory { private static final int TOTAL_RUSSIA_SQUARE_COUNT = 3; public static AbstractRussiaSquare generateNextRussiaSquareByRandom() { AbstractRussiaSquare rs = null; int index = new Random().nextInt(TOTAL_RUSSIA_SQUARE_COUNT); switch (index) { case 0: rs = new RussiaSquare_1(); break; case 1: rs = new RussiaSquare_2(); break; case 2: rs = new RussiaSquare_3(); break; default: rs = new RussiaSquare_1(); break; } return rs; } }
每一个图形经过旋转,均可以有不同的初始化形态。好比T字形的方块就能够有四种形态,初始化的时候,也就有四种初始状态。以下是T字形方块的初始化:
/* (non-Javadoc) * @see my.games.russia.model.AbstractRussiaSquare#initGrids() */ @Override public void initGrids() { state = new Random().nextInt(4); switch (state) { case 0: grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX() - 1); grids[1].setY(grids[0].getY() + 1); grids[2].setX(grids[0].getX()); grids[2].setY(grids[0].getY() + 1); grids[3].setX(grids[0].getX() + 1); grids[3].setY(grids[0].getY() + 1); break; case 1: grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX()); grids[1].setY(grids[0].getY() + 1); grids[2].setX(grids[0].getX() + 1); grids[2].setY(grids[0].getY() + 1); grids[3].setX(grids[0].getX()); grids[3].setY(grids[0].getY() + 2); break; case 2: grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX() + 1); grids[1].setY(grids[0].getY()); grids[2].setX(grids[0].getX() + 2); grids[2].setY(grids[0].getY()); grids[3].setX(grids[0].getX() + 1); grids[3].setY(grids[0].getY() + 1); break; case 3: grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX() - 1); grids[1].setY(grids[0].getY() + 1); grids[2].setX(grids[0].getX()); grids[2].setY(grids[0].getY() + 1); grids[3].setX(grids[0].getX()); grids[3].setY(grids[0].getY() + 2); break; default: break; } }
方块降低和速度改变
方块降低能够采用Timer来控制。如:
public Timer timer; public TimerAction timerAction;
timerAction = new TimerAction(); timer = new Timer(1000, timerAction);
TimeAction类执行相关的逻辑行为,如:
private class TimerAction implements ActionListener, Serializable { private static final long serialVersionUID = -6117702515382009989L; public void actionPerformed(ActionEvent event) { if (!gameState.isRunState()) { return; } //满行的个数 int num = 0; sr1.moveDown(flag); if (!sr1.isAlive()) { for (int i = 0; i < 4; i++) { Grid[] grids = sr1.getGrids(); flag[grids[i].getX()][grids[i].getY()] = 1; color[grids[i].getX()][grids[i].getY()] = sr1.getColor(); } judgeGameOver(); for (int i = RussiaGameConstant.UP; i <= RussiaGameConstant.DOWN; i++) { int count = 0; for (int j = RussiaGameConstant.LEFT; j <= RussiaGameConstant.RIGHT; j++) { count += flag[j][i]; } /* * flag[i][j] =1 表示这个位置有小方块,若是一行的位置都有小方块,那么满行的个数num加1. * 而且消除行。 */ if (count == RussiaGameConstant.GRID_COLUMN_NUMBER) { num++; /** * 消除行操做。 */ for (int m = i; m > RussiaGameConstant.UP; m--) { for (int n = RussiaGameConstant.LEFT; n <= RussiaGameConstant.RIGHT; n++) { flag[n][m] = flag[n][m - 1]; color[n][m] = color[n][m - 1]; } } /* * 从新将第一行的flag[s][0]置为0 */ for (int s = RussiaGameConstant.LEFT; s <= RussiaGameConstant.RIGHT; s++) { flag[s][RussiaGameConstant.UP] = 0; } } } /* * 将下一个图形做为当前运动的图形,并随机产生下一个图形。 */ sr1 = sr2; sr2 = RussiaSquareFactory.generateNextRussiaSquareByRandom(); } // 计算分数 calculateScore(num); repaint(); } }
经过如上的步骤,一个单机版的Swing游戏就实现了,本文描述和实现了三种方块类型的旋转。
- 田字形
- 一字型
- T字形
你们能够参考上述的变形方法完成其余类型的变化,如L型, Z字形。
游戏效果以下:
貌似OSChina博客没有附件上传,写把代码列出来,下次找个时间放到GITHUB上去,再提供下载地址。
下面按照package包的名字来列出源码吧。
MyRussiaGameApplication.java
package my.games.russia.application; import javax.swing.JFrame; import my.games.russia.ui.RussiaGameFrame; public class MyRussiaGameApplication { @SuppressWarnings("deprecation") public static void main(String[] args) { RussiaGameFrame frame = new RussiaGameFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.show(); } }
RecordComparator.java
package my.games.russia.compare; import java.util.Comparator; import my.games.russia.model.Record; /** * 俄罗斯记录的比较器 * @author wangmengjun * */ public class RecordComparator implements Comparator<Record> { public int compare(Record o1, Record o2) { Record r1 = (Record) o1; Record r2 = (Record) o2; int compareScore = compareScore(r1, r2); return (0 == compareScore) ? compareScore : compareName(r1, r2); } private int compareScore(Record r1, Record r2) { return r2.getScore() - r1.getScore(); } private int compareName(Record r1, Record r2) { return r1.getPlayer().compareTo(r2.getPlayer()); } }
RussiaGameConstant.java
package my.games.russia.constants; /** * 俄罗斯方块的常量类 * @author wangmengjun * */ public class RussiaGameConstant { public static final int GRID_SIZE = 20; public static final int RUSSIA_GAME_PANEL_LEFT = 10; public static final int RUSSIA_GAME_PANEL_RIGHT = RUSSIA_GAME_PANEL_LEFT + 400; public static final int RUSSIA_GAME_PANEL_TOP = 0; public static final int RUSSIA_GAME_PANEL_BOTTOM = RUSSIA_GAME_PANEL_TOP + 600; public static final int RUSSIA_GAME_NEXT_PANEL_LEFT = RUSSIA_GAME_PANEL_RIGHT + GRID_SIZE; public static final int RUSSIA_GAME_NEXT_PANEL_RIGHT = RUSSIA_GAME_NEXT_PANEL_LEFT + 80; public static final int RUSSIA_GAME_NEXT_PANEL_TOP = RUSSIA_GAME_PANEL_TOP; public static final int RUSSIA_GAME_NEXT_PANEL_BOTTOM = RUSSIA_GAME_NEXT_PANEL_TOP + 80; public static final int LEFT = 0; public static final int RIGHT = 19; public static final int UP = 0; public static final int DOWN = 29; public static final int LITTLEX = 21; public static final int RUSSIA_GAME_FRAME_WIDTH = 540; public static final int RUSSIA_GAME_FRAME_HEIGHT = 660; public static final int GRID_COLUMN_NUMBER = 20; public static final int GRID_ROW_NUMBER = 30; }
GameState.java
package my.games.russia.enums; import java.util.HashMap; import java.util.Map; public enum GameState { INITIALIZE("I", "Initial Game State"), RUN("R", "Run State"), PAUSE("P", "Pause State"), OVER("O", "Over State"), UNKNOWN("U", "UNKNOWN"); private String gameStateCode = null; private String gameStateValue = null; private static Map<String, GameState> MAP = new HashMap<String, GameState>(); static { for (GameState gameState : GameState.values()) { MAP.put(gameState.getGameStateCode(), gameState); } } private GameState(String gameStateCode, String gameStateValue) { this.gameStateCode = gameStateCode; this.gameStateValue = gameStateValue; } public static GameState getGameStateByCode(String gameStateCode) { return MAP.containsKey(gameStateCode) ? MAP.get(gameStateCode) : UNKNOWN; } /** * @return the gameStateCode */ public String getGameStateCode() { return gameStateCode; } /** * @param gameStateCode * the gameStateCode to set */ public void setGameStateCode(String gameStateCode) { this.gameStateCode = gameStateCode; } /** * @return the gameStateValue */ public String getGameStateValue() { return gameStateValue; } /** * @param gameStateValue * the gameStateValue to set */ public void setGameStateValue(String gameStateValue) { this.gameStateValue = gameStateValue; } public boolean isInitializedState() { return this == INITIALIZE; } public boolean isRunState() { return this == RUN; } public boolean isPausedState() { return this == PAUSE; } public boolean isOverState() { return this == OVER; } }
model
Grid.java
package my.games.russia.model; import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.io.Serializable; import my.games.russia.constants.RussiaGameConstant; /** * 格子,俄罗斯方块游戏中的图形由四个格子组成 * @author wangmengjun * */ public class Grid implements Serializable { private static final long serialVersionUID = -3722886719784770741L; /**x位置*/ public int x; /**y位置*/ private int y; /**格子的颜色*/ private Color color; public Grid() { } public Grid(int x, int y, Color color) { this.x = x; this.y = y; this.color = color; } /** * Draw Grid * @param g2 */ public void draw(Graphics2D g2) { int clientX = RussiaGameConstant.RUSSIA_GAME_PANEL_LEFT + x * RussiaGameConstant.GRID_SIZE; int clientY = RussiaGameConstant.RUSSIA_GAME_PANEL_TOP + y * RussiaGameConstant.GRID_SIZE; Rectangle2D.Double rect = new Rectangle2D.Double(clientX, clientY, RussiaGameConstant.GRID_SIZE, RussiaGameConstant.GRID_SIZE); g2.setPaint(color); g2.fill(rect); g2.setPaint(Color.BLACK); g2.draw(rect); } /** * @return the x */ public int getX() { return x; } /** * @param x the x to set */ public void setX(int x) { this.x = x; } /** * @return the y */ public int getY() { return y; } /** * @param y the y to set */ public void setY(int y) { this.y = y; } /** * @return the color */ public Color getColor() { return color; } /** * @param color the color to set */ public void setColor(Color color) { this.color = color; } }
AbstractRussiaSquare.java
package my.games.russia.model; import java.awt.Color; import java.awt.Graphics2D; import java.io.Serializable; import my.games.russia.constants.RussiaGameConstant; /** * 俄罗斯方块游戏,图形的抽象类 * @author wangmengjun * */ public abstract class AbstractRussiaSquare implements Serializable { private static final long serialVersionUID = 192398482620404584L; /**每个图形都是有四个小方块Grid组成*/ protected Grid[] grids = { null, null, null, null }; /**xLocations*/ protected int[] xLocations = { 0, 0, 0, 0 }; /**yLocations*/ protected int[] yLocations = { 0, 0, 0, 0 }; /**图形是否alive,便是否还能变换*/ protected boolean alive; /**图形格子的颜色*/ protected Color color; /**图形初始状态,图形转换的状态*/ public int state; public AbstractRussiaSquare() { int r = (int) (Math.random() * 256); int g = (int) (Math.random() * 256); int b = (int) (Math.random() * 256); this.color = new Color(r, g, b); grids[0] = new Grid(0, 0, color); grids[1] = new Grid(0, 0, color); grids[2] = new Grid(0, 0, color); grids[3] = new Grid(0, 0, color); alive = true; /** * 每一个图形都有1到4种变换形态,随机产生一种 */ initGrids(); } /** * 图形绘制 */ public void draw(Graphics2D g2) { for (Grid grid : grids) { grid.draw(g2); } } /** * 往左移动 * */ public void moveLeft(int[][] flags) { if (!alive) { return; } /** * 将现有的点赋值到xLocation和yLocation上去 */ for (int i = 0; i < grids.length; i++) { xLocations[i] = grids[i].getX() - 1; yLocations[i] = grids[i].getY(); } if (xLocations[0] >= RussiaGameConstant.LEFT && flags[xLocations[0]][yLocations[0]] == 0 && xLocations[1] >= RussiaGameConstant.LEFT && flags[xLocations[1]][yLocations[1]] == 0 && xLocations[2] >= RussiaGameConstant.LEFT && flags[xLocations[2]][yLocations[2]] == 0 && xLocations[3] >= RussiaGameConstant.LEFT && flags[xLocations[3]][yLocations[3]] == 0) { for (int i = 0; i < grids.length; i++) { grids[i].setX(xLocations[i]); } } } /** * 往右移动 */ public void moveRight(int flags[][]) { if (!alive) { return; } for (int i = 0; i < grids.length; i++) { xLocations[i] = grids[i].getX() + 1; yLocations[i] = grids[i].getY(); } if (xLocations[0] <= RussiaGameConstant.RIGHT && flags[xLocations[0]][yLocations[0]] == 0 && xLocations[1] <= RussiaGameConstant.RIGHT && flags[xLocations[1]][yLocations[1]] == 0 && xLocations[2] <= RussiaGameConstant.RIGHT && flags[xLocations[2]][yLocations[2]] == 0 && xLocations[3] <= RussiaGameConstant.RIGHT && flags[xLocations[3]][yLocations[3]] == 0) { for (int i = 0; i < grids.length; i++) { grids[i].setX(xLocations[i]); } } } /** * 往下移动 */ public void moveDown(int[][] flags) { for (int i = 0; i < grids.length; i++) { xLocations[i] = grids[i].getX(); yLocations[i] = grids[i].getY() + 1; } if (yLocations[0] <= RussiaGameConstant.DOWN && flags[xLocations[0]][yLocations[0]] == 0 && yLocations[1] <= RussiaGameConstant.DOWN && flags[xLocations[1]][yLocations[1]] == 0 && yLocations[2] <= RussiaGameConstant.DOWN && flags[xLocations[2]][yLocations[2]] == 0 && yLocations[3] <= RussiaGameConstant.DOWN && flags[xLocations[3]][yLocations[3]] == 0) { for (int i = 0; i < grids.length; i++) { grids[i].setY(yLocations[i]); ; } } else { alive = false; } } public void drawNext(Graphics2D g2) { for (int i = 0; i < grids.length; i++) { xLocations[i] = grids[i].getX(); yLocations[i] = grids[i].getY(); } while (true) { xLocations[0]++; xLocations[1]++; xLocations[2]++; xLocations[3]++; if (xLocations[0] >= RussiaGameConstant.LITTLEX && xLocations[1] >= RussiaGameConstant.LITTLEX && xLocations[2] >= RussiaGameConstant.LITTLEX && xLocations[3] >= RussiaGameConstant.LITTLEX) { break; } } for (int i = 0; i < grids.length; i++) { new Grid(xLocations[i], yLocations[i], color).draw(g2); } } protected void isAllowChangeState(int[][] flags, int count) { if (!alive) { return; } if (xLocations[0] >= RussiaGameConstant.LEFT && xLocations[0] <= RussiaGameConstant.RIGHT && yLocations[0] >= RussiaGameConstant.UP && yLocations[0] <= RussiaGameConstant.DOWN && flags[xLocations[0]][yLocations[0]] == 0 && xLocations[1] >= RussiaGameConstant.LEFT && xLocations[1] <= RussiaGameConstant.RIGHT && yLocations[1] >= RussiaGameConstant.UP && yLocations[1] <= RussiaGameConstant.DOWN && flags[xLocations[1]][yLocations[1]] == 0 && xLocations[2] >= RussiaGameConstant.LEFT && xLocations[2] <= RussiaGameConstant.RIGHT && yLocations[2] >= RussiaGameConstant.UP && yLocations[2] <= RussiaGameConstant.DOWN && flags[xLocations[2]][yLocations[2]] == 0 && xLocations[3] >= RussiaGameConstant.LEFT && xLocations[3] <= RussiaGameConstant.RIGHT && yLocations[3] >= RussiaGameConstant.UP && yLocations[3] <= RussiaGameConstant.DOWN && flags[xLocations[3]][yLocations[3]] == 0) { for (int i = 0; i < grids.length; i++) { grids[i].setX(xLocations[i]); grids[i].setY(yLocations[i]); } /** * count为图形能够变化的种数 */ state = (state + 1) % count; } } /** * 每一个图形的图形变化各不相同,须要子类实现细节 */ public abstract void changeState(int[][] flags); public abstract void initGrids(); /** * @return the alive */ public boolean isAlive() { return alive; } /** * @param alive the alive to set */ public void setAlive(boolean alive) { this.alive = alive; } /** * @return the grids */ public Grid[] getGrids() { return grids; } /** * @param grids the grids to set */ public void setGrids(Grid[] grids) { this.grids = grids; } /** * @return the color */ public Color getColor() { return color; } /** * @param color the color to set */ public void setColor(Color color) { this.color = color; } }
Record.java
package my.games.russia.model; import java.io.Serializable; /** * 记录玩家的信息 * @author wangmengjun * */ public class Record implements Serializable { private static final long serialVersionUID = 9143467974370981697L; /**玩家姓名*/ private String player = null; /**玩家得分*/ private int score = 0; public Record(String player, int score) { this.player = player; this.score = score; } /** * @return the player */ public String getPlayer() { return player; } /** * @param player the player to set */ public void setPlayer(String player) { this.player = player; } /** * @return the score */ public int getScore() { return score; } /** * @param score the score to set */ public void setScore(int score) { this.score = score; } }
RussiaGameRecords.java
package my.games.russia.model; import java.io.Serializable; import java.util.Arrays; import java.util.Collections; import my.games.russia.compare.RecordComparator; /** * 俄罗斯方块游戏的排行榜 * @author wangmengjun * */ public class RussiaGameRecords implements Serializable { private static final long serialVersionUID = 2621026339727176509L; private static final int TOP_TEN = 10; private Record[] records = null; private int numberInRecord = 0; // 排行榜中已经拥有的记录个数 public RussiaGameRecords() { records = new Record[TOP_TEN]; } public void sortRecords() { Collections.sort(Arrays.asList(getAvailableRecords()), new RecordComparator()); } private Record[] getAvailableRecords() { Record[] availableRecords = new Record[numberInRecord]; for (int i = 0; i < numberInRecord; i++) { availableRecords[i] = new Record(records[i].getPlayer(), records[i].getScore()); } return availableRecords; } /** * * @return */ public Record getLastAvailableRecord() { return isEmpty() ? null : records[numberInRecord - 1]; } /** * * @param record */ public void addRecordToTopTen(Record record) { if (isEmpty()) { records[0] = record; numberInRecord++; return; } if (isFull()) { if (records[TOP_TEN - 1].getScore() < record.getScore()) { records[TOP_TEN - 1] = record; sortRecords(); return; } } records[numberInRecord] = record; numberInRecord++; sortRecords(); } /** * * @return */ public boolean isEmpty() { return 0 == numberInRecord; } /** * * @return */ public boolean isFull() { return TOP_TEN == numberInRecord; } /** * @return the numberInRecord */ public int getNumberInRecord() { return numberInRecord; } /** * @param numberInRecord * the numberInRecord to set */ public void setNumberInRecord(int numberInRecord) { this.numberInRecord = numberInRecord; } /** * @return the records */ public Record[] getRecords() { return records; } /** * @param records * the records to set */ public void setRecords(Record[] records) { this.records = records; } }
RussiaSquare_1.java
package my.games.russia.model; /** * 田字形 * * @author wangmengjun * */ public class RussiaSquare_1 extends AbstractRussiaSquare { private static final long serialVersionUID = -2293988596788484343L; public RussiaSquare_1() { initGrids(); } /* (non-Javadoc) * @see my.games.russia.model.AbstractRussiaSquare#changeState(int[][]) */ @Override public void changeState(int[][] flags) { // 田字形只有一种形态,不须要变换 } /* (non-Javadoc) * @see my.games.russia.model.AbstractRussiaSquare#initGrids() */ @Override public void initGrids() { grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX() + 1); grids[1].setY(0); grids[2].setX(grids[0].getX()); grids[2].setY(grids[0].getY() + 1); grids[3].setX(grids[0].getX() + 1); grids[3].setY(grids[0].getY() + 1); } }
RussiaSquare_2.java
package my.games.russia.model; import java.util.Random; /** * 一字型 * @author wangmengjun * */ public class RussiaSquare_2 extends AbstractRussiaSquare { private static final long serialVersionUID = -4746450405460864752L; public RussiaSquare_2() { initGrids(); } /* (non-Javadoc) * @see my.games.russia.model.AbstractRussiaSquare#changeState(int[][]) */ @Override public void changeState(int[][] flags) { int fixedXLocation = grids[1].getX(); int fixedYLocation = grids[1].getY(); switch (state) { case 0: /** * 横向到竖直方向转换 */ /** * 第二个点保持不变 */ xLocations[1] = fixedXLocation; yLocations[1] = fixedYLocation; xLocations[0] = fixedXLocation; yLocations[0] = fixedYLocation - 1; xLocations[2] = fixedXLocation; yLocations[2] = fixedYLocation + 1; xLocations[3] = fixedXLocation; yLocations[3] = fixedYLocation + 2; isAllowChangeState(flags, 2); break; case 1: xLocations[1] = fixedXLocation; yLocations[1] = fixedYLocation; /** * 竖直到横向转换 */ xLocations[0] = fixedXLocation - 1; yLocations[0] = fixedYLocation; xLocations[2] = fixedXLocation + 1; yLocations[2] = fixedYLocation; xLocations[3] = fixedXLocation + 2; yLocations[3] = fixedYLocation; isAllowChangeState(flags, 2); break; default: break; } } /* (non-Javadoc) * @see my.games.russia.model.AbstractRussiaSquare#initGrids() */ @Override public void initGrids() { state = new Random().nextInt(2); switch (state) { case 0: /** * 竖直 */ grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX()); grids[1].setY(grids[0].getY() + 1); grids[2].setX(grids[0].getX()); grids[2].setY(grids[0].getY() + 2); grids[3].setX(grids[0].getX()); grids[3].setY(grids[0].getY() + 3); break; case 1: /** * 横向 */ grids[0].setX(8); grids[0].setY(0); grids[1].setX(grids[0].getX() + 1); grids[1].setY(grids[0].getY()); grids[2].setX(grids[0].getX() + 2); grids[2].setY(grids[0].getY()); grids[3].setX(grids[0].getX() + 3); grids[3].setY(grids[0].getY()); break; default: break; } } }
RussiaSquare_3.java
package my.games.russia.model; import java.util.Random; /** * T字型方块 * @author wangmengjun * */ public class RussiaSquare_3 extends AbstractRussiaSquare { private static final long serialVersionUID = -8336206016924545562L; public RussiaSquare_3() { initGrids(); } /* (non-Javadoc) * @see my.games.russia.model.AbstractRussiaSquare#changeState(int[][]) */ @Override public void changeState(int[][] flags) { switch (state) { case 0: xLocations[0] = grids[0].getX(); yLocations[0] = grids[0].getY(); xLocations[1] = xLocations[0]; yLocations[1] = yLocations[0] + 1; xLocations[2] = xLocations[0] + 1; yLocations[2] = yLocations[0] + 1; xLocations[3] = xLocations[0]; yLocations[3] = yLocations[0] + 2; isAllowChangeState(flags, 4); break; case 1: xLocations[0] = grids[0].getX() - 1; yLocations[0] = grids[0].getY() + 1; xLocations[1] = xLocations[0] + 1; yLocations[1] = yLocations[0]; xLocations[2] = xLocations[0] + 2; yLocations[2] = yLocations[0]; xLocations[3] = xLocations[0] + 1; yLocations[3] = yLocations[0] + 1; isAllowChangeState(flags, 4); break; case 2: xLocations[0] = grids[0].getX() + 1; yLocations[0] = grids[0].getY() - 1; xLocations[1] = xLocations[0] - 1; yLocations[1] = yLocations[0] + 1; xLocations[2] = xLocations[0]; yLocations[2] = yLocations[0] + 1; xLocations[3] = xLocations[0]; yLocations[3] = yLocations[0] + 2; isAllowChangeState(flags, 4); break; case 3: xLocations[0] = grids[0].getX(); yLocations[0] = grids[0].getY(); xLocations[1] = xLocations[0] - 1; yLocations[1] = yLocations[0] + 1; xLocations[2] = xLocations[0]; yLocations[2] = yLocations[0] + 1; xLocations[3] = xLocations[0] + 1; yLocations[3] = yLocations[0] + 1; isAllowChangeState(flags, 4); break; default: break; } } /* (non-Javadoc) * @see my.games.russia.model.AbstractRussiaSquare#initGrids() */ @Override public void initGrids() { state = new Random().nextInt(4); switch (state) { case 0: grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX() - 1); grids[1].setY(grids[0].getY() + 1); grids[2].setX(grids[0].getX()); grids[2].setY(grids[0].getY() + 1); grids[3].setX(grids[0].getX() + 1); grids[3].setY(grids[0].getY() + 1); break; case 1: grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX()); grids[1].setY(grids[0].getY() + 1); grids[2].setX(grids[0].getX() + 1); grids[2].setY(grids[0].getY() + 1); grids[3].setX(grids[0].getX()); grids[3].setY(grids[0].getY() + 2); break; case 2: grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX() + 1); grids[1].setY(grids[0].getY()); grids[2].setX(grids[0].getX() + 2); grids[2].setY(grids[0].getY()); grids[3].setX(grids[0].getX() + 1); grids[3].setY(grids[0].getY() + 1); break; case 3: grids[0].setX(9); grids[0].setY(0); grids[1].setX(grids[0].getX() - 1); grids[1].setY(grids[0].getY() + 1); grids[2].setX(grids[0].getX()); grids[2].setY(grids[0].getY() + 1); grids[3].setX(grids[0].getX()); grids[3].setY(grids[0].getY() + 2); break; default: break; } } }
ReadRecord.java
package my.games.russia.record; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.ObjectInputStream; import my.games.russia.model.RussiaGameRecords; public class ReadRecord { public RussiaGameRecords readRecordsFromFile(File recordFile) { RussiaGameRecords records = new RussiaGameRecords(); FileInputStream fileInput = null; ObjectInputStream objectInput = null; if (!recordFile.exists()) { return records; } try { fileInput = new FileInputStream(recordFile); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { objectInput = new ObjectInputStream(fileInput); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } Object o = null; try { o = objectInput.readObject(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { objectInput.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { fileInput.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } records = (RussiaGameRecords) o; records.sortRecords(); return records; } }
WriteRecord.java
package my.games.russia.record; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import my.games.russia.model.RussiaGameRecords; public class WriteRecord { public void writeRecordToFile(RussiaGameRecords records, File recordFile) { FileOutputStream fileOutput = null; try { fileOutput = new FileOutputStream(recordFile); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } ObjectOutputStream objectOutput = null; try { objectOutput = new ObjectOutputStream(fileOutput); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { objectOutput.writeObject(records); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { objectOutput.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { fileOutput.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
ReadScrollPane.java
package my.games.russia.ui; import java.io.File; import javax.swing.JScrollPane; import javax.swing.JTable; import my.games.russia.model.Record; import my.games.russia.model.RussiaGameRecords; /** * * @author wangmengjun * */ public class ReadScrollPane { public JScrollPane getReadScrollPane(RussiaGameRecords records, File recordFile) { Object[][] data = new Object[records.getNumberInRecord()][3]; for (int i = 0; i < records.getNumberInRecord(); i++) { Record record = records.getRecords()[i]; data[i][0] = String.valueOf(i + 1); data[i][1] = record.getPlayer(); data[i][2] = String.valueOf(record.getScore()); } Object[] columnNames = new Object[3]; columnNames[0] = "ID"; columnNames[1] = "Name"; columnNames[2] = "Score"; JTable table = new JTable(data, columnNames); table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); JScrollPane pane = new JScrollPane(table); return pane; } }
RussiaGameFrame.java
package my.games.russia.ui; import java.awt.Container; import java.awt.FileDialog; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import javax.swing.ButtonGroup; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JRadioButtonMenuItem; import javax.swing.JScrollPane; import my.games.russia.constants.RussiaGameConstant; import my.games.russia.enums.GameState; import my.games.russia.model.RussiaGameRecords; import my.games.russia.record.ReadRecord; /** * * @author wangmengjun * */ public class RussiaGameFrame extends JFrame { private static final long serialVersionUID = 2511418550392568827L; private final int WIDTH = RussiaGameConstant.RUSSIA_GAME_FRAME_WIDTH; private final int HEIGHT = RussiaGameConstant.RUSSIA_GAME_FRAME_HEIGHT; private RussiaGamePanel panel; private Container contentPane; private JMenuItem startMI = new JMenuItem("Start"); private JMenuItem pauseMI = new JMenuItem("Pause"); private JMenuItem recordMI = new JMenuItem("Record"); private JMenu speedMenu = new JMenu("Speed"); private JMenuItem exitMI = new JMenuItem("Exit"); private JMenuItem aboutMI = new JMenuItem("About"); private JMenuItem loadMI = new JMenuItem("Open"); public JMenuItem saveMI = new JMenuItem("Save"); private JRadioButtonMenuItem speedMI1 = new JRadioButtonMenuItem("Speed1", true); private JRadioButtonMenuItem speedMI2 = new JRadioButtonMenuItem("Speed2", false); private JRadioButtonMenuItem speedMI3 = new JRadioButtonMenuItem("Speed3", false); private JRadioButtonMenuItem speedMI4 = new JRadioButtonMenuItem("Speed4", false); private JRadioButtonMenuItem speedMI5 = new JRadioButtonMenuItem("Speed5", false); public int speedFlag = 1; public RussiaGameFrame() { setTitle("俄罗斯方块"); setSize(WIDTH, HEIGHT); setResizable(false); JMenuBar menuBar = new JMenuBar(); setJMenuBar(menuBar); JMenu setMenu = new JMenu("Set"); JMenu helpMenu = new JMenu("Help"); setMenu.setMnemonic('s'); setMenu.setMnemonic('H'); menuBar.add(setMenu); menuBar.add(helpMenu); setMenu.add(startMI); setMenu.add(pauseMI); setMenu.addSeparator(); setMenu.add(loadMI); setMenu.add(saveMI); setMenu.add(recordMI); setMenu.addSeparator(); setMenu.add(speedMenu); setMenu.addSeparator(); setMenu.add(exitMI); ButtonGroup group = new ButtonGroup(); group.add(speedMI1); group.add(speedMI2); group.add(speedMI3); group.add(speedMI4); group.add(speedMI5); speedMenu.add(speedMI1); speedMenu.add(speedMI2); speedMenu.add(speedMI3); speedMenu.add(speedMI4); speedMenu.add(speedMI5); startMI.addActionListener(new StartAction()); pauseMI.addActionListener(new PauseAction()); loadMI.addActionListener(new LoadAction()); saveMI.addActionListener(new SaveAction()); recordMI.addActionListener(new RecordAction()); exitMI.addActionListener(new ExitAction()); speedMI1.addActionListener(new SpeedAction()); speedMI2.addActionListener(new SpeedAction()); speedMI3.addActionListener(new SpeedAction()); speedMI4.addActionListener(new SpeedAction()); speedMI5.addActionListener(new SpeedAction()); helpMenu.add(aboutMI); aboutMI.addActionListener(new AboutAction()); contentPane = getContentPane(); panel = new RussiaGamePanel(this); contentPane.add(panel); startMI.setEnabled(true); pauseMI.setEnabled(false); saveMI.setEnabled(false); // 设置游戏状态是初始化状态 panel.setGameState(GameState.INITIALIZE); } private class StartAction implements ActionListener { public void actionPerformed(ActionEvent event) { startMI.setEnabled(false); pauseMI.setEnabled(true); saveMI.setEnabled(true); panel.setGameState(GameState.RUN); panel.timer.start(); } } private class PauseAction implements ActionListener { public void actionPerformed(ActionEvent event) { pauseMI.setEnabled(false); startMI.setEnabled(true); panel.setGameState(GameState.PAUSE); if (panel.timer.isRunning()) { panel.timer.stop(); } } } private class LoadAction implements ActionListener { public void actionPerformed(ActionEvent event) { FileDialog dialog = new FileDialog(RussiaGameFrame.this, "Open", FileDialog.LOAD); dialog.setVisible(true); String dir = dialog.getDirectory(); String fileName = dialog.getFile(); String filePath = dir + fileName; if (fileName != null && fileName.trim().length() != 0) { File file = new File(filePath); panel.readSelfFromFile(file); startMI.setEnabled(false); pauseMI.setEnabled(true); } else { JOptionPane.showConfirmDialog(RussiaGameFrame.this, "文件名为空\n装载游戏进度失败", "俄罗斯方块", JOptionPane.DEFAULT_OPTION); } } } private class SaveAction implements ActionListener { public void actionPerformed(ActionEvent event) { if (panel.gameState == GameState.INITIALIZE) { JOptionPane .showConfirmDialog(RussiaGameFrame.this, "游戏没有运行\n不能保存游戏进度", "俄罗斯方块", JOptionPane.DEFAULT_OPTION); return; } FileDialog dialog = new FileDialog(RussiaGameFrame.this, "Save", FileDialog.SAVE); dialog.setVisible(true); String dir = dialog.getDirectory(); String fileName = dialog.getFile(); String filePath = dir + fileName; if (fileName != null && fileName.trim().length() != 0) { File file = new File(filePath); panel.writeSelfToFile(file); } else { JOptionPane.showConfirmDialog(RussiaGameFrame.this, "文件名为空\n保存游戏进度失败", "俄罗斯方块", JOptionPane.DEFAULT_OPTION); } } } private class RecordAction implements ActionListener { @SuppressWarnings("deprecation") public void actionPerformed(ActionEvent event) { File file = new File("file.dat"); RussiaGameRecords records = new ReadRecord() .readRecordsFromFile(file); records.sortRecords(); JScrollPane panel = new ReadScrollPane().getReadScrollPane(records, file); JDialog recordDialog = new JDialog(RussiaGameFrame.this, "俄罗斯方块"); recordDialog.setBounds(300, 300, 300, 219); Container container = recordDialog.getContentPane(); container.add(panel); recordDialog.show(); } } private class SpeedAction implements ActionListener { public void actionPerformed(ActionEvent event) { Object speed = event.getSource(); if (speed == speedMI1) { speedFlag = 1; } else if (speed == speedMI2) { speedFlag = 2; } else if (speed == speedMI3) { speedFlag = 3; } else if (speed == speedMI4) { speedFlag = 4; } else if (speed == speedMI5) { speedFlag = 5; } panel.timer.setDelay(1000 - 200 * (speedFlag - 1)); } } private class ExitAction implements ActionListener { public void actionPerformed(ActionEvent event) { int result = JOptionPane.showConfirmDialog(RussiaGameFrame.this, "Are you sure quit?", "俄罗斯方块", JOptionPane.YES_NO_OPTION); if (result == JOptionPane.YES_OPTION) { System.exit(0); } } } private class AboutAction implements ActionListener { public void actionPerformed(ActionEvent event) { String string = "说明:\n1.按左键向左移动\n" + "2.按右键向右移动\n" + "3.按向上键翻滚\n" + "4.按向下键加速降低\n" + "5.按空格键降低到最底部"; JOptionPane.showMessageDialog(RussiaGameFrame.this, string); } } }
RussiaGamePanel.java
package my.games.russia.ui; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.geom.Rectangle2D; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.Timer; import my.games.russia.constants.RussiaGameConstant; import my.games.russia.enums.GameState; import my.games.russia.model.Grid; import my.games.russia.model.Record; import my.games.russia.model.RussiaGameRecords; import my.games.russia.model.AbstractRussiaSquare; import my.games.russia.record.ReadRecord; import my.games.russia.record.WriteRecord; import my.games.russia.util.RussiaSquareFactory; /** * 俄罗斯方块游戏面板 * @author wangmengjun * */ public class RussiaGamePanel extends JPanel { private static final long serialVersionUID = 3422344654252668944L; public int[][] flag = new int[RussiaGameConstant.GRID_COLUMN_NUMBER][RussiaGameConstant.GRID_ROW_NUMBER];// 在一个10*20的界面中,设置每一个方块的flag public Color[][] color = new Color[RussiaGameConstant.GRID_COLUMN_NUMBER][RussiaGameConstant.GRID_ROW_NUMBER];// 在一个10*20的界面中,设置每一个方块的颜色 public AbstractRussiaSquare sr1; // 主显示界面的图形 public AbstractRussiaSquare sr2; // 下一个显示界面的图形 public Timer timer; public TimerAction timerAction; public int score; public RussiaGameFrame frame; public Grid square; // public int gameState; public GameState gameState = GameState.INITIALIZE; public RussiaGamePanel(RussiaGameFrame frame) { for (int i = RussiaGameConstant.LEFT; i <= RussiaGameConstant.RIGHT; i++) { for (int j = RussiaGameConstant.UP; j <= RussiaGameConstant.DOWN; j++) { flag[i][j] = 0; } } addKeyListener(new KeyHandler()); setFocusable(true); timerAction = new TimerAction(); timer = new Timer(1000, timerAction); sr1 = RussiaSquareFactory.generateNextRussiaSquareByRandom(); sr2 = RussiaSquareFactory.generateNextRussiaSquareByRandom(); score = 0; this.frame = frame; square = new Grid(); } public void drawGameFrame(Graphics2D g2) { Rectangle2D.Double leftFrame = new Rectangle2D.Double( RussiaGameConstant.RUSSIA_GAME_PANEL_LEFT, RussiaGameConstant.RUSSIA_GAME_PANEL_TOP, 400, 600); Rectangle2D.Double rightFrame = new Rectangle2D.Double( RussiaGameConstant.RUSSIA_GAME_NEXT_PANEL_LEFT, RussiaGameConstant.RUSSIA_GAME_NEXT_PANEL_TOP, 80, 80); g2.draw(leftFrame); g2.draw(rightFrame); } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; drawGameFrame(g2); if (gameState.isInitializedState()) { return; } sr1.draw(g2); sr2.drawNext(g2); for (int i = RussiaGameConstant.LEFT; i <= RussiaGameConstant.RIGHT; i++) { for (int j = RussiaGameConstant.UP; j <= RussiaGameConstant.DOWN; j++) { if (flag[i][j] == 1) { square.setX(i); square.setY(j); square.setColor(color[i][j]); square.draw(g2); } } } g.drawString("Score: " + score, RussiaGameConstant.RUSSIA_GAME_NEXT_PANEL_LEFT, 200); } public void writeSelfToFile(File file) { try { FileOutputStream fileStream = new FileOutputStream(file); ObjectOutputStream objectStream = new ObjectOutputStream(fileStream); objectStream.writeObject(flag); objectStream.writeObject(color); objectStream.writeObject(sr1); objectStream.writeObject(sr2); objectStream.writeObject(new Integer(score)); objectStream.close(); fileStream.close(); JOptionPane.showConfirmDialog(frame, "保存游戏进度成功", "俄罗斯方块", JOptionPane.DEFAULT_OPTION); } catch (Exception e) { JOptionPane.showConfirmDialog(frame, e.toString() + "\n保存游戏进度失败", "俄罗斯方块", JOptionPane.DEFAULT_OPTION); } } public void readSelfFromFile(File file) { try { int[][] f; AbstractRussiaSquare s1, s2; Integer integer; Color[][] c; FileInputStream fileStream = new FileInputStream(file); ObjectInputStream objectStream = new ObjectInputStream(fileStream); f = (int[][]) objectStream.readObject(); c = (Color[][]) objectStream.readObject(); s1 = (AbstractRussiaSquare) objectStream.readObject(); s2 = (AbstractRussiaSquare) objectStream.readObject(); integer = (Integer) objectStream.readObject(); objectStream.close(); fileStream.close(); if (f != null && c != null && s1 != null && s2 != null && integer != null) { flag = f; color = c; sr1 = s1; sr2 = s2; score = integer.intValue(); gameState = GameState.RUN; frame.saveMI.setEnabled(true); if (!timer.isRunning()) { timer.start(); } repaint(); JOptionPane.showConfirmDialog(frame, "装载游戏进度成功", "俄罗斯方块", JOptionPane.DEFAULT_OPTION); } } catch (Exception e) { JOptionPane.showConfirmDialog(frame, e.toString() + "\n装载游戏进度失败", "俄罗斯方块", JOptionPane.DEFAULT_OPTION); } } public void setGameState(GameState state) { gameState = state; } private void writeScore() { if (score == 0) { return; } File file = new File("file.dat"); RussiaGameRecords records = new ReadRecord().readRecordsFromFile(file); if (records == null || records.isEmpty() || !records.isFull() || (records.getLastAvailableRecord().getScore() < score && records.isFull())) { String playerName = JOptionPane.showInputDialog("Please input your name"); if (playerName == null || playerName.length() == 0) { playerName = "无名英雄"; } Record record = new Record(playerName, score); records.addRecordToTopTen(record); new WriteRecord().writeRecordToFile(records, file); } } private boolean isTopTouched() { for (int i = RussiaGameConstant.LEFT; i <= RussiaGameConstant.RIGHT; i++) { if (flag[i][RussiaGameConstant.UP] == 1) { return true; } } return false; } /** * 若是是top touched 则执行Game Over的相关操做 * */ private void judgeGameOver() { if (isTopTouched()) { gameState = GameState.OVER; writeScore(); int result = JOptionPane.showConfirmDialog(frame, "Game over! Continue?", "俄罗斯方块", JOptionPane.YES_NO_OPTION); if (result == JOptionPane.YES_OPTION) { for (int i = RussiaGameConstant.LEFT; i <= RussiaGameConstant.RIGHT; i++) { for (int j = RussiaGameConstant.UP; j <= RussiaGameConstant.DOWN; j++) { flag[i][j] = 0; } } gameState = GameState.RUN; score = 0; timer.start(); } else { System.exit(0); } } } private class KeyHandler implements KeyListener { public void keyPressed(KeyEvent event) { if (!gameState.isRunState()) { return; } int keyCode = event.getKeyCode(); switch (keyCode) { case KeyEvent.VK_LEFT: sr1.moveLeft(flag); break; case KeyEvent.VK_RIGHT: sr1.moveRight(flag); break; case KeyEvent.VK_UP: sr1.changeState(flag); break; case KeyEvent.VK_DOWN: sr1.moveDown(flag); break; case KeyEvent.VK_SPACE: while (sr1.isAlive()) { sr1.moveDown(flag); } default: break; } repaint(); } public void keyReleased(KeyEvent event) { } public void keyTyped(KeyEvent event) { } } private class TimerAction implements ActionListener, Serializable { private static final long serialVersionUID = -6117702515382009989L; public void actionPerformed(ActionEvent event) { if (!gameState.isRunState()) { return; } //满行的个数 int num = 0; sr1.moveDown(flag); if (!sr1.isAlive()) { for (int i = 0; i < 4; i++) { Grid[] grids = sr1.getGrids(); flag[grids[i].getX()][grids[i].getY()] = 1; color[grids[i].getX()][grids[i].getY()] = sr1.getColor(); } judgeGameOver(); for (int i = RussiaGameConstant.UP; i <= RussiaGameConstant.DOWN; i++) { int count = 0; for (int j = RussiaGameConstant.LEFT; j <= RussiaGameConstant.RIGHT; j++) { count += flag[j][i]; } /* * flag[i][j] =1 表示这个位置有小方块,若是一行的位置都有小方块,那么满行的个数num加1. * 而且消除行。 */ if (count == RussiaGameConstant.GRID_COLUMN_NUMBER) { num++; /** * 消除行操做。 */ for (int m = i; m > RussiaGameConstant.UP; m--) { for (int n = RussiaGameConstant.LEFT; n <= RussiaGameConstant.RIGHT; n++) { flag[n][m] = flag[n][m - 1]; color[n][m] = color[n][m - 1]; } } /* * 从新将第一行的flag[s][0]置为0 */ for (int s = RussiaGameConstant.LEFT; s <= RussiaGameConstant.RIGHT; s++) { flag[s][RussiaGameConstant.UP] = 0; } } } /* * 将下一个图形做为当前运动的图形,并随机产生下一个图形。 */ sr1 = sr2; sr2 = RussiaSquareFactory.generateNextRussiaSquareByRandom(); } // 计算分数 calculateScore(num); repaint(); } } /** * @param num * 方块满行的个数 */ private void calculateScore(int num) { switch (num) { case 1: score += 10; break; case 2: score += 20; break; case 3: score += 50; break; case 4: score += 100; break; default: break; } } }
RussiaSquareFactory.java
package my.games.russia.util; import java.util.Random; import my.games.russia.model.AbstractRussiaSquare; import my.games.russia.model.RussiaSquare_1; import my.games.russia.model.RussiaSquare_2; import my.games.russia.model.RussiaSquare_3; /** * * @author wangmengjun * */ public class RussiaSquareFactory { private static final int TOTAL_RUSSIA_SQUARE_COUNT = 3; public static AbstractRussiaSquare generateNextRussiaSquareByRandom() { AbstractRussiaSquare rs = null; int index = new Random().nextInt(TOTAL_RUSSIA_SQUARE_COUNT); switch (index) { case 0: rs = new RussiaSquare_1(); break; case 1: rs = new RussiaSquare_2(); break; case 2: rs = new RussiaSquare_3(); break; default: rs = new RussiaSquare_1(); break; } return rs; } }
若有任何错误,请你们指正。
若有任何建议,也请告诉我,谢谢。