⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gamepanel.java

📁 扫雷游戏实现
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
        statusLabel1.setForeground(OVER_COLOR);
        statusLabel1.setText("Game Over");
    }
        
    public void setActive(boolean b) {//设置游戏状态
        removeMouseListener(this);//移除原有的侦听器
        if (b) {//可以进行游戏
            addMouseListener(this);//添加侦听器
            //设置状态条面板
            statusLabel1.setForeground(ACTIVE_COLOR);
            statusLabel1.setText("Game begin   ");
            statusLabel2.setText(flagNum + "/" + mineNum);
        }
    }
        
    public void setGameParam(int mineNum, int r, int c) {//设置游戏参数
        if (mineNum <= 0 || r <= 0 || c <= 0 || mineNum >= r * c)
            throw new IllegalArgumentException("游戏参数设置错误!!!");
        w = c*32+(c-1)*2;//单元宽度
        h = r*32+(r-1)*2;//单元高度
        setPreferredSize(new Dimension(w, h));
        this.mineNum = mineNum;
        this.r = r;
        this.c = c;
        totalNum = r * c;
        
        //生成游戏数据
        cells = new FieldCell[r][c];
        //生成雷区
        for (int i=0; i<r; i++) {
            for (int j=0; j<c; j++) {
                cells[i][j] = new FieldCell();
            }
        }
        
        int count = 0;//扫雷计数器
        while (count < mineNum) {//随机埋雷
            int s = (int) (Math.random() * totalNum);//产生随机数
            FieldCell fc = cells[s/c][s%c];//产生随机位置
            if (!fc.isMine()) {
                fc.setMine(true);//埋雷
                count++;
            }
        }
        
        //计算某个位置相邻的地雷数
        for (int i=0; i<r; i++) {
            for (int j=0; j<c; j++) {
                if (!cells[i][j].isMine()) {//不是地雷的单元才显示相邻的地雷数
                    int num = 0;
                    if (i-1 >= 0) {//计算左侧3个相邻位置的雷数
                        if (j-1 >= 0 && cells[i-1][j-1].isMine())//左上位置
                            num++;
                        if (cells[i-1][j].isMine())//左中位置
                            num++;
                        if (j+1 < c && cells[i-1][j+1].isMine())//左下位置
                            num++;
                    }
                    { //计算上下2个相邻位置的雷数
                        if (j-1 >= 0 && cells[i][j-1].isMine())//上方位置
                            num++;
                        //if (cells[i][j].isMine())
                            //num++;
                        if (j+1 < c && cells[i][j+1].isMine())//下方位置
                            num++;
                    }
                    if (i+1 < r) { //计算右侧3个相邻位置的雷数
                        if (j-1 >= 0 && cells[i+1][j-1].isMine())//右上位置
                            num++;
                        if (cells[i+1][j].isMine())//右中位置
                            num++;
                        if (j+1 < c && cells[i+1][j+1].isMine())//右下位置
                            num++;
                    }
                    cells[i][j].setNumber(num);//设定相邻的地雷数
                } 
            } 
        } 
        
        // 重置游戏数据
        flagNum = 0;
        revealNum = 0;
    }
    
    protected void paintComponent(Graphics g) {//画出游戏界面
        g.setColor(Color.lightGray);
        g.fillRect(0, 0, w, h);
        for (int i=0; i<r; i++) {
            for (int j=0; j<c; j++) {
                cells[i][j].draw(g, j*34, i*34);
            }
        }
    }
            
    public void mouseClicked(MouseEvent e) {//MouseEvent鼠标事件处理
        int j = (e.getX() + 2) / 34;
        int i = (e.getY() + 2) / 34;
        FieldCell cell = cells[i][j];
        //如果该单元已经翻开,则返回
        if (cell.getState() == FieldCell.REVEALED)
            return;
        if (e.getButton() == MouseEvent.BUTTON1) {//按下鼠标按键1(左键),进行翻雷
            //如果已经扫雷(标上红旗),则返回
            if (cell.getState() == FieldCell.FLAGGED)
                return;
            if (cell.isMine()) {//如果该单元为地雷,则翻开后游戏结束(失败)
                cell.setState(FieldCell.REVEALED);
                setActive(false);
                revealAll();
                gameOver();
            } else {
                cell.setState(FieldCell.UNKNOWN);//先设成未扫单元
                reveal(i, j);//再翻雷
                if (checkVictory()) {//检查是否胜利
                    setActive(false);
                    gameWin();
                }
            }
        } else if (e.getButton() == MouseEvent.BUTTON3) {//按下鼠标按键3(右键),进行扫雷或标记疑问
            if (cell.getState() == FieldCell.UNKNOWN) {//对于未扫单元进行扫雷或疑问标记
                if (flagNum < mineNum) {//如果已扫雷数低于总雷数则进行扫雷
                    cell.setState(FieldCell.FLAGGED);
                    flagNum++;
                    statusLabel2.setText(flagNum+"/"+mineNum);
                    if (checkVictory()) {//检查是否胜利
                        setActive(false);
                        gameWin();
                    }
                } else {//如果已扫雷数不低于总雷数则进行疑问标记
                    cell.setState(FieldCell.DOUBTED);
                }
            } else if (cell.getState() == FieldCell.FLAGGED) {//对于已扫单元进行疑问标记
                cell.setState(FieldCell.DOUBTED);
                flagNum--;
                statusLabel2.setText(flagNum+"/"+mineNum);
            } else if (cell.getState() == FieldCell.DOUBTED) {//对于疑问标记单元则再设置成未扫单元
                cell.setState(FieldCell.UNKNOWN);
            }
        }
        repaint();//重画
    }
    
    private boolean checkVictory() {//检查是否胜利
        return flagNum + revealNum == totalNum;
    }
    
    //游戏失败时显示所有的地雷以及挖错的和标记错的位置
    private void revealAll() {
        for (int i=0; i<r; i++) {
            for (int j=0; j<c; j++) {
                FieldCell cell = cells[i][j];
                if (cell.isMine()) {
                    if (cell.getState() == FieldCell.UNKNOWN)
                        cell.setState(FieldCell.REVEALED);//显示地雷
                } else {
                    switch (cell.getState()) {
                        case FieldCell.FLAGGED:
                            cell.setState(FieldCell.WRONG_F);//显示挖错的地雷
                            break;
                        case FieldCell.DOUBTED:
                            cell.setState(FieldCell.WRONG_D);//显示标记错的地雷
                            break;
                    }
                }
            }
        }
    }
    
    //用递归的方法显示其它非地雷的位置
    private void reveal(int i, int j) {
        if (i < 0 || i >= r || j < 0 || j >= c)
            return;
        FieldCell cell = cells[i][j];
        if (cell.getState() == FieldCell.REVEALED 
                || cell.getState() == FieldCell.FLAGGED
                || cell.getState() == FieldCell.DOUBTED)
            return;
        cell.setState(FieldCell.REVEALED);
        revealNum++;
        if (cell.getNumber() != 0)
            return;
        reveal(i-1, j-1);
        reveal(i-1, j);
        reveal(i-1, j+1);
        reveal(i, j-1);
        reveal(i, j+1);
        reveal(i+1, j-1);
        reveal(i+1, j);
        reveal(i+1, j+1);
    }
    
    
    public void mouseEntered(MouseEvent e) {}
    
    public void mouseExited(MouseEvent e) {}
    
    public void mousePressed(MouseEvent e) {}
    
    public void mouseReleased(MouseEvent e) {}
    
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -