swing练习挖雷(源代码)

/*
* Created on 2006-6-2
*
*/
package com.ftinternet;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
* @author *
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/

class MineButton extends JButton {
       
        private static final long serialVersionUID = -2004966127695755657L;

        public static final int MINE_BUTTON_WIDTH = 220;
        public static final boolean MINESTATUS_MINED        = true;
        public static final boolean MINESTATUS_ACTIVE        = false;
       
        private int XPos = 0;
        private int YPos = 0;
        public boolean MineStatus = MINESTATUS_ACTIVE;
        private int MineCount = -1;
        private boolean Suspected = false;
       
        public MineButton(int XPos, int YPos) {
                this.XPos = XPos;
                this.YPos = YPos;
               
                setSize(MINE_BUTTON_WIDTH, MINE_BUTTON_WIDTH);
                SetSuspected(false);
        }
       
        public int GetXPos() { return XPos; }
        public int GetYPos() { return YPos; }
       
        public boolean IsSuspected()
        {
                return Suspected;
        }

        public void SetSuspected(boolean IsSuspect)
        {
                Suspected = IsSuspect;
                if (!Suspected) setText("   ");
                else setText("x");
        }
       
        public boolean IsMined() {
                return MineStatus == MINESTATUS_MINED;
        }
       
        public void SetMine() {
                MineStatus = MINESTATUS_MINED;
        }
       
        public void Reset() {
                MineStatus = MINESTATUS_ACTIVE;
                SetSuspected(false);
                MineCount = -1;
                setBackground(Color.lightGray);
                setForeground(Color.black);
        }
       
        public void setMineCount(int mine) {
                MineCount = mine;
                setBackground(Color.white);
                switch (MineCount)
                {
                case 1:
                        setForeground(Color.blue);
                        break;
                case 2:
                        setForeground(Color.green);
                        break;
                case 3:
                        setForeground(Color.darkGray);
                        break;
                case 4:
                        setForeground(Color.cyan);
                        break;
                case 5:
                        setForeground(Color.magenta);
                        break;
                case 6:
                        setForeground(Color.orange);
                        break;
                case 7:
                        setForeground(Color.red);
                        break;
                }
        }
       
        public int getMineCount() { return MineCount; }
}

public class TestMine extends JFrame {
        private static final long serialVersionUID = -3295523726245939815L;

        private static Point[] AroundPoint = {
                new Point(-1, -1), new Point(0, -1), new Point(1, -1),
                new Point(-1,  0),                   new Point(1,  0),
                new Point(-1,  1), new Point(0,  1), new Point(1,  1)
        };

        private HashMap<String, MineButton> MineList = new HashMap<String, MineButton>();
        private int MineMapWidth = 0;
        private int MineMapHeight = 0;
        private int MineMapCount = 0;
        private boolean GameActive = false;
       
        JPanel pnlControl = new JPanel();
        JPanel pnlView = new JPanel();
        JLabel lbMineLeft = new JLabel("");
        JLabel lbMineOver = new JLabel("Game Over");
       
        private String GetMineCode(int width, int height)
        {
                return "M" + width + "-" + height;
        }
       
        private MineButton GetMineButton(int XPos, int YPos)
        {
                if (MineList.containsKey(GetMineCode(XPos, YPos)))
                        return (MineButton) MineList.get(GetMineCode(XPos, YPos));
                else
                        return null;
        }
       
        private MineButton GetMineButton(int Index) {
                return GetMineButton(Index % MineMapWidth, Index / MineMapWidth);
        }
       
        private void ResetMineMap()
        {
                for (int i = 0; i < MineMapWidth * MineMapHeight; i++)
                        GetMineButton(i).Reset();
        }
       
        private void InitMineMap()
        {
                Random rand = new Random();
               
                int rCount = MineMapCount;
                ResetMineMap();
                while (rCount > 0)
                {
                        int rPos = rand.nextInt(MineMapWidth * MineMapHeight);
                        MineButton mbTemp = GetMineButton(rPos);
                        if ((mbTemp == null) || mbTemp.IsMined()) continue;
                        mbTemp.SetMine();
                       
                        rCount--;
                }
               
                lbMineLeft.setText("" + MineMapCount);
                GameActive = true;
                pnlView.setEnabled(true);
                lbMineOver.setVisible(false);
        }
       
        private void GameOver(boolean Active)
        {
                GameActive = false;
                pnlView.setEnabled(false);
               
                if (Active) lbMineOver.setForeground(Color.green);
                else lbMineOver.setForeground(Color.red);
                lbMineOver.setVisible(true);
               
                repaint();
        }
       
        /**
         * 检查mbTemp1,mbTemp2是否相邻
         * @param mbTemp1
         * @param mbTemp2
         * @return
         */
        protected boolean IsNeighbor(MineButton mbTemp1, MineButton mbTemp2) {
                return (mbTemp1 != null) && (mbTemp2 != null)
                && Math.abs(mbTemp1.GetXPos() - mbTemp2.GetXPos()) + Math.abs(mbTemp1.GetYPos()  - mbTemp1.GetYPos()) == 1;
        }
       
        /**
         * 检查mbTemp1是否在mbTemp2在周围
         * @param mbTemp1
         * @param mbTemp2
         * @return
         */
        protected boolean IsAround(MineButton mbTemp1, MineButton mbTemp2) {
                return (mbTemp1 != null) && (mbTemp2 != null)
                && (Math.abs(mbTemp1.GetXPos() - mbTemp2.GetXPos()) < 2) && (Math.abs(mbTemp1.GetYPos() - mbTemp2.GetYPos()) < 2);
        }

        private boolean CheckPosition(int XPos, int YPos)
        {
                MineButton mbMine = GetMineButton(XPos, YPos);
                return ((mbMine != null) && mbMine.IsMined());
        }
       
        private int GetMineAround(int XPos, int YPos)
        {
                int Mines = 0;

                for (int i = 0; i < AroundPoint.length; i++)
                        if (CheckPosition(XPos + AroundPoint[i].x, YPos + AroundPoint[i].y)) Mines++;
               
                return Mines;
        }
       
        /**
         * 从(XPos, YPos)向周围扩展
         * @param XPos
         * @param YPos
         */
        private void ExplorMine(int XPos, int YPos)
        {
                MineButton mbMine = GetMineButton(XPos, YPos);
                if ((mbMine == null) || (mbMine.getMineCount() > -1) || mbMine.IsSuspected()) return;
               
                mbMine.setMineCount(GetMineAround(XPos, YPos));
                if (mbMine.getMineCount() > 0)
                        mbMine.setText("" + mbMine.getMineCount());
                else {
                        for (int i = 0; i < AroundPoint.length; i++)
                                ExplorMine(XPos + AroundPoint[i].x, YPos + AroundPoint[i].y);
                }
        }
       
        /**
         * 统计点(XPos, YPos)周围的情况
         * @param XPos
         * @param YPos
         * @return Point.x 周围的嫌疑个数,Point.y周围的未知个数
         */
        private void CheckSuspectPosition(int XPos, int YPos, Point info)
        {
                MineButton mbTemp = GetMineButton(XPos, YPos);
                if (mbTemp == null) return;
               
                if (mbTemp.IsSuspected()) info.x++;
                else if (mbTemp.getMineCount() < 0) info.y++;
        }

        private Point CalculatePositionAround(int XPos, int YPos)
        {
                Point around = new Point();
               
                for (int i = 0; i < AroundPoint.length; i++)
                        CheckSuspectPosition(XPos + AroundPoint[i].x, YPos + AroundPoint[i].y, around);
                return around;
        }
       
        /**
         * 从(XPos, YPos)处展开周围所有未探测的点都被认为非雷
         * @param XPos
         * @param YPos
         */
        private void FlashPosition(int XPos, int YPos)
        {
                MineButton mbTemp = GetMineButton(XPos, YPos);
                if ((mbTemp == null) || mbTemp.IsSuspected()) return;
               
                if (mbTemp.getMineCount() < 0) {
                        if (mbTemp.IsMined())
                        {
                                mbTemp.setText("x");
                                mbTemp.setBackground(Color.RED);
                                GameOver(false);
                        }
                        else
                                ExplorMine(XPos, YPos);
                }
        }
       
        /**
         * see also FlashPosition(int XPos, int YPos)
         * @param mbSender
         */
        private void FlashPositionAround(MineButton mbSender)
        {
                FlashPositionAround(mbSender.GetXPos(), mbSender.GetYPos());
        }
       
        private void FlashPositionAround(int XPos, int YPos)
        {
                for (int i = 0; i < AroundPoint.length; i++)
                        FlashPosition(XPos + AroundPoint[i].x, YPos + AroundPoint[i].y);
        }
       

        private void CalculatePosition(MineButton mbSender)
        {
                /**
                 *  计算(XPos, YPos) 附近雷的情况
                 */
                if (mbSender == null) return;
               
                Point around = CalculatePositionAround(mbSender.GetXPos(), mbSender.GetYPos());
               
                /** (XPos, YPos)周围雷已全部发现 */
                if (around.x == mbSender.getMineCount())
                        FlashPositionAround(mbSender);
        }
       
        private boolean FindAllMine() {
                int safemines = 0;
                for (int i = 0; i < MineMapWidth * MineMapHeight; i++)
                        if (GetMineButton(i).getMineCount() > -1) safemines++;
                return (safemines + MineMapCount) == MineMapWidth * MineMapHeight;
        }
               
        public TestMine() {
                this(9, 9, 10);
        }
       
        public TestMine(int Width, int Height, int Mines) {
                setDefaultCloseOperation(EXIT_ON_CLOSE);
               
                MineMapWidth = Width < 9 ? 9 : Width;
                MineMapHeight = Height < 9 ? 9 : Height;
                MineMapCount = 2 * Mines > MineMapWidth * MineMapHeight
                                        ? MineMapWidth * MineMapHeight / 2
                                        : Mines;
               
                getContentPane().add(pnlControl, BorderLayout.NORTH);
                pnlControl.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 2));
               
                JButton bRestart = new JButton("开 始");
                pnlControl.add(lbMineLeft);
               
                bRestart.addMouseListener(new MouseAdapter() {
                        public void mouseClicked(MouseEvent ae) {
                                InitMineMap();
                        }
                        });
                pnlControl.add(bRestart);
                pnlControl.add(lbMineOver);
               
                pnlView.setSize(MineButton.MINE_BUTTON_WIDTH * MineMapWidth, MineButton.MINE_BUTTON_WIDTH * MineMapHeight);
                getContentPane().add(pnlView, BorderLayout.CENTER);
                pnlView.setLayout(new GridLayout(MineMapHeight, MineMapWidth));
               
                for (int h = 0; h < MineMapHeight; h++)
                        for (int w = 0; w < MineMapWidth; w++)
                        {
                                MineButton mbMine = new MineButton(w, h);
                                pnlView.add(mbMine);
                                MineList.put(GetMineCode(w, h), mbMine);
                                mbMine.addMouseListener(new MouseAdapter() {
                                                public void mouseClicked(MouseEvent ae) {
                                                        if (!GameActive) return;
                                                        MineButton mbSender = (MineButton) ae.getSource();
                                                       
                                                        if (ae.getButton() == MouseEvent.BUTTON1) {
                                                                if (mbSender.IsSuspected()) return;
                                                                if (mbSender.getMineCount() != -1) {
                                                                        CalculatePosition(mbSender);
                                                                }
                                                                else if (mbSender.IsMined()) {
                                                                        mbSender.setText("x");
                                                                        mbSender.setBackground(Color.RED);
                                                                        GameOver(false);
                                                                        return;
                                                                }
                                                                else
                                                                        ExplorMine(mbSender.GetXPos(), mbSender.GetYPos());
                                                        }
                                                       
                                                        if (ae.getButton() == MouseEvent.BUTTON3) {
                                                                if (mbSender.getMineCount() > -1) return;
                                                               
                                                                mbSender.SetSuspected(!mbSender.IsSuspected());
                                                                if (mbSender.IsSuspected())
                                                                        lbMineLeft.setText("" + (Integer.parseInt(lbMineLeft.getText()) - 1));
                                                                else
                                                                        lbMineLeft.setText("" + (Integer.parseInt(lbMineLeft.getText()) + 1));
                                                        }
                                                        if (FindAllMine()) GameOver(true);
                                                }
                                        });
                        }
               
                InitMineMap();
               
                this.setTitle("扫雷:雷区----" + MineMapWidth + "x" + MineMapHeight + ":" + MineMapCount);
                pack();
        }
       
        public static void main(String[] args) {
                TestMine tm = new TestMine(9, 9, 10);
                tm.setVisible(true);
        }
}

你可能感兴趣的:(swing,String,null,Random,button,templates)