主页 > 网页UI

Java游戏开发——连连看

时间:2019-08-16 来源:开新视界

Linux编程
点击右侧关注,免费入门到精通!


来源java团长


游戏介绍:


“连连看”是一款来源于我国台湾的桌面小游戏,主要考验的是玩家们的眼力,在有限的时间内,只要能把所有能连接的相同图案,两个两个的找出来,每找到一对,它们就会自动消失,只要能把所有的图案全部消完即可获得胜利。所谓能够连接,是指无论横向还是纵向,从一个图案到另一个图案之间的连线拐角不能超过两个(中间的直线不超过三根),其中连线不能从尚未消去的图案上经过。


本次开发的连连看游戏运行效果如下图所示,游戏具有统计消去方块个数、打乱现有方块位置、智能辅助以及重开一局的功能。


使用到的素材文件夹如下:

游戏数据模型:


连连看的游戏界面是一个N*M的网格地图,每个网格显示一张图片;网格地图的信息使用二维数组来存储,每个数组元素存储对应网格地图中的每一个格子里的图片ID,如果图片ID非-1(BLANK_STATE)则绘制图片。


动物方块布局:


游戏地图信息初始化时,由于方块必须成对出现,需要引入一个临时的动态数组list,该list用来存储地图所有的图案ID信息,在这里我们是制作10*10的网格地图,一共10种图案,所以可以先向list里添加10组完全一样的图案ID,每组10个;创建二维数组map存储网格地图信息,初始化map里的每个数组元素为-1(BLANK_STATE),然后遍历map,按遍历顺序依次随机从list中取一个图案ID元素放入map并从list中移出刚才取出来的元素,遍历完成后返回map;代码实现如下:


public int[][] getMap(){

   ArrayList<Integer> list = new ArrayList<Integer>();//先将等量图片ID添加到list中

   for(int i=0;i<n*n/10;i++){      
     for(int j=0;j<count;j++){//每个图案种类的ID各添加一个,循环10次
     list.add(j);
     }      
   }    

 for(int i=0;i<n;i++){
   for(int j=0;j<n;j++){
     int index = (int) (Math.random()*list.size());//从list中随机取一个图片ID,并将其添加到数组中,再从list中删除掉它
     map[i][j] = list.get(index);
     list.remove(index);  
   }
 }

 return map;//返回一个图片随机生成的地图数组

 }


连通算法:


①直连方式


在直连方式中,要求两个选中的方块在同一行或者同一列(图1-1,图1-2),并且之间没有其他任何图案的方块,实现最简单。

图1-1

图1-2


②单拐点连通


相当于通过两个选中的方块划出一个矩形,两个方块是一对矩形的对角顶点,另外两个顶点中的某个顶点如果为BLANK_STATE并且可以同时与这两个方块直连,那就说明可以单拐点连通(图1-3)。

图1-3


③双拐点连通


这种方式的两个拐点z1,z2必定在两个选中的方块p1,p2所在的水平方向或者垂直方向的直线上(图1-4,图1-5)。

图1-4

图1-5


按p1(x1,y1)点向4个方向探测(此处的x1,y1为数组下标),例如向右探测,每次y1+1,判断(x1,y1+1)与p2(x2,y2)点可否形成单拐点连通性,如果可以形成连通,则两个拐点连通;如果超出图形右边界区域,则还需要判断两个拐点在选中方块的右侧,且两个拐点在图案区域之外连通的情况是否存在。这里可以简化为判断p2点(x2,y2)是否可以水平直通到右边界(图1-6)。

图1-6


经过上面的分析,对两个选中的方块是否可以消去算法流程图如下:

该功能属于鼠标点击事件的一部分,代码如下:


@Override
 public void mousePressed(MouseEvent e) 
{
   // TODO Auto-generated method stub

   Graphics g = this.getGraphics();

   int x = e.getX()-leftX;//点击位置x-偏移量x
   int y = e.getY()-leftY;//点击位置y-偏移量y
   int i = y/50;//对应数组行数,根据像素坐标转换成数组下标坐标
   int j = x/50;//对应数组列数
   if(x<0||y<0)//超出地图范围
     return ;



   if(isClick){//第二次点击

     if(map[i][j]!=BLANK_STATE){
       if(map[i][j]==clickId){//点击的是相同图片Id,但不是重复点击同一图片
         if(i==clickX&&j==clickY)
         return ;

         if(verticalLink(clickX,clickY,i,j)||horizontalLink(clickX,clickY,i,j)||oneCornerLink(clickX,clickY,i,j)||twoCornerLink(clickX,clickY,i,j)){//如果可以连通,画线连接,然后消去选中图片并重置第一次选中标识            
           drawSelectedBlock(j*50+leftX,i*50+leftY,g);
           drawLink(clickX,clickY,i,j);//画线连接
           isClick = false;  

         }else{
           clickId = map[i][j];//重新选中图片并画框
           clearSelectBlock(clickX,clickY,g);
           clickX = i;
           clickY = j;
           drawSelectedBlock(j*50+leftX,i*50+leftY,g);
         }

       }else{
         clickId = map[i][j];//重新选中图片并画框
         clearSelectBlock(clickX,clickY,g);
         clickX = i;
         clickY = j;
         drawSelectedBlock(j*50+leftX,i*50+leftY,g);
       }

     }

   }else{//第一次点击
     if(map[i][j]!=BLANK_STATE){
       //选中图片并画框
       clickId = map[i][j];
       isClick = true;
       clickX = i;
       clickY = j;
       drawSelectedBlock(j*50+leftX,i*50+leftY,g);
     }
   }
 }


其中isClick是用来标识是否第一次选中图案,clickId表示第一次选择图案对应的ID,clickX表示第一次选中图案的行下标,clickY表示第一次选中图案的列下标,如果第二次选中的图案与第一次选中的图案不同,重新选中;如果两次选择的图案相同,但是不连通,重新选中第二次选中的图片。


直连方式分为水平连通和垂直连通两种方式,分别使用horizontalLink()和verticalLink()进行判断:


//判断是否可以水平相连
 private boolean horizontalLink(int clickX1, int clickY1, int clickX2, int clickY2) {

   if(clickY1>clickY2){//保证y1<y2
     int temp1 = clickX1;
     int temp2 = clickY1;
     clickX1 = clickX2;
     clickY1 = clickY2;
     clickX2 = temp1;
     clickY2 = temp2;
   }

   if(clickX1==clickX2){//如果两个选中图片的所在行数相同,说明可能可以水平相联

     for(int i=clickY1+1;i<clickY2;i++){
       if(map[clickX1][i]!=BLANK_STATE){//如果两图片中间还有其他图片,说明不能直接水平相连
         return false;
       }
     }

     linkMethod = LINKBYHORIZONTAL;
     return true;
   }


   return false;
 }


 //判断是否可以垂直连接
 private boolean verticalLink(int clickX1, int clickY1, int clickX2, int clickY2) {

   if(clickX1>clickX2){//保证x1<x2
     int temp1 = clickX1;
     int temp2 = clickY1;
     clickX1 = clickX2;
     clickY1 = clickY2;
     clickX2 = temp1;
     clickY2 = temp2;
   }

   if(clickY1==clickY2){//如果两个选中图片的所在列数相同,说明可能可以垂直相联

     for(int i=clickX1+1;i<clickX2;i++){
       if(map[i][clickY1]!=BLANK_STATE){//如果两图片中间还有其他图片,说明不能直接垂直相连
         return false;
       }
     }

     linkMethod = LINKBYVERTICAL;


     return true;
   }



   return false;
 }


单拐点连通使用oneCornerLink()方法实现判断(z1存储拐点数组下标信息):


//判断是否可以通过一个拐点相连
 private boolean oneCornerLink(int clickX1, int clickY1, int clickX2, int clickY2) {

   if(clickY1>clickY2){//保证(x1,y1)是矩形的左上角或者左下角
     int temp1 = clickX1;
     int temp2 = clickY1;
     clickX1 = clickX2;
     clickY1 = clickY2;
     clickX2 = temp1;
     clickY2 = temp2;
   }

   if(clickX1<clickX2){//如果(x1,y1)位于矩形左上角

     //判断右上角是否为空并且可以直接与(x1,y1)和(x2,y2)相连接,(clickX1, clickY2)是右上角拐点下标
     if(map[clickX1][clickY2]==BLANK_STATE&&horizontalLink(clickX1, clickY1, clickX1, clickY2)&&verticalLink(clickX2,clickY2,clickX1,clickY2)){
       linkMethod = LINKBYONECORNER;
       z1 = new Node(clickX1,clickY2);
       return true;
     }

     //判断左下角是否为空并且可以直接与(x1,y1)和(x2,y2)相连接,(clickX2, clickY1)是左下角拐点下标
     if(map[clickX2][clickY1]==BLANK_STATE&&horizontalLink(clickX2, clickY2, clickX2, clickY1)&&verticalLink(clickX1,clickY1,clickX2, clickY1)){
       linkMethod = LINKBYONECORNER;
       z1 = 

相关阅读

  • Copyright © all rights reserved 版权所有 开新视界