连连看设计思路与源码[一]-地图类

一.地图的生成

在上一篇文章中,我们已经试玩了本连连看的DEMO了.而地图是由一个由M*N个的矩形图案组成的.因此我们可以设定地图的行数为ROWS,列数为COLS,然后用一个二维数组来存储地图元素MapArray[ROWS][COLS],其中每个数字代表一种图案.而0则为通路,也即无图.所以,我们的地图数组可能是以下这样的一组数据

[[0,0,0,0,0,0],
 [0,1,2,1,3,0],
 [0,4,4,2,5,0],
 [0,6,5,6,3,0],
 [0,0,0,0,0,0]]

想想为何要在周围的一圈加上0?答案在以后的寻路代码中解答.

那么,这样的地图有什么特点呢?

  1. 地图中的每一个数字的个数都是偶数,也即都是成对的出现
  2. 地图的排列必须是随机排列的.
  3. 地图中的每一个数字的种类不能大于已有的图案的个数

那么一共有多少对大于0的数字呢?一共是(ROWS-2)*(COLS-2)/2对.那么初始地图的设计思路便是,先用一个一维的临时数组,tempArray,成对的往这个数组里推一个随机的大于0的数字进去,一共推(ROWS-2)*(COLS-2)/2次,则此时的tempArray的元素可能为,[2,2,3,3,1,1,6,6,4,4,5,5],接着再通过数组的自定义排序函数将数组打乱最后再将此数组转化为二维的数组并同时在周围加多一圈的0以后,即为我们的初始地图了.以下是生成初始地图的代码:

        public static const COLS:uint = 20;//列数
        public static const ROWS:uint = 16;//行数

        private var picCounts:uint = 20;//所有图片数
       
        public var MapArray:Array;
       
        public function Map(){
            MapArray = new Array();
            var tempArray:Array = new Array();
            for(var i:uint=0;i<(Map.COLS-2)*(Map.ROWS-2)/2;i++){
                var t:uint = Math.random()*picCounts+1;
                tempArray.push(t,t);               
            }
           
            tempArray.sort(Map.randomSort);                       
            var q:Array = new Array();
            for(i=0;i<Map.COLS;q.push(0),i++);
            MapArray.push(q);
           
            for(i=0;i<Map.ROWS-2;i++){
                var arr:Array = new Array();
                arr.push(0);//前面加上0
                for(var j:uint=0;j<Map.COLS-2;j++){
                    arr.push(tempArray[i*(Map.COLS-2)+j]);
                }
                arr.push(0);//后面加上0
                MapArray.push(arr);
            }
            MapArray.push(q);           
        }
       
        //数组随机排序帮助函数
        public static function randomSort(a:Object,b:Object):Number{
            return Math.pow(-1,Math.floor(Math.random()*2));
        }

二.地图的重排

我们在玩的过程中,有时会出现死局的情况,就是无法再找到一对可以连上的图案,例如下面的情况

[[0,0,0,0,0,0],
 [0,1,2,0,0,0],
 [0,2,1,0,0,0],
 [0,0,0,0,0,0],
 [0,0,0,0,0,0]]

1也好,2也好,都各自不能相连了,所以此时就只能对原地图进行重排,也即洗牌.当然,洗牌后的位置不能变了,变的,只是原来位置上的图案.所以洗牌后的数据可能就是:

[[0,0,0,0,0,0],
 [0,1,2,0,0,0],
 [0,1,2,0,0,0],
 [0,0,0,0,0,0],
 [0,0,0,0,0,0]]

以下是洗牌的代码,思路在注释当中

//对无解的数组进行重新洗牌
        public function cutCard():void{
            //首先提取所有大于0的数据存于一个临时数组arr里面
            var arr:Array = new Array();
            for(var i:uint=0;i<Map.ROWS;i++){
                for(var j:uint=0;j<Map.COLS;j++){
                    if(MapArray[i][j]>0)
                        arr.push(MapArray[i][j]);
                }
            }
            //接着再对arr进行随机排序
            arr.sort(Map.randomSort);
            //新数组替换原来的数据
            var arrCount:uint=0;//arr数组的下标
            for(i=0;i<Map.ROWS;i++){
                for(j=0;j<Map.COLS;j++){
                    if(MapArray[i][j]>0){
                        MapArray[i][j]=arr[arrCount];
                        arrCount++;
                    }
                }
            }           
        }

