天天看點

swing練習挖雷(源代碼)

轉自http://student.csdn.net/space.php?uid=288365&do=blog&id=31861

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;

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();

        }

        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;

        }

        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;

        }

        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);

                }

        }

        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;

        }

        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);

                }

        }

        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)

        {

                if (mbSender == null) return;

                Point around = CalculatePositionAround(mbSender.GetXPos(), mbSender.GetYPos());

                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);

        }

}