`
叶紫夜子
  • 浏览: 9364 次
  • 性别: Icon_minigender_2
社区版块
存档分类
最新评论

果蔬连连看

阅读更多
果蔬连连看

    像连连看、扫雷、五子棋等游戏从小就玩,我最爱玩的就是连连看了,闲下来就玩,连连看有很多种,像是宠物、石头、麻将、果蔬连连看等等,我最喜欢的还是果蔬连连看。当我们要做这个项目时,我第一个想做的就是连连看。
    其实这些游戏刚开始的做法都差不多,它们都是棋盘类游戏,就要先做一个界面,然后在画布上把棋盘画出来,有了前面的学习基础,这一步就很简单了。做这类游戏,最难的就是算法了。想连连看的算法,一定要事先想清楚,图片是怎样消掉的。还要清楚一点就是图片的消失只是一个表象,在幕后是操作数组。下面就是我做的果蔬连连看,一起看看吧。



    首先,要先做一个界面,然后将棋盘画在画布上。
    关于界面的做法,之前的几个项目中都有做过,要注意的是界面的布局设置,还有面板的放置位置。对于画棋盘,五子棋,黑白棋需要画出来,连连看其实没必要将棋盘显示的画出来,只需要将图片重绘在画布上即可。需要注意的是,重绘前一定要先获取画布。


1.定义配置信息的接口

/**
 * 
 * 配置信息的接口
 *
 */
public interface Config 
{
    // 左上角的点
     public static final int X0 = 10, Y0 = 30;   
    
    //简单
     public static final int ROWS0 = 7, COLUMNS0 = 9;   // 横线和竖线的条数
     int UI_WIDTH0 = 500;
    int UI_HEIGHT0 = 500; //初始界面大小

     //一般
     public static final int ROWS1 = 13, COLUMNS1 = 15;   // 横线和竖线的条数
     int UI_WIDTH1 = 800;
    int UI_HEIGHT1 = 800; //一般界面大小

     //困难
     public static final int ROWS2 = 13, COLUMNS2 = 19;   // 横线和竖线的条数
     int UI_WIDTH2 = 1000;
    int UI_HEIGHT2 = 800; //困难界面大小
	
     // 单元格大小
     public static final int SIZE = 50;

    // 图片大小
	public static final int CELL_SIZE = 50;
}



2.初始化中间的绘制面板

/**
 * 初始化中间绘制面板的方法
 */
    public DrawPanel()
     {
    	//设置大小
	this.setPreferredSize(new Dimension());
	    
         //设置背景色
	this.setBackground(new Color(0,255,255));
	   
	    	     
	//设置布局为流式居中对齐,间距为0
         FlowLayout flayout=new FlowLayout();
	this.setLayout(flayout);
	  
	//设置边框
	javax.swing.border.LineBorder border=new      javax.swing.border.LineBorder(Color.LIGHT_GRAY);
	this.setBorder(border);
      }


3.定义单元格和图片数组,并将图片放到数组中


 /**
 * 定义初始化数据的方法
 * @param rows 线的行数
 * @param columns 线的列数
 */
   
 public static void initData(int rows, int columns)
 {
   		
     //定义单元格和图片数组
      CELL = new int[rows + 1][columns + 1];
     CELL_IMG = new ImageIcon[rows - 1][columns - 1];
		
     // 创建随机数对象
      java.util.Random rd = new java.util.Random();

     //创建Integer型队列
      ArrayList<Integer> list = new ArrayList<Integer>();
		
//****************将元素加到队列中******************//
	    
     for (int i = 0; i < CELL_IMG.length * CELL_IMG[0].length / 2; i++) 
	{
			
	   // 随机一个数字
	   int num = rd.nextInt(30) + 1;
			
	   // 往队列中加两次,保证每个数字出现的次数都是偶数次
	   list.add(num);
	   list.add(num);
			
	}
       
     //将图片添加到图片数组中
      for (int i = 1; i < CELL.length - 1; i++) 
	{
	   for (int j = 1; j < CELL[i].length - 1; j++) 
	      {
	         // 取一个随机的下标
		int index = rd.nextInt(list.size());
				
		// 移除被随机到的下标对应的元素
		int t = list.remove(index);
		CELL[i][j] = t;
		CELL_IMG[i - 1][j - 1] = new ImageIcon("images/draw" + t + ".jpg");
						
	      }
	}
		
	//System.out.println(" "+CELL.length);
	}


4.重写paint()方法,将图片绘制到画布上


/**
 * 重写paint方法
 */
 public void paint(Graphics g)
  {
  	    
      //调用父类中的 paint方法
       super.paint(g);
  		
      if(!(DrawPanel.CELL==null))
  	    {
  		// 重绘图片
  		for (int i = 1; i < DrawPanel.CELL.length; i++) 
  		   {
  		      for (int j = 0; j <DrawPanel. CELL[i].length; j++) 
  			{

  			     // 根据下标计算每个单元格左上角的坐标
  			      int x1 = SIZE * j;
  			     int y1 = SIZE * i;

  			     if (DrawPanel.CELL[i][j] != 0) 
  			       {
  			          //如果单元格为空,画图片
  				 g.drawImage(DrawPanel.CELL_IMG[i-1][j-1].getImage(), x1, y1, SIZE,SIZE, null);

                                   }
  		        }
  		}
  	     }

  }




    然后就是给画布添加监听器,实现监听,当鼠标点击画布上的图标时,就会有相应的动作。


1.画布监听器要继承鼠标适配器

public class DrawListener extends MouseAdapter implements Config 



2.在鼠标点击式的方法中,获取鼠标点击处的坐标
3.计算该坐标在哪个单元格中
4.根据单元格,操作图片数组,即消去图片

/**
 * 鼠标点击时的方法
 */
public void mouseReleased(MouseEvent e)
    {
         //获得第一次点击的坐标
           int x=e.getX();
	int y=e.getY();
		
	if(count==0)
	{
	     //判断鼠标点击的位置是在哪个单元格中
	      r1=(y-Y0)/SIZE;
	     c1=(x-X0)/SIZE;
			
	     num1=DrawPanel.CELL[r1][c1];   
	     count++;
	}
	else
	{
	    r2=(y-Y0)/SIZE;
	    c2=(x-X0)/SIZE;
	    num2=DrawPanel.CELL[r2][c2];     
	    count--;
				
	//如果不是自己本身,是相同的图片,且不为空
	if((r1!=r2||c1!=c2)&&num1==num2&&num1!=0)
	{  
	    //如果某一个方法返回true
	    if(SuanFa.checkRow(r1,c1,r2,c2)
							||SuanFa.checkCulumn(r1,c1,r2,c2)||SuanFa.checkOne(r1, c1, r2, c2)
		 					||SuanFa.checkTwo1(r1, c1, r2, c2)||SuanFa.checkTwo2(r1, c1, r2, c2))
		{
						
		   //消去点击的图片
		    DrawPanel.CELL[r1][c1]=0;
		   DrawPanel.CELL[r2][c2]=0;
						
		   //刷新窗体
		   javax.swing.SwingUtilities.updateComponentTreeUI(fu);
		}
	  }
      }
		
  }



    最后就是算法了,关于算法,要先自己画图看看到底有几种消去图片的方式,搞清楚怎样才能消去,同行,同列,不同行,不同列,边界怎样消去等等,注意要用循环判断该单元格是否为空,只要途中遇到一个不为空,就不能连。

1.同行
/**
*同行的算法
*/
public static boolean checkRow(int r1,int c1,int r2,int c2)
	 {
		if(r1!=	r2)
		 {
			//如果不是同行,返回false
			return false;
		 }
		
		//如果是同行
		for(int i=Math.min(c1,c2)+1;i<Math.max(c1,c2);i++)
			{
				if(DrawPanel.CELL[r1][i]!=0)
				{
					//只要中途碰到一个不为空,就不能连
					return false;
				}
			}
			
			//如果该循环执行完,表示可以连
			return true;
		}

2.同列


/**
 * 判断同列可否相消的方法
 * @param r1点击的第一个点所在格子的下标
 * @param c1点击的第一个点所在格子的下标
 * @param r2点击的第二个点所在格子的下标
 * @param c2点击的第二个点所在格子的下标
 * @return  false或true
 */
public static boolean checkCulumn(int r1, int c1, int r2, int c2) 
	{

		if (c1 != c2) 
		{
			//如果不是同列,返回false
			return false;
		}
			
		//如果是同列
		for (int j = Math.min(r1, r2)+1; j < Math.max(r1, r2); j++) 
		{
			if (DrawPanel.CELL[j][c1] != 0) 
				{
				    //只要中途碰到一个不为空,就不能连
					return false;
				}
		}
			
			
			return true;
}

3.一个拐点

/**
* 有一个拐点的方法
* @param r1点击的第一个点所在格子的下标
* @param c1点击的第一个点所在格子的下标
* @param r2点击的第二个点所在格子的下标
* @param c2点击的第二个点所在格子的下标
* @return  false或true
*/
public static boolean checkOne(int r1, int c1, int r2, int c2) 
	{

	    if (DrawPanel.CELL[r1][c2] == 0 && checkRow(r1, c1, r1, c2)
				&& checkCulumn(r1, c2, r2, c2)) 
	    {
	    	//若果拐点为空,且连线上都为空  ,返回true
			
			return true;
        
		}
		
		if (DrawPanel.CELL[r2][c1] == 0 && checkRow(r2, c2, r2, c1)
				&& checkCulumn(r1, c1, r2, c1)) 
		{
			//若果拐点为空,且连线上都为空  ,返回true
		}
                  //否 则,返回false 
		return false;
	}

4.两个拐点
/**
* 有两个拐点的方法
* @param r1点击的第一个点所在格子的下标
* @param c1点击的第一个点所在格子的下标
* @param r2点击的第二个点所在格子的下标
* @param c2点击的第二个点所在格子的下标
* return false或true
*/
	
public static boolean checkTwo1(int r1, int c1, int r2, int c2) 
	{
		for (int i = 0; i < DrawPanel.CELL[0].length; i++) 
		{
			if (DrawPanel.CELL[r1][i] == 0 && DrawPanel.CELL[r2][i] == 0
					&& checkRow(r1, c1, r1, i) && checkRow(r2, c2, r2, i)
					&& checkCulumn(r1, i, r2, i)) 
			 {
				//若果拐点为空,且连线上都为空  ,返回true
				
				
				
				
				return true;
			 }
			
		}
		//否 则,返回false 
			return false;
	}	
    public static  boolean checkTwo2(int r1, int c1, int r2, int c2) 
     {
	     for(int j=0;j<DrawPanel.CELL.length;j++)
 
		   {
			  if(DrawPanel.CELL[j][c1]==0&&DrawPanel.CELL[j][c2]==0
					&&checkCulumn(r1,c1,j,c1)&&checkCulumn(r2,c2,j,c2)
					&& checkRow(j, c1, j, c2))
			 {
				//若果拐点为空,且连线上都为空  ,返回true
				
				return true;
			 }
		}
		//否 则,返回false 
		return false;
  }


整个项目中,最应该注意的问题就是传参的问题,像是在添加监听器是,一定要将画布传入。还有就是要注意单元格数组和图片数组的操作,数组初始化,当点击图片可以连接时,数组的值设为空等等。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics