alin613 2016-05-21 08:25 采纳率: 0%
浏览 2009

JAVA编写俄罗斯方块问题,键盘监听事件不能响应,请大神指点!!!

本人开发环境,MyEclipse8.5,安装JDK版本为1.7:键盘监听器不能相应。
但如果使用MyEclipse自带的JDK的话,键盘监听事件会有响应,但是需要重新加载JDK,请求大神指点原因!!!程序入口在类Tetris中,键盘监听事件也在此类中
#类Cell

 package com.MyTetris;

import java.awt.image.BufferedImage;

public class Cell {
    private int row;
    private int col;
    private BufferedImage image; // 贴图

    /**
     * 构造器
     * 
     * @param row
     * @param col
     * @param image
     */
    public Cell(int row, int col, BufferedImage image) {
        super(); // 调用Object构造器
        this.row = row;
        this.col = col;
        this.image = image;
    }

    public int getRow() {
        return row;
    }

    public void setRow(int row) {
        this.row = row;
    }

    public int getCol() {
        return col;
    }

    public void setCol(int col) {
        this.col = col;
    }

    public BufferedImage getImage() {
        return image;
    }

    public void setImage(BufferedImage image) {
        this.image = image;
    }
    /**
     * 重写toString方法,方便调试
     */
    public String toString() {
        return row + "," + col;
    }

    public void moveRigth() {
        col++;
    }

    public void moveLeft() {
        col--;
    }

    public void softDrop() {
        row++;
    }

}

#类Tetromino

 package com.MyTetris;

import java.util.Arrays;
import java.util.Random;

public abstract class Tetromino extends Object {
    protected Cell[] cells = new Cell[4];
    protected Stage[] stages; // 不同的方块旋转所用的数据不一样
    protected int index = 10000; // 取第几组数据旋转,index指下标

    /**
     * 用于存储方块旋转时的数据
     * 
     * @author Administrator
     * 
     */
    protected class Stage {
        int row0, col0;
        int row1, col1;
        int row2, col2;
        int row3, col3;

        public Stage(int row0, int col0, int row1, int col1, int row2,
                int col2, int row3, int col3) {
            super();
            this.row0 = row0;
            this.col0 = col0;
            this.row1 = row1;
            this.col1 = col1;
            this.row2 = row2;
            this.col2 = col2;
            this.row3 = row3;
            this.col3 = col3;
        }

    }

    /**
     * 随机生成7种方块之一,是公共方法 。 工厂方法:用于生产(创建)一个对象的方法,封装了复杂的创建过程,方便使用 用在创建对象过程复杂的情况
     */
    public static Tetromino randomOne() {
        Random random = new Random();
        int type = random.nextInt(7); // 随机生成[0,7)
        switch (type) {
        case 0:
            return new T();
        case 1:
            return new I();
        case 2:
            return new S();
        case 3:
            return new O();
        case 4:
            return new J();
        case 5:
            return new L();
        case 6:
            return new Z();
        }
        return null; // 必须写,不然编译时报错:编译时不看对象,只看引用类型
    }

    /**
     * 测试方法,用来测试随机生成方法
     */
    public String toString() {
        return Arrays.toString(cells);
    }

    /**
     * 当前对象的4格方块整体向左移动
     */
    public void moveLeft() {
        cells[0].moveLeft();
        cells[1].moveLeft();
        cells[2].moveLeft();
        cells[3].moveLeft();
    }

    public void moveRigth() {
        for (int i = 0; i < cells.length; i++) {
            cells[i].moveRigth();
        }
    }

    public void softDrop() {
        this.cells[0].softDrop();
        this.cells[1].softDrop();
        this.cells[2].softDrop();
        this.cells[3].softDrop();
    }

    /**
     * 向右旋转算法
     */
    public void rotateRigth() {
        // 1、计算index++
        // 2、获取Sn(4组数据0,1,2,3)
        // 3、获取当前轴
        // 4、格子0是轴,不变
        // 5、格子1的行列变成:轴+Sn[1]
        // 6、格子2的行列变成:轴+Sn[2]
        // 7、格子3的行列变成:轴+Sn[3]
        index++;
        Stage s = stages[index % stages.length];
        Cell o = cells[0];
        int row = o.getRow();
        int col = o.getCol();
        cells[1].setRow(row + s.row1);
        cells[1].setCol(col + s.col1);
        cells[2].setRow(row + s.row2);
        cells[2].setCol(col + s.col2);
        cells[3].setRow(row + s.row3);
        cells[3].setCol(col + s.col3);
    }

