这里面用了io流写了等级,会生成一个文件。
如果想学习,可以看我的word文档,已经复制在下方。
import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Properties; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.Timer; public class Tetris extends JFrame implements ActionListener { private static final long serialVersionUID = 1L; private TetrisJPanel jPanel; private JMenuItem menuItem_start, menuItem_stop, menuItem_end, menuItem_rank, menuItem_help; private JLabel jLabel_First, jLabel_Second, jLabel_Three; private JDialog jDialog; public Tetris() { super("俄罗斯方块"); addMenu(); // new 对象 this.jPanel = new TetrisJPanel(); // 设置背景,这里有点邪门。。。 // jPanel.setBackground(Color.black); this.setBackground(Color.white); this.getContentPane().add(jPanel); // 初始化排名 writeRankToFile(jPanel.dir, jPanel.filename, 0); // 为框架添加键盘监听 this.addKeyListener(jPanel.listener); } private void addMenu() { // new 对象 JMenuBar menuBar = new JMenuBar(); JMenu menu = new JMenu("菜单"); menuItem_start = new JMenuItem("新建游戏"); menuItem_stop = new JMenuItem("暂停"); menuItem_stop.setActionCommand("stop"); menuItem_rank = new JMenuItem("排名"); menuItem_end = new JMenuItem("结束"); jDialog = new JDialog(this, "^_^排名记录^_^"); jLabel_First = new JLabel(); jLabel_Second = new JLabel(); jLabel_Three = new JLabel(); JMenu menu_help = new JMenu("帮助"); menuItem_help = new JMenuItem("游戏说明"); // 为JDialog加控件 jDialog.setDefaultCloseOperation(HIDE_ON_CLOSE); jDialog.setVisible(false); jDialog.setBounds(350, 70, 200, 150); jDialog.setLayout(new GridLayout(3, 1)); jDialog.add(jLabel_First); jDialog.add(jLabel_Second); jDialog.add(jLabel_Three); // 给菜单项加监听 menuItem_start.addActionListener(this); menuItem_stop.addActionListener(this); menuItem_rank.addActionListener(this); menuItem_end.addActionListener(this); menuItem_help.addActionListener(this); // 加工具条和菜单 this.setJMenuBar(menuBar); menuBar.add(menu); menuBar.add(menu_help); // menu加组件 menu.add(menuItem_start); menu.add(menuItem_stop); menu.add(menuItem_rank); menu.addSeparator(); menu.add(menuItem_end); // menu_help加组件 menu_help.add(menuItem_help); } public void showRank(String dir, String fileName) { jLabel_First.setText(" First: " + readRankFromFile(dir, fileName, 1)); jLabel_Second.setText(" Second: " + readRankFromFile(dir, fileName, 2)); jLabel_Three.setText(" Third: " + readRankFromFile(dir, fileName, 3));//这个单词先前写错了 jDialog.setVisible(true); } public void writeRankToFile(String dir, String fileName, int value) { File file = null; FileInputStream fis = null; Properties p = new Properties(); FileOutputStream fos = null; try { file = new File(dir + fileName); // 路径名表示的文件不可用,这时指定默认路径名 if (!file.canExecute()) { dir = "d:/tetris/game/"; file = new File(dir); file.mkdirs(); file = new File(dir + fileName); } file.createNewFile(); // 从文件中读取数据 fis = new FileInputStream(dir + fileName); p.load(fis); // 第一个名 int temp1 = 120; String first = p.getProperty("First"); if (first != null) { temp1 = Integer.parseInt(first); } p.setProperty("First", String.valueOf(temp1)); // 第二名 int temp2 = 60; first = p.getProperty("Second"); if (first != null) { temp2 = Integer.parseInt(first); } p.setProperty("Second", String.valueOf(temp2)); // 第三名 int temp3 = 0; first = p.getProperty("Three"); if (first != null) { temp3 = Integer.parseInt(first); } p.setProperty("Three", String.valueOf(temp3)); // 插入排名数据**** if (value > temp1) { p.setProperty("First", String.valueOf(value)); } else if (value > temp2) { p.setProperty("Second", String.valueOf(value)); } else if (value > temp3) { p.setProperty("Three", String.valueOf(value)); } // 把数据保存到文件中 fos = new FileOutputStream(dir + fileName); p.store(fos, "写入\"tetris\"游戏数据"); } catch (IOException e) { new RuntimeException("文件创建失败"); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } public int readRankFromFile(String dir, String fileName, int value) { File file = null; FileInputStream fis = null; Properties p = new Properties(); // 如果没成员,那么返回0 int temp = 0; try { file = new File(dir + fileName); // 如果文件不存在,那么就返回0 if (!file.canExecute()) { return 0; } // 从文件中读取数据 fis = new FileInputStream(dir + fileName); p.load(fis); String first = p.getProperty("First"); // 第一个名 if (value == 1 && first != null) { temp = Integer.parseInt(first); } // 第二名 first = p.getProperty("Second"); if (value == 2 && first != null) { temp = Integer.parseInt(first); } // 第三名 first = p.getProperty("Three"); if (value == 3 && first != null) { temp = Integer.parseInt(first); } } catch (IOException e) { new RuntimeException("文件创建失败"); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } return temp; } // 不访问外面的变量,使本类可以独立 public class TetrisJPanel extends JPanel { private static final long serialVersionUID = 1L; // 设置排名 protected String dir = "d:/tetris/game/", filename = "tetris.properties"; // 控制游戏是否开始或暂停 public boolean isStart; // 设置像素 private final int paintWidth = 20; private int blockType, turnState; private int blockType_copy = ((int) (Math.random() * 1000)) % 7; private int turnState_copy = ((int) (Math.random() * 1000)) % 4; // 设置方块的位置 private int x, y; // 方块数据 private final int[][][] shapes = { // I型 { // 状态 { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 }, { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 }, { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // J型 { // 状态 { 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 }, { 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, { 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // L型 { // 状态 { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 }, { 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // O型 { // 状态 { 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // S型 { // 状态 { 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, { 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 } }, // T型 { // 状态 { 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 } }, // Z型 { // 状态 { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 } } }; // /* // * 0 表示空白 // * 1 表示积累块 // * 2 // * 3 表示框架 // */ // 游戏地图24+4行12+3列 private int[][] map = new int[24 + 4][12 + 3]; // 定时器 protected TimerListener listener = new TimerListener(); // 定时 private int delay = 1000; Timer timer = new Timer(delay, listener); // 记分 private int score = 0; // 画笔字体 Font drawFont = new Font("宋体", Font.BOLD, 30); public TetrisJPanel() { newMap(); nextBlock(); timer.start(); } // /* // * 左移和右移都不能消行 // * 只有向下移动才可能消行 // */ private void down() { // 先预测下移一位是否安全,如果不安全就返回0 if (collide(x, y + 1, blockType, turnState) == 0) { // 当前快与框架与积淀块碰撞时要重新开始游戏 add(x, y, blockType, turnState); nextBlock(); } else { y++; } tryDelecteLine(); } private void right() { // 根据T型方块定的10,O型是9, if (x <= 10) {// 有了预判,就可以随意了,只要不太小就行 // 先预测右移一位是否安全 x += collide(x + 1, y, blockType, turnState); } } private void left() { // 根据I型方块定的0是1, if (x >= 1) {// 有了预判,就可以随意了,只要不太大就行 // 没有碰撞就返回1,先预测左移一位是否安全 x -= collide(x - 1, y, blockType, turnState); } } private void turn() { if (collide(x, y, blockType, (turnState + 1) % 4) == 1) { turnState = (turnState + 1) % 4; } } private void add(int x, int y, int blockType, int turnState) { for (int a = 0; a < 4; a++) {// 行 for (int b = 0; b < 4; b++) {// 列 if (shapes[blockType][turnState][a * 4 + b] == 1) { map[y + a][x + b] = 1; } } } } // 碰撞 crash collide impact 单词 private int collide(int x, int y, int blockType, int turnState) { for (int a = 0; a < 4; a++) {// 方块的行 for (int b = 0; b < 4; b++) {// 方块的列 // 一个数与1与运算,可以判断这个数是否是素数 // 这里的框架与积淀块分别是3,1; // 遍历整个方块,然后与map的下一行进行对比(y+1),由此判断此方块是否碰撞 if ((map[y + a][x + b] & shapes[blockType][turnState][a * 4 + b]) == 1) { // 确认当前块会覆盖 框架或积淀块 // 设置map[][]中的数据为沉淀快 // 当碰撞时返回1 return 0; } } } // 当方块没有与框架与积淀块碰撞时返回1,方便计算 return 1; } private void tryDelecteLine() { // 从最下面一行开始遍历,这样写会有特殊效果,会出现东西掉下来的感觉 for (int a = 23; a >= 0; a--) {// 24行 int c = 1; for (int b = 1; b <= 12; b++) { c &= map[a][b]; } // 如果c==1,那么说明当前行装满了 if (c == 1) { // 第一行没有拷贝 for (int i = a; i > 0; i--) { for (int j = 1; j <= 12; j++) { map[i][j] = map[i - 1][j]; } } // 第一行全赋值为0 for (int i = 1; i <= 12; i++) { map[0][i] = 0; } score += 12; delay -= 150; setScoreDelay(score, delay); } } } private void newMap() { // map[24+3][12+3] for (int i = 0; i < map[0].length - 1; i++) {// 列,多加了1列 for (int j = 0; j < map.length - 3; j++) {// 行,多加了2行,加下边的一行 // 多加了1列,2行,第一列和倒数第二列 if (i == 0 || (i + 2 == map[0].length)) {// 表示框架 map[j][i] = 3; } else {// 下次调用次函数可以重新初始化 map[j][i] = 0; } } // 实际上并不需要四行 map[map.length - 4][i] = 3;// 最下边的框架 } } private void nextBlock() { blockType = blockType_copy; turnState = turnState_copy; blockType_copy = ((int) (Math.random() * 1000)) % 7; turnState_copy = ((int) (Math.random() * 1000)) % 4; x = 5; y = 0; // 如果撞到了就重新开始,会返回0 if (collide(x, y, blockType, turnState) == 0) { end(); JOptionPane.showMessageDialog(Tetris.this, "你输了,游戏结束!!!"); } } public void setScoreDelay(int score, int delay) { this.score = score; // 1000-150*5 < 400 if (delay < 400) { delay = 1000; } timer.setDelay(delay); } public void start() { // 初始化数据 end(); timer.start(); // 设置分数 score = 0; // 游戏失败,但是不清空,重新开始时就清空 newMap(); nextBlock(); isStart = true; } public void end() { // 所有数据复原 writeRankToFile(dir, filename, score); isStart = false; timer.stop(); setScoreDelay(0, 1000); repaint(); } class TimerListener extends KeyAdapter implements ActionListener { @Override public void actionPerformed(ActionEvent e) { // 先画 repaint(); // 控制游戏是否开始 if (!isStart) { return; } // 自动向下 down(); } // 有三个类,但是只有这个用到了 @Override public void keyPressed(KeyEvent e) { // 控制游戏是否开始或暂停 if (!isStart) { return; } switch (e.getKeyCode()) { case KeyEvent.VK_DOWN: down(); break; case KeyEvent.VK_RIGHT: right(); break; case KeyEvent.VK_LEFT: left(); break; case KeyEvent.VK_UP: turn(); break; } repaint(); } } @Override protected void paintComponent(Graphics g) { // 清除内容,可以解决残影 super.paintComponent(g); // 画当前块 g.setColor(Color.blue); for (int a = 0; a < 16; a++) { if (shapes[blockType][turnState][a] == 1) { // x 表示列(a%4),y表示行(a/4) g.fill3DRect((x + a % 4) * paintWidth, (y + a / 4) * paintWidth, paintWidth, paintWidth, false); // 画在右边 g.fill3DRect(340 + (a % 4) * paintWidth, 80 + (a / 4) * paintWidth, paintWidth, paintWidth, false); } else { g.draw3DRect(340 + (a % 4) * paintWidth, 80 + (a / 4) * paintWidth, paintWidth, paintWidth, false); } } // 画框架和堆积快 for (int j = 0; j < map.length; j++) {// 行,多加了2行 for (int i = 0; i < map[i].length; i++) {// 列,多加了1列 if (map[j][i] == 3) {// 框架 g.setColor(Color.YELLOW); g.fill3DRect(i * paintWidth, j * paintWidth, paintWidth, paintWidth, true); } else if (map[j][i] == 1) {// 画堆积快 g.setColor(Color.red); g.fill3DRect(i * paintWidth, j * paintWidth, paintWidth, paintWidth, true); g.setColor(Color.black); g.draw3DRect(i * paintWidth, j * paintWidth, paintWidth, paintWidth, false); } } } // 记分面板 g.setColor(Color.red); if (score <= 120) { g.drawString("score:" + score, 340, 20); } else { g.setFont(drawFont); g.drawString("恭喜你胜利" + score, 10, 100); isStart = false; } // 下一个 g.drawString("下一个", 340, 200); for (int a = 0; a < 16; a++) { if (shapes[blockType_copy][turnState_copy][a] == 1) {// 空白快 g.fill3DRect(340 + (a % 4) * paintWidth, 220 + (a / 4) * paintWidth, paintWidth, paintWidth, true); } else { g.draw3DRect(340 + (a % 4) * paintWidth, 220 + (a / 4) * paintWidth, paintWidth, paintWidth, false); } } } } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == menuItem_start) { if (JOptionPane.showConfirmDialog(this, "你确定新建游戏吗?") == 0) { jPanel.start(); } } if (e.getActionCommand().equalsIgnoreCase("stop")) { menuItem_stop.setActionCommand("continue"); menuItem_stop.setText("继续"); jPanel.isStart = false; } if (e.getActionCommand().equalsIgnoreCase("continue")) { menuItem_stop.setActionCommand("stop"); menuItem_stop.setText("暂停"); jPanel.isStart = true; } if (e.getSource() == menuItem_rank) { showRank(jPanel.dir, jPanel.filename); } if (e.getSource() == menuItem_end) { if (JOptionPane.showConfirmDialog(this, "你确定要退出吗?") == 0) { System.exit(0); } } if (e.getSource() == menuItem_help) { JOptionPane.showMessageDialog(this, "每消一行就加12分,满120分就胜利。\n如果想看以前的记录,可以看前三名。"); } } public static void main(String[] args) { Tetris te = new Tetris(); // 一个像素有10int的大小,纯手工调试,不要抄袭啊!!! te.setBounds(300, 60, 500, 565); // te.setResizable(false); te.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); te.setVisible(true); } }
//这个是没有等级的。
package design_Tetris_Analog1; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import javax.swing.JApplet; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.Timer; public class Tetris extends JFrame implements ActionListener { private static final long serialVersionUID = 1L; private TetrisJPanel jPanel; public boolean isStart; JMenuItem menuItem_start, menuItem_stop, menuItem_end; public Tetris() { addMenu(); // new 对象 this.jPanel = new TetrisJPanel(); // 设置背景,这里有点邪门。。。 // jPanel.setBackground(Color.black); this.setBackground(Color.white); this.getContentPane().add(jPanel); // 为框架添加键盘监听 this.addKeyListener(jPanel.listener); } private void addMenu() { // new 对象 JMenuBar menuBar = new JMenuBar(); JMenu menu = new JMenu("菜单"); menuItem_start = new JMenuItem("新建游戏"); menuItem_stop = new JMenuItem("暂停"); menuItem_stop.setActionCommand("stop"); menuItem_end = new JMenuItem("结束"); // 给菜单项加监听 menuItem_start.addActionListener(this); menuItem_stop.addActionListener(this); menuItem_end.addActionListener(this); // 加工具条和菜单 this.setJMenuBar(menuBar); menuBar.add(menu); menu.add(menuItem_start); menu.add(menuItem_stop); menu.add(menuItem_end); } class TetrisJPanel extends JPanel { private static final long serialVersionUID = 1L; private int blockType, turnState; private int blockType_copy = ((int) (Math.random() * 1000)) % 7; private int turnState_copy = ((int) (Math.random() * 1000)) % 4; // 设置方块的位置 private int x, y; // 方块数据 private final int[][][] shapes = { // I型 { // 状态 { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 }, { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 }, { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // J型 { // 状态 { 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 }, { 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, { 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // L型 { // 状态 { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 }, { 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // O型 { // 状态 { 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // S型 { // 状态 { 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, { 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 } }, // T型 { // 状态 { 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 } }, // Z型 { // 状态 { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 } } }; // /* // * 0 表示空白 // * 1 表示积累块 // * 2 // * 3 表示框架 // */ // 游戏地图24+4行12+3列 private int[][] map = new int[24 + 4][12 + 3]; // 定时器 protected TimerListener listener = new TimerListener(); // 定时 private int delay = 1000; Timer timer = new Timer(delay, listener); // 记分 private int score = 0; // 画笔字体 Font drawFont = new Font("宋体", Font.BOLD, 30); // 控制游戏是否开始 public TetrisJPanel() { // this.setBackground(Color.blue);//加监听器后,调用down()函数,就可以用了 newMap(); nextBlock(); timer.start(); } class TimerListener extends KeyAdapter implements ActionListener { @Override public void actionPerformed(ActionEvent e) { // 控制游戏是否开始 if (!isStart) { return; } // 自动向下 down(); repaint(); } // 有三个类,但是只有这个用到了 @Override public void keyPressed(KeyEvent e) { // 控制游戏是否开始 if (!isStart) { return; } switch (e.getKeyCode()) { case KeyEvent.VK_DOWN: // System.out.println("down"); down(); break; case KeyEvent.VK_RIGHT: // System.out.println("right"); right(); break; case KeyEvent.VK_LEFT: // System.out.println("left"); left(); break; case KeyEvent.VK_UP: // System.out.println("turn"); turn(); break; } repaint(); } } private void newMap() { // map[24+3][12+3] for (int i = 0; i < map[0].length - 1; i++) {// 列,多加了1列 for (int j = 0; j < map.length - 3; j++) {// 行,多加了2行,加下边的一行 // 多加了1列,2行,第一列和倒数第二列 if (i == 0 || (i + 2 == map[0].length)) {// 表示框架 map[j][i] = 3; } else {// 下次调用次函数可以重新初始化 map[j][i] = 0; } } // 实际上并不需要四行 map[map.length - 4][i] = 3;// 最下边的框架 } repaint(); } private void nextBlock() { blockType = blockType_copy; turnState = turnState_copy; blockType_copy = ((int) (Math.random() * 1000)) % 7; turnState_copy = ((int) (Math.random() * 1000)) % 4; x = 5; y = 0; repaint(); // 如果撞到了就重新开始,会返回0 if (collide(x, y, blockType, turnState) == 0) { isStart = false; JOptionPane.showMessageDialog(Tetris.this, "你输了,游戏结束!!!"); //看要不要自动开始游戏 //isStart = true; newMap(); } } // /* // * 左移和右移都不能消行 // * 只有向下移动才可能消行 // */ private void down() { // 先预测下移一位是否安全,如果不安全就返回0 if (collide(x, y + 1, blockType, turnState) == 0) { // 当前快与框架与积淀块碰撞时要重新开始游戏 add(x, y, blockType, turnState); nextBlock(); } else { y++; } tryDelecteLine(); repaint(); } private void right() { // 根据T型方块定的10,O型是9, if (x <= 10) {// 有了预判,就可以随意了,只要不太小就行 // 先预测右移一位是否安全 x += collide(x + 1, y, blockType, turnState); repaint(); } } private void left() { // 根据I型方块定的0是1, if (x >= 1) {// 有了预判,就可以随意了,只要不太大就行 // 没有碰撞就返回1,先预测左移一位是否安全 x -= collide(x - 1, y, blockType, turnState); repaint(); } } private void turn() { if (collide(x, y, blockType, (turnState + 1) % 4) == 1) { turnState = (turnState + 1) % 4; repaint(); } } private void add(int x, int y, int blockType, int turnState) { for (int a = 0; a < 4; a++) {// 行 for (int b = 0; b < 4; b++) {// 列 if (shapes[blockType][turnState][a * 4 + b] == 1) { map[y + a][x + b] = 1; } } } } private void tryDelecteLine() { // 从最下面一行开始遍历 for (int a = 23; a >= 0; a--) {// 24行 int c = 1; for (int b = 1; b <= 12; b++) { c &= map[a][b]; } // 如果c==1,那么说明当前行装满了 if (c == 1) { // 第一行没有拷贝 for (int i = a; i > 0; i--) { for (int j = 1; j <= 12; j++) { map[i][j] = map[i - 1][j]; } } // 第一行全赋值为0 for (int i = 1; i <= 12; i++) { map[0][i] = 0; } score += 12; delay /= 2; setScoreDelay(score, delay); } } } public void setScoreDelay(int score, int delay) { this.score = score; timer.setDelay(delay); if (delay < 100) { delay = 2000; } } // 碰撞 crash collide impact 单词 private int collide(int x, int y, int blockType, int turnState) { for (int a = 0; a < 4; a++) {// 方块的行 for (int b = 0; b < 4; b++) {// 方块的列 // 一个数与1与运算,可以判断这个数是否是素数 // 这里的框架与积淀块分别是3,1; // 遍历整个方块,然后与map的下一行进行对比(y+1),由此判断此方块是否碰撞 if ((map[y + a][x + b] & shapes[blockType][turnState][a * 4 + b]) == 1) { // 确认当前块会覆盖 框架或积淀块 // 设置map[][]中的数据为沉淀快 // 当碰撞时返回1 return 0; } } } // 当方块没有与框架与积淀块碰撞时返回1,方便计算 return 1; } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // 画当前块 g.setColor(Color.blue); for (int a = 0; a < 16; a++) { if (shapes[blockType][turnState][a] == 1) { // g.fillRect(int x,int y,int width,int height) // x 表示列(a%4),y表示行(a/4) g.fillRect((x + a % 4) * 10, (y + a / 4) * 10, 10, 10); } } // 画框架和堆积块 g.setColor(Color.red); for (int j = 0; j < map.length; j++) {// 行,多加了2行 for (int i = 0; i < map[i].length; i++) {// 列,多加了1列 if (map[j][i] == 3) { g.drawRect(i * 10, j * 10, 10, 10); } else if (map[j][i] == 1) {// 画堆积快 g.fillRect(i * 10, j * 10, 10, 10); } } } // 记分面板 if (score <= 120) { g.drawString("score:" + score, 170, 20); } else { g.setFont(drawFont); g.drawString("恭喜你胜利" + score, 10, 100); isStart = false; } // 当前块 g.drawString("当前块", 170, 60); for (int a = 0; a < 16; a++) { if (shapes[blockType][turnState][a] == 1) { g.fillRect(180 + (a % 4) * 10, 80 + (a / 4) * 10, 10, 10); } else { g.drawRect(180 + (a % 4) * 10, 80 + (a / 4) * 10, 10, 10); } } // 下一个 g.drawString("下一个", 170, 160); for (int a = 0; a < 16; a++) { if (shapes[blockType_copy][turnState_copy][a] == 1) { g.fillRect(180 + (a % 4) * 10, 180 + (a / 4) * 10, 10, 10); } else { g.drawRect(180 + (a % 4) * 10, 180 + (a / 4) * 10, 10, 10); } } } } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == menuItem_start) { if (JOptionPane.showConfirmDialog(this, "你确定新建游戏吗?") == 0) { jPanel.newMap(); // jPanel.nextBlock(); isStart = true; } } if (e.getActionCommand().equalsIgnoreCase("stop")) { menuItem_stop.setActionCommand("continue"); isStart = false; menuItem_stop.setText("继续"); } if (e.getActionCommand().equalsIgnoreCase("continue")) { menuItem_stop.setActionCommand("stop"); isStart = true; menuItem_stop.setText("暂停"); } if (e.getSource() == menuItem_end) { if (JOptionPane.showConfirmDialog(this, "你确定要退出吗?") == 0) { System.exit(0); } } } public static void main(String[] args) { Tetris te = new Tetris(); // 一个像素有10int的大小,纯手工调试,不要抄袭啊!!! te.setBounds(800, 60, 250, 305); te.setResizable(false); te.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); te.setVisible(true); } }
\
原文:http://blog.csdn.net/hncu1306602liuqiang/article/details/46572905