扫雷游戏制作全过程02 之 JButton 弯路

4 篇文章 0 订阅
4 篇文章 0 订阅

我看JButton(用了前文00的感官)长得很好看,于是决定用一个JButton来代表一个地雷块。而此时完全没有考虑标记地雷和判输判赢的实现。

首先在面板上生成width*height个JButton,生成之时通过查询mine[][]数组来为JButton的mine属性赋值。然后监听点击事件,如果被点击,则打开该块

(其实是切换JButton的背景图片)。

这是MyButton类:

class MyButton extends JButton
{
	private boolean is_mine = false;
  	private int status = 0;
	public MyButton()
	{
		this.setLayout(null);
		setIcon(new ImageIcon("a.png"));
		setMargin(new Insets(0,0,0,0));
		setIconTextGap(0);
		setBorderPainted(false);
		setBorder(null);
		setText(null);
		setRolloverIcon(new ImageIcon("b.png"));
		//setPressedIcon(new ImageIcon("c.png"));
                // setSelectedIcon(new ImageIcon("d.png"));
		this.addActionListener(new ActionListener()
		{
		    public void actionPerformed(ActionEvent event)
		    {
                         digOut();
		    }
		});
	}

	public void  beMarked()
        {
	   this.setIcon(new ImageIcon("beMarked.png"));
	}

         public void digOut()
	{
	     switch(status)
		 {
		    case -1:
			  this.setIcon(new ImageIcon("c.png"));
			  //setRolloverIcon(new ImageIcon("c.png"));
			break;
		    case 0:
			  this.setIcon(new ImageIcon("0.png"));
			  //setRolloverIcon(new ImageIcon("0.png"));
			break;
		    case 1:
			  this.setIcon(new ImageIcon("1.png"));
			  //setRolloverIcon(new ImageIcon("1.png"));
			break;
		    case 2:
			  this.setIcon(new ImageIcon("2.png"));
			  //setRolloverIcon(new ImageIcon("2.png"));
			break;
		    case 3:
			  this.setIcon(new ImageIcon("3.png"));
			  //setRolloverIcon(new ImageIcon("3.png"));
			break;
		    case 4:
			  this.setIcon(new ImageIcon("4.png"));
			  //setRolloverIcon(new ImageIcon("4.png"));
			break;
		    case 5:
			  this.setIcon(new ImageIcon("5.png"));
			  //setRolloverIcon(new ImageIcon("5.png"));
			break;
		    case 6:
			  this.setIcon(new ImageIcon("6.png"));
			  //setRolloverIcon(new ImageIcon("6.png"));
			break;
		    case 7:
			  this.setIcon(new ImageIcon("7.png"));
			  //setRolloverIcon(new ImageIcon("7.png"));
			break;
		    case 8:
			  this.setIcon(new ImageIcon("8.png"));
			  //setRolloverIcon(new ImageIcon("8.png"));
			break;
         }

	}

	public void setStatus(int copy_status)
	{
		status = copy_status;

	}
	public boolean getIsMine()
	{
	    return is_mine;
	}
}
生成地雷的Mine类多添加了一个方法getMineByLocation()

class Mine
{
	//雷区的长和宽及雷的个数
	final int width = 5;
	final int height = 4;
	final int mine_num = 6;
	//为了生成雷区方便
	private int[][] mine= new int[height+2][width+2];

	public Mine()
	{
		createMine();
		initMine();
	}

	public void createMine()
	{
		int num = 0;
		int[] x = new int[mine_num];
		int[] y = new int[mine_num];
		//用于判断是否重复
		boolean mark = true;

		while(num<mine_num)
		{
			x[num] = (int)(Math.random()*(height-1))+1;
			y[num] = (int)(Math.random()*(width-1))+1;

			mark = true;
			for(int i=0;i<num;i++)
			{
				if(x[num]==x[i]&&y[num]==y[i])
				 mark = false;
			}
			  if(mark)
				num++;
		}

		//布雷
		for(int i=0;i<mine_num;i++)
		{
		   mine[x[i]][y[i]] = -1;
		}
	}

	public void initMine()
	{
	   int mine_around = 0;

	   for(int i=1;i<=height;i++)
	   {
		 for(int j=1;j<=width;j++)
		 {
			if(mine[i][j]!=-1)
			{
			  for(int k=i-1;k<=i+1;k++)
				for(int l=j-1;l<=j+1;l++)
				  if(mine[k][l]==-1)
					 mine_around++;

			  mine[i][j]=mine_around;
			  mine_around = 0;
			}
		 }
	   }
	}
	/*新添加了一个方法,生成M也Button时用到*/
	public int getMineByLocation(int copy_x,int copy_y)
	{
	  return mine[copy_x][copy_y];
	}

	public int getWidth()
	{
		return width;
	}

	public int getHeight()
	{
		return height;
	}
}

主要的控制类为MyPanel

class MyPanel extends JPanel
{
        private MyButton button[];
	public MyPanel()
	{
	    setSize(850,700);

	    Mine mine = new Mine();
		button = new MyButton[mine.getWidth()*mine.getHeight()];
		for(int i=0;i<20;i++)
		{
		   button[i] = new MyButton();
		   add(button[i]);
		   /*因为生成的地雷数组有空边界,而初始化并不显示该边界*/
		   button[i].setStatus( mine.getMineByLocation(i%mine.width+1,i/mine.width+1));
		}
                try
		{
		  UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
		  SwingUtilities.updateComponentTreeUI(MyPanel.this);
		}
		catch(Exception e) { e.printStackTrace(); }
	}
}

最为关键的就是button[i].setStatus( mine.getMineByLocation(i%mine.width+1,i/mine.width+1));将Mine与JButton联系了起来。

下面给一个用来测试的类

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;


public class PlayMine
{
    public static void main(String[] args)
    {
	JFrame frame = new MyFrame();
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

class MyFrame extends JFrame
{
	public MyFrame()
	{
	    setTitle("移动");
	    setSize(850,700);
            JPanel panel = new MyPanel();
	    add(panel);
	    this.setFocusable(true);
	}
}
运行PlayMine就OK了。对了一定要记得把图片和类文件放在同一层的目录下!

a.pngb.pngc.png0.png1.png

2.png3.png4.png5.png6.png


7.png8.png

当时写到这里还是很happy的,可是正要继续的时候,要开始做标记了,发现问题来了。出在了JButton上。


这个阶段是一个犯错的阶段,警示自己以后着手写软件前一定要先想一想,而不是直接上手。不过亲身犯一次这样的错,我想同样的错误

以后犯得就会少一点了。

我把这一话的资源已经上传了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值