    public void rotateLeft() {
        index--;
        Stage s = stages[index % stages.length];
        Cell o = cells[0];
        int row = o.getRow();
        int col = o.getCol();
        cells[1].setRow(row + s.row1);
        cells[1].setCol(col + s.col1);
        cells[2].setRow(row + s.row2);
        cells[2].setCol(col + s.col2);
        cells[3].setRow(row + s.row3);
        cells[3].setCol(col + s.col3);
    }
}

class T extends Tetromino {
    public T() {
        /**
         * 格子的出场位置
         */
        cells[0] = new Cell(0, 4, Tetris.T);
        cells[1] = new Cell(0, 3, Tetris.T);
        cells[2] = new Cell(0, 5, Tetris.T);
        cells[3] = new Cell(1, 4, Tetris.T);
        stages = new Stage[4];
        stages[0] = new Stage(0, 0, 0, -1, 0, 1, 1, 0); // s0
        stages[1] = new Stage(0, 0, -1, 0, 1, 0, 0, -1); // s1
        stages[2] = new Stage(0, 0, 0, 1, 0, -1, -1, 0); // s2
        stages[3] = new Stage(0, 0, 1, 0, -1, 0, 0, 1); // s3

    }

}

class I extends Tetromino {
    public I() {
        cells[0] = new Cell(0, 4, Tetris.I);
        cells[1] = new Cell(0, 3, Tetris.I);
        cells[2] = new Cell(0, 5, Tetris.I);
        cells[3] = new Cell(0, 6, Tetris.I);
        stages = new Stage[2];
        stages[0] = new Stage(0, 0, 0, -1, 0, 1, 0, 2);
        stages[1] = new Stage(0, 0, -1, 0, 1, 0, 2, 0);
    }
}

class S extends Tetromino {
    public S() {
        cells[0] = new Cell(0, 4, Tetris.S);
        cells[1] = new Cell(0, 5, Tetris.S);
        cells[2] = new Cell(1, 3, Tetris.S);
        cells[3] = new Cell(1, 4, Tetris.S);
        stages = new Stage[2];
        stages[0] = new Stage(0, 0, 0, 1, 1, -1, 1, 0);
        stages[1] = new Stage(0, 0, 1, 0, -1, -1, 0, -1);
    }

}

class J extends Tetromino {
    public J() {
        cells[0] = new Cell(0, 4, Tetris.J);
        cells[1] = new Cell(0, 3, Tetris.J);
        cells[2] = new Cell(0, 5, Tetris.J);
        cells[3] = new Cell(1, 5, Tetris.J);
        stages = new Stage[4];
        stages[0] = new Stage(0, 0, 0, -1, 0, 1, 1, 1);
        stages[1] = new Stage(0, 0, -1, 0, 1, 0, 1, -1);
        stages[2] = new Stage(0, 0, 0, 1, 0, -1, -1, -1);
        stages[3] = new Stage(00, 0, 1, 0, -1, 0, -1, 1);
    }

}

class L extends Tetromino {
    public L() {
        cells[0] = new Cell(0, 4, Tetris.L);
        cells[1] = new Cell(0, 3, Tetris.L);
        cells[2] = new Cell(0, 5, Tetris.L);
        cells[3] = new Cell(1, 3, Tetris.L);
        stages = new Stage[4];
        stages[0] = new Stage(0, 0, 0, -1, 0, 1, -1, 1);
        stages[1] = new Stage(0, 0, -1, 0, 1, 0, 1, 1);
        stages[2] = new Stage(0, 0, 0, 1, 0, -1, 1, -1);
        stages[3] = new Stage(0, 0, 1, 0, -1, 0, -1, -1);

    }

}