三.检测游戏是否结束

检测游戏结束的方法就是遍历整个数组,只要全为0则游戏结束,所以只要在遍历的过程中,一发现有非0的数字,则代表游戏仍然还没通关.以下是代码:

//检测游戏是否已经结束
        public function gameFinished():Boolean{
            for(var i:uint=0;i<Map.ROWS;i++){
                for(var j:uint=0;j<Map.COLS;j++){
                    if(MapArray[i][j]>0)return false;
                }
            }
            return true;
        }

四.地图的模式

这也是本DEMO的一个重点或者也说是一个亮点吧.就是在每消掉一对图案以后,剩下的图案的堆挤方式,例如有所有的图案都往左靠,或者都往中靠,往上往下往右等,例如数组

[[0,0,0,0,0,0],
 [0,0,1,0,1,0],
 [0,2,0,0,2,0],
 [0,2,2,3,3,0],
 [0,0,0,0,0,0]]

则往左靠以后的数组就成为

[[0,0,0,0,0,0],
 [0,1,1,0,0,0],
 [0,2,2,0,0,0],
 [0,2,2,3,3,0],
 [0,0,0,0,0,0]]

往右靠的是

[[0,0,0,0,0,0],
 [0,0,0,1,1,0],
 [0,0,0,2,2,0],
 [0,2,2,3,3,0],
 [0,0,0,0,0,0]]

可以看到,其实就是对二维数组的一些巧妙的操作而已.例如排序移位等,

