俄罗斯方块

来源:互联网 发布:彩虹岛封魔武器 20淘宝 编辑:程序博客网 时间:2024/06/10 16:55
package Game;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.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 {TetrisPanel tp = null;public Tetris() {// 添加菜单// 菜单条JMenuBar menubar = new JMenuBar();this.setJMenuBar(menubar);// 菜单JMenu menuGame = new JMenu("游戏");menubar.add(menuGame);// 菜单项JMenuItem mi1 = new JMenuItem("新游戏");mi1.setActionCommand("new");JMenuItem mi2 = new JMenuItem("暂停");mi2.setActionCommand("pause");JMenuItem mi3 = new JMenuItem("继续");mi3.setActionCommand("continue");JMenuItem mi4 = new JMenuItem("退出");mi4.setActionCommand("exit");menuGame.add(mi1);menuGame.add(mi2);menuGame.add(mi3);menuGame.add(mi4);// 菜单监听MenuListener menuListener = new MenuListener();mi1.addActionListener(menuListener);mi2.addActionListener(menuListener);mi3.addActionListener(menuListener);mi4.addActionListener(menuListener);// this.setBounds(500, 200, 220, 275);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setSize(220, 275);this.setLocation(500, 200);this.setResizable(false);tp = new TetrisPanel();this.getContentPane().add(tp);this.addKeyListener(tp.listener);}class MenuListener implements ActionListener {@Overridepublic void actionPerformed(ActionEvent e) {if (e.getActionCommand().equalsIgnoreCase("new")) {getContentPane().remove(tp);tp = new TetrisPanel();getContentPane().add(tp);getContentPane().validate(); // 校验当前容器,有刷新功能} else if (e.getActionCommand().equalsIgnoreCase("Pause")) {tp.getTimer().stop();} else if (e.getActionCommand().equalsIgnoreCase("continue")) {tp.getTimer().restart();} else if (e.getActionCommand().equalsIgnoreCase("exit")) {System.exit(0);}}}public static void main(String[] args) {Tetris t = new Tetris();t.setVisible(true);}}class TetrisPanel extends JPanel {private int map[][] = new int[13][23];// map[列号][行号]。真正的方块区是:21行*10列。边框(2列,1行)// 方块的形状:// 第一维代表方块类型(包括7种:S、Z、L、J、I、O、T)// 第二维代表旋转次数// 第三四维代表方块矩阵// shapes[type][turnState][i] i--> block[i/4][i%4]int shapes[][][] = new int[][][] {/* * 模板 { {0,0,0,0,0,0,0,0, 0,0,0,0, 0,0,0,0}, {0,0,0,0,0,0,0,0, 0,0,0,0, * 0,0,0,0}, {0,0,0,0,0,0,0,0, 0,0,0,0, 0,0,0,0}, {0,0,0,0,0,0,0,0, 0,0,0,0, * 0,0,0,0} } */// I (※把版本1中的横条从第1行换到第2行){ { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },{ 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 } },// S{ { 0, 0, 1, 1, 0, 1, 1, 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, 0, 1, 1, 0, 1, 1, 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 } },// Z 第3行: shapes[2][2][]{ { 1, 1, 0, 0, 0, 1, 1, 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, 1, 0, 0, 0, 1, 1, 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 } },// J{ { 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },{ 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },{ 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },{ 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },// O{ { 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, 0 } },// L{ { 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },{ 1, 1, 1, 0, 1, 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, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },// T{ { 0, 1, 0, 0, 1, 1, 1, 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, 1, 1, 0, 0, 1, 0, 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 } } };// 当前块的信息private int blockType; // 表示第几种形状private int turnState; // 表示这种形状的第几种状态private int x;// 当前块的x坐标(第几列的位置)private int y;// 当前块的y坐标(第几行的位置)TimeListerner listener = null;private int score = 0;private int delay = 1000;private Timer timer = null;public TetrisPanel() {newGame();nextBlock();}public void newGame() {// 初始化游戏框架for (int i = 0; i < 12; i++) {for (int j = 0; j < 21; j++) {if (i == 0 || i == 11) { // 第0列和最后一列map[i][j] = 3;  //边界} else {map[i][j] = 0; //活动区域}}map[i][21] = 3; // 最后一行}listener = new TimeListerner();timer = new Timer(delay, listener); //定时器timer.start();score = 0;  }private void nextBlock() {blockType = (int) (Math.random() * 1000) % 7; //七种方块方式turnState = (int) (Math.random() * 1000) % 4; //四种变换方式x = 4;y = 0;if (crash(x, y, blockType, turnState) == 0) {timer.stop();int op = JOptionPane.showConfirmDialog(null,"Game Over!....菜鸡,敢再来一局吗?!");if (op == JOptionPane.YES_OPTION) {newGame();} else if (op == JOptionPane.NO_OPTION) {System.exit(0);}}}public void down() {if (crash(x, y + 1, blockType, turnState) == 0) {// 判断和正下方某块碰撞:y+1add(x, y, blockType, turnState);nextBlock();} else {y++;}repaint(); // 刷新界面}public void left() {if (x >= 0) {x -= crash(x - 1, y, blockType, turnState);repaint();}}public void right() {if (x < 8) {x += crash(x + 1, y, blockType, turnState);repaint();}}public void turn() {if (crash(x, y, blockType, (turnState + 1) % 4) == 1) {turnState = (turnState + 1) % 4;repaint();}}private int crash(int x, int y, int blockType, int turnState) {for (int a = 0; a < 4; a++) { // 行号for (int b = 0; b < 4; b++) { // 列号// 只有当map[][]的值为1,3时,&运算的结果才可能会是1if ((shapes[blockType][turnState][a * 4 + b] & map[x + b + 1][y+ a]) == 1) {return 0;// 碰撞}}}return 1; // 代表没有碰撞}// 把所放置的当前块(4*4的格子)中实心块的位置信息记录到map[][]中,即对应元素赋1private 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[x + b + 1][y + a] = 1;}}}// 每添加一块,要看看能否消行tryDelLine();}public void tryDelLine() {// 从上往下,逐行判断是否该行中的每个块都是实心,是则消行(让上面所有的块移下一行,加分)for (int b = 0; b < 21; b++) {int c = 1;for (int a = 0; a < 12; a++) {c &= map[a][b];// 只有这一行的每个块都是实心或是框架,&运算结果才是1}if (c == 1) {score += 10;// 必须要倒着遍历(从上往下依次):下落一行for (int d = b; d > 0; d--) {for (int e = 0; e < 11; e++) {map[e][d] = map[e][d - 1];}}// 更改游戏难度(即加快下落速度)delay /= 2;timer.setDelay(delay);}}}@Overridepublic void paint(Graphics g) {super.paint(g); // 清除残影g.setColor(new Color(153, 51, 205));for (int j = 0; j < 16; j++) {if (shapes[blockType][turnState][j] == 1) {g.fillRect((x + 1 + j % 4) * 10, (y + j / 4) * 10, 10, 10);}}// 画俄罗斯方块游戏界面框架和 已经堆积的方块g.setColor(Color.red);for (int i = 0; i < 12; i++) { // 走列,x坐标方向for (int j = 0; j < 22; j++) { // 走列,x坐标方向// 画外框if (map[i][j] == 3) {g.setColor(Color.red);g.drawRect(i * 10, j * 10, 10, 10);}// 画堆积块if (map[i][j] == 1) {g.setColor(Color.red);g.fillRect(i * 10, j * 10, 10, 10);// 画填充块g.setColor(Color.yellow);g.drawRect(i * 10, j * 10, 10, 10);// 画轮廓线}}}// 显示游戏得分// 显示分数,同时为版面美观,在界面上再加点东西// 画方块区右侧部分g.setColor(Color.blue);g.setFont(new Font("aa", Font.BOLD, 18));g.drawString("score=" + score, 130, 20);g.setFont(new Font("aa", Font.PLAIN, 13));g.drawString("热爱盗版游戏", 130, 70);g.drawString("注意自我放纵", 130, 90);g.drawString("接受受骗上当。", 125, 110);g.drawString("过度游戏补脑,", 125, 130);g.drawString("沉迷游戏有益。", 125, 150);g.drawString("合理安排时间,", 125, 170);g.drawString("享受健康生活。", 125, 190);}class TimeListerner extends KeyAdapter implements ActionListener {@Overridepublic void actionPerformed(ActionEvent e) {down();}@Overridepublic void keyPressed(KeyEvent e) {switch (e.getKeyCode()) {case KeyEvent.VK_DOWN:down();break;case KeyEvent.VK_LEFT:left();break;case KeyEvent.VK_RIGHT:right();break;case KeyEvent.VK_UP:turn();}}}public Timer getTimer() {return timer;}}

原创粉丝点击