class O extends Tetromino {
    public O() {
        cells[0] = new Cell(0, 4, Tetris.O);
        cells[1] = new Cell(0, 5, Tetris.O);
        cells[2] = new Cell(1, 4, Tetris.O);
        cells[3] = new Cell(1, 5, Tetris.O);
        stages = new Stage[2];
        stages[0] = new Stage(0, 0, 0, 1, 1, 0, 1, 1);
        stages[1] = new Stage(0, 0, 0, 1, 1, 0, 1, 1);
    }

}

class Z extends Tetromino {
    public Z() {
        cells[0] = new Cell(1, 4, Tetris.Z);
        cells[1] = new Cell(0, 3, Tetris.Z);
        cells[2] = new Cell(0, 4, Tetris.Z);
        cells[3] = new Cell(1, 5, Tetris.Z);
        stages = new Stage[2];
        stages[0] = new Stage(0, 0, -1, -1, -1, 0, 0, 1);
        stages[1] = new Stage(0, 0, -1, 1, 0, 1, 1, 0);
    }

}

#类Tetris

 package com.MyTetris;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Tetris extends JPanel {

    public static final int ROWS = 20;
    public static final int COLS = 10;
    /** 墙 */
    private Cell[][] wall = new Cell[ROWS][COLS];

    /** 正在下落的方块 */
    private Tetromino tetromino;
    /** 下一个进场的方块 */
    private Tetromino nextOne;
    /** 消失的行数 */
    private int lines;
    /** 得分 */
    private int score;

    /** 定时器 */
    private Timer timer;
    /** 得分表,对应销毁行数得分 */
    private int[] souseTable = new int[] { 0, 10, 100, 1000, 10000 };

    /**
     * 在Tetris中添加背景图片引用
     */
    private static BufferedImage backGround;
    private static BufferedImage gameOver;
    public static BufferedImage T;
    public static BufferedImage I;
    public static BufferedImage S;
    public static BufferedImage J;
    public static BufferedImage L;
    public static BufferedImage Z;
    public static BufferedImage O;

    // 静态代码块
    static {
        try {
            // 图片加载,注意:Tetris类必须与tetris.png(图片)在一个包中,图片名字不能错
            backGround = ImageIO.read(Tetris.class.getResource("tetris.png"));
            gameOver = ImageIO.read(Tetris.class.getResource("game-over.png"));
            T = ImageIO.read(Tetris.class.getResource("T.png"));
            I = ImageIO.read(Tetris.class.getResource("I.png"));
            S = ImageIO.read(Tetris.class.getResource("S.png"));
            J = ImageIO.read(Tetris.class.getResource("J.png"));
            L = ImageIO.read(Tetris.class.getResource("L.png"));
            O = ImageIO.read(Tetris.class.getResource("O.png"));
            Z = ImageIO.read(Tetris.class.getResource("Z.png"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 重写paint方法
     */
    @Override
    public void paint(Graphics g) {
        // background:图片对象;0, 0:图片位置,与画板顶角位置相同,图片有多大,展示多大
        // 绘制图片背景
        g.drawImage(backGround, 0, 0, null);
        g.translate(15, 15); // 整体向下漂移
        paintWall(g); // 画墙
        paintTetromino(g); // 画正在下落的格子
        paintNextOne(g); // 画下一个出场的格子
        paintScore(g);
    }

    /**
     * 画分数
     * 
     * @param g
     */
    public void paintScore(Graphics g) {
        int x = 294;
        int y = 160;
        // 设置分数和销毁行数的字体颜色
        g.setColor(new Color(0xD667799));
        Font font = new Font(Font.MONOSPACED, Font.BOLD, 28);
        g.setFont(font);
        g.drawString("SCORE:" + score, x, y);
        y += 56;
        g.drawString("LINES:" + lines, x, y);
    }

    /**
     * 封装绘制正在下落的格子的算法
     */
    public void paintTetromino(Graphics g) {
        if (tetromino == null) {
            return;
        }
        Cell[] cells = tetromino.cells;
        for (int i = 0; i < cells.length; i++) {
            // cells指下落的所有格子
            // 将正在下落的某一个格子的引用赋值给cell
            Cell cell = cells[i];
            int x = cell.getCol() * CELL_SIZE;
            int y = cell.getRow() * CELL_SIZE;
            g.drawImage(cell.getImage(), x, y, null);
        }
    }

    /**
     * 绘制下一个要出场的格子的算法
     */
    public void paintNextOne(Graphics g) {
        if (nextOne == null) {
            return;
        }
        Cell[] cells = nextOne.cells;
        for (int i = 0; i < cells.length; i++) {
            Cell cell = cells[i];
            int x = (cell.getCol() + 10) * CELL_SIZE;
            int y = (cell.getRow() + 1) * CELL_SIZE;
            g.drawImage(cell.getImage(), x, y, null);
        }
    }

    /**
     * 封装了绘制墙的算法
     */
    private static final int CELL_SIZE = 26;

    private void paintWall(Graphics g) {
        for (int row = 0; row < wall.length; row++) {
            for (int col = 0; col < wall[row].length; col++) {
                Cell cell = wall[row][col];
                int x = col * CELL_SIZE;
                int y = row * CELL_SIZE;
                if (cell == null) {
                    g.drawRect(x, y, CELL_SIZE, CELL_SIZE);
                } else {
                    g.drawImage(cell.getImage(), x, y, null);
                }
            }
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("1111");
        JFrame frame = new JFrame("Tetris");
        Tetris tetris = new Tetris(); // Tetris继承了JPanel,所以Tetris就是面板
        frame.add(tetris);
        frame.setSize(541, 588);
        frame.setLocationRelativeTo(null);
        /**
         * 设置默认关闭操作 operation操作
         */
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true); // 尽快调用paint()方法
        tetris.action();
    }

    /**
     * 添加软件启动(action)方法
     */
    public void action() {
        // wall[1][8] = new Cell(0, 0, T);
        // wall[8][2] = new Cell(0, 0, J);
        // Tetromino引用了randomOne创建的对象
        tetromino = Tetromino.randomOne();
        nextOne = Tetromino.randomOne();
        this.repaint(); // 重新绘制界面,尽快自动自动调用paint()方法
        KeyListener l = new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                int key = e.getKeyCode();
                switch (key) {
                case KeyEvent.VK_RIGHT:
                    // tetromino.moveRigth();
                    System.out.println("按下->键");
                    Tetris.this.moveRigthAction();
                    break;
                case KeyEvent.VK_LEFT:
                    // tetromino.moveLeft();
                    moveLeftAction();
                    break;
                case KeyEvent.VK_DOWN:
                    // tetromino.softDrop();
                    softDropAction();
                    break;
                case KeyEvent.VK_SPACE:
                    hardDropAction();
                    break;
                case KeyEvent.VK_UP:
                    // tetromino.rotateRigth();
                    rotateRigthAction();
                }
                repaint();
            }
        };
        this.addKeyListener(l);
        this.setFocusable(true);
        // 添加定时任务,让方块定时下落
        timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                softDropAction();
                repaint();
            }
        };
        timer.schedule(task, 1000, 1000);
    }

    /**
     * 变形方法
     */
    public void rotateRigthAction() {
        tetromino.rotateRigth();
        if (outOfBounds() || coincide()) {
            tetromino.rotateLeft();
        }
    }

    /**
     * 正在下落的4格方块右移
     */
    public void moveRigthAction() {
        // 正在下落的方块右移
        tetromino.moveRigth();
        // 判断是否出界;coincide:重合;检查4格方块是否与墙上方块是否重合
        if (outOfBounds() || coincide()) {
            // 如果出界,立刻左移
            tetromino.moveLeft();
        }
    }

    /**
     * 正在下落的4格方块左移
     */
    public void moveLeftAction() {
        tetromino.moveLeft();
        if (outOfBounds() || coincide()) {
            tetromino.moveRigth();
        }
    }

    /**
     * 检查正在下落的格子是否出界
     * 
     * @return
     */
    public boolean outOfBounds() {
        // 正在下落的4个格子中任意一个格子出界,就是出界
        Cell[] cells = tetromino.cells;
        for (int i = 0; i < cells.length; i++) {
            Cell cell = cells[i];
            int row = cell.getRow();
            int col = cell.getCol();
            if (row < 0 || row >= ROWS || col < 0 || col >= COLS) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断格子是否重合
     * 
     * @return
     */
    public boolean coincide() {
        Cell[] cells = tetromino.cells;
        for (int i = 0; i < cells.length; i++) {
            Cell cell = cells[i];
            int row = cell.getRow();
            int col = cell.getCol();
            if (wall[row][col] != null) {
                return true;
            }
        }
        return false;
    }

    /**
     * 下落方法,直接下落到底部,并且进入到墙内
     */
    public void hardDropAction() {
        while (canDrop()) {
            tetromino.softDrop();
        }
        landIntoWall();
        int lines = destroyLines();
        this.lines += lines;
        this.score += souseTable[lines];
        if (!isGameOver()) {
            tetromino = nextOne;
            nextOne = tetromino.randomOne();
        }
    }

    /**
     * 下落方法,一格一格的下落
     */
    public void softDropAction() {
        // 1、如果4格方块能下落,就下落
        // 2、如果不能下落,就着陆到墙里面
        // 3、检查行是否满,销毁已经慢的行
        // 4、检查游戏是否结束,如果没有结束,就产生下一个方块
        if (canDrop()) {
            tetromino.softDrop();
        } else {
            this.landIntoWall();
            int lines = destroyLines();
            // 计算销毁的行数
            this.lines = this.lines + lines;
            // 计算得分
            this.score = this.score + souseTable[lines];
            if (!isGameOver()) {
                tetromino = nextOne;
                nextOne = tetromino.randomOne();
            }
        }
    }

    /**
     * 检查方块是否能够下落
     */
    private boolean canDrop() {
        // 1、4格方块的任意一个格子的行达到19,就不能下落
        // 2、4格方块的任意一个格子,对应墙上的下方出现格子,则不能下落
        // 3、先判断第一 种情况,不然会出现下标越界的错误
        Cell[] cells = tetromino.cells;
        for (int i = 0; i < cells.length; i++) {
            Cell cell = cells[i];
            int row = cell.getRow();
            if (row == ROWS - 1) {
                return false;
            }
        }
        // 判断格子下方的墙上是否有格子
        for (int i = 0; i < cells.length; i++) {
            Cell cell = cells[i];
            int row = cell.getRow();
            int col = cell.getCol();
            if (wall[row + 1][col] != null) {
                return false;
            }
        }
        return true;
    }

    /**
     * 着陆到墙里面
     */
    private void landIntoWall() {
        // 获取每个格子的行、列,根据每个格子的位置,将格子订到墙上
        Cell[] cells = tetromino.cells;
        for (Cell cell : cells) {
            int row = cell.getRow();
            int col = cell.getCol();
            wall[row][col] = cell;
        }
    }

    /**
     * 销毁已经满的行,返回销毁行数
     */
    private int destroyLines() {
        // 从0~19逐行查找,如果找到满行,就删除这行
        int lines = 0;
        for (int row = 0; row < ROWS; row++) {
            if (isFullCells(row)) {
                deleteRow(row);
                lines++;
            }
        }
        return lines;
    }

    /**
     * 检查row行的格子是否是满的
     * 
     * @param row
     * @return
     */
    private boolean isFullCells(int row) {
        Cell[] line = wall[row];
        /**
         * for(int i=0;i<line.length;i++){ Cell cell = line[i]; }
         */
        for (Cell cell : line) {
            if (cell == null) {
                return false;
            }
        }
        return true;
    }

    /**
     * 删除row行格子
     * 
     * @param row
     */
    private void deleteRow(int row) {
        for (int i = row; i >= 1; i--) {
            // 复制:从wall[i-1] -> wall[i]
            System.arraycopy(wall[i - 1], 0, wall[i], 0, COLS);
        }
        Arrays.fill(wall[0], null);
    }

    /**
     * 检查游戏是否结束
     */
    private boolean isGameOver() {
        // 如果下一个方块没有出场位置了,则游戏结束:就是下一个出场的方块每个格子行列对应的墙上位置如果有方块,就游戏结束
        Cell[] cells = nextOne.cells;
        for (int i = 0; i < cells.length; i++) {
            Cell cell = cells[i];
            int row = cell.getRow();
            int col = cell.getCol();
            if (wall[row][col] != null) {
                return true;
            }
        }
        return false;
    }
}

  • 写回答

1条回答

报告相同问题?

悬赏问题

  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥15 绘制多分类任务的roc曲线时只画出了一类的roc,其它的auc显示为nan
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?