在本DEMO代码中,我写了八种基本类型的数组变换,以下是代码,思路都在注释当中

        //整个地图的方块都往左靠
        //原理,从数组的最后一个元素开始往前判断,只要发现是0,就将0取出将放到最后,然后继续往前判断
        public function change_AllLeft():void{
            for(var i:uint=0;i<Map.ROWS;i++){               
                for(var j:int=Map.COLS;j>=0;j--){                   
                    if(MapArray[i][j]==0){
                        MapArray[i].push(MapArray[i].splice(j,1));
                    }
                }
                //恢复最左边的一个0
                MapArray[i].unshift(MapArray[i].pop());
            }
        }
       
        //整个地图的方块都往右靠
        //原理,从数组的第一个元素开始往后判断,只要发现是0,就将0取出并放到最前面,然后继续往后判断
        public function change_AllRight():void{
            for(var i:uint=0;i<Map.ROWS;i++){
                for(var j:uint=0;j<Map.COLS;j++){
                    if(MapArray[i][j]==0){
                        MapArray[i].unshift(MapArray[i].splice(j,1));
                    }
                }
                //恢复最右边的一个0
                MapArray[i].push(MapArray[i].shift());
            }           
        }
       
        //整个地图的方块都往上升
        //原理,将每一列的非零数据都存于一个临时的数组,再从第1列开始(第0列始终为0),将临时的数组独个代入,往后的就都为0
        public function change_AllUp():void{
            for(var i:uint=1;i<Map.COLS-1;i++){               
                var unZeroArray:Array = new Array();//记录非零的数据
                for(var j:uint=1;j<Map.ROWS-1;j++){
                    if(MapArray[j][i]>0){                       
                        unZeroArray.push(MapArray[j][i]);
                    }
                }
                //如果该列仍有方块
                if(unZeroArray.length>0){
                    var t:uint=0;
                    for(j=1;j<Map.ROWS-1;j++){
                        if(j<=unZeroArray.length){
                            MapArray[j][i] = unZeroArray[t++];
                           
                        }
                        else
                        {
                            MapArray[j][i] = 0;
                        }
                    }
                   
                }
            }
        }
       
        //整个地图的方块都往下沉
        //原理,将每一列的非零数据存于一个临时数组,再计算第一个非零数据的列数,则该列之前的数据都为0,之后则独个代入
        public function change_AllDown():void{
            for(var i:uint=1;i<Map.COLS-1;i++){
                var unZeroArray:Array = new Array();//记录非零的数据
                for(var j:uint=1;j<Map.ROWS-1;j++){
                    if(MapArray[j][i]>0)
                    {
                        unZeroArray.push(MapArray[j][i]);
                    }
                }
                //如果该列仍有方块
                if(unZeroArray.length>0){
                    var t:uint=0;
                    for(j=1;j<Map.ROWS-1;j++){
                        if(j<Map.ROWS-1-unZeroArray.length)
                        {
                            MapArray[j][i]=0;
                        }
                        else{
                            MapArray[j][i] = unZeroArray[t++];
                           
                        }
                    }
                }
            }
        }
       
        //整个地图的方块都往左右两边靠
        //原理,统计每一列的非零数据并存于临时数组同时记录应往左靠的方块个数.
        public function change_CenterToLeftRight():void{
            for(var i:uint=1;i<Map.ROWS-1;i++){
                var unZeroArray:Array = new Array();//记录非零的数据
                var LeftCount:uint = 0;//应靠往左边的方块数
                for(var j:uint=1;j<Map.COLS-1;j++){
                    if(MapArray[i][j]>0){
                        unZeroArray.push(MapArray[i][j]);
                        if(j<Map.COLS/2)LeftCount++;
                    }
                }
                //如果该行仍有方块
                if(unZeroArray.length>0){
                    var t:uint=0;
                    for(j=1;j<Map.COLS-1;j++){
                        if(j<=LeftCount){
                            MapArray[i][j] = unZeroArray[t++];
                        }
                        else if(j>=Map.COLS-1-(unZeroArray.length-LeftCount)){
                            MapArray[i][j] = unZeroArray[t++];
                        }
                        else
                        {
                            MapArray[i][j]=0;
                        }
                    }
                }
            }
        }
       
        //地图上的所有方块从左右往中间靠
        public function change_LeftRightToCenter():void{
            for(var i:uint=1;i<Map.ROWS-1;i++){
                var unZeroArray:Array = new Array();// 保存非0数据
                var LeftCount:uint=0;//左边往中靠的方块数
                for(var j:uint=1;j<Map.COLS-1;j++){
                    if(MapArray[i][j]>0){
                        unZeroArray.push(MapArray[i][j]);
                        if(j<Map.COLS/2)LeftCount++;
                    }
                }
                //如果该行仍有方块
                if(unZeroArray.length>0){
                    var t:uint=0;
                    for(j=1;j<Map.COLS-1;j++){
                        if(j>=(Map.COLS/2-LeftCount) && j<Map.COLS/2+unZeroArray.length-LeftCount){
                            MapArray[i][j] = unZeroArray[t++];
                        }
                        else{
                            MapArray[i][j] = 0;
                        }
                    }
                }
            }
        }
       
        //方块从中间往上下分开
        public function change_MiddleToTopBottom():void{
            for(var i:uint=1;i<Map.COLS-1;i++){
                var unZeroArray:Array = new Array();//保存非0数据
                var TopCount:uint = 0;//应该往上升的方块数量
                for(var j:uint=1;j<Map.ROWS-1;j++){
                    if(MapArray[j][i]>0){
                        unZeroArray.push(MapArray[j][i]);
                        if(j<Map.ROWS/2)TopCount++;
                    }
                }
                //如果该列仍有方块
                if(unZeroArray.length>0){
                    var t:uint=0;
                    for(j=1;j<Map.ROWS-1;j++){
                        if(j<=TopCount || j>= Map.ROWS - 1 - (unZeroArray.length-TopCount)){
                            MapArray[j][i] = unZeroArray[t++];
                        }
                        else
                        {
                            MapArray[j][i] = 0;
                        }
                    }
                }
            }
        }
       
        public function change_TopBottomToMiddle():void{
            for(var i:uint=1;i<Map.COLS-1;i++){
                var unZeroArray:Array = new Array();//保存非0数据
                var TopCount:uint = 0;//应该往上升的方块数量
                for(var j:uint=1;j<Map.ROWS-1;j++){
                    if(MapArray[j][i]>0){
                        unZeroArray.push(MapArray[j][i]);
                        if(j<Map.ROWS/2)TopCount++;
                    }
                }
                //如果该列仍有方块
                if(unZeroArray.length>0){
                    var t:uint=0;
                    for(j=1;j<Map.ROWS-1;j++){
                        //if(j>=(Map.COLS/2-LeftCount) && j
                        if(j>=(Map.ROWS/2-TopCount) && j < Map.ROWS/2 + unZeroArray.length - TopCount){
                            MapArray[j][i] = unZeroArray[t++];
                        }
                        else
                        {
                            MapArray[j][i] = 0;
                        }
                    }
                }
            }
        }

 

你可能感兴趣的:(连连看设计思路与源码[一]-地图类)