配对序列生成算法实现与分析

本文介绍了一种用于游戏的配对算法实现,通过数组填充、计数及去单操作完成元素配对,确保每种元素均有偶数个实例,适用于如连连看等游戏场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

配对算法实现与分析

这个也是做连连看时所写的算法,为了保持通用原则,这里一律采用数组实现

基本思路:

1.       先将所有元素填充到数组里,并把出现次数放到eCount[]里、最后出现的地址放到

lastAddr[]中。

2.       查看eCount[]此时数组里的各种元素出现的次数有双有单。

3.       找出两个eCount[x1],eCount[x2]为单的元素的lastAddr[x1]lastAddr[x2],并设置 data[lastAddr[x1]]=data[lastAddr[x2]]

4.       这就完成了双去单。

/**

     * 产生范围在[start,end]区间的配对的序列, 填充到int[arrayRows>0][arrayCloums>0]的数组中,

     * 最后返回这个数组

     * 完美版,适用于任何情况

     *

     * @param start

     *            起始整数

     * @param end

     *            终点整数

     * @param arrayRows

     *            数组行数

     * @param arrayColums

     *            数组列数

     * @return 如果参数中数组行列值小于等于零或者数组大小为奇数,则返回null,否则

     *         返回已经填充了配对数的数组int[arrayRows][arrayCloums]

     */

    public static int[][] partnerUP(int start, int end, int arrayRows,

           int arrayColums) {

 

       if (arrayColums <= 0 || arrayRows <= 0

              || (arrayColums * arrayRows) % 2 != 0) {

           return null;

       }

       int[] eCount;// 元素计数器

       int[] lastAddr;// 元素最后出现的地址

       int[][] data = new int[arrayRows][arrayColums];// 保存配对序列数组

       int arraySize = arrayRows * arrayColums;// 数组大小

       int maxPartners = arraySize / 2;// 数组中可能出现的最大对数

      

       // start恒置为小的数,end为大的数

       if (end - start < 0) {

           int tmp = end;

           end = start;

           start = tmp;

       }

       // 填充范围,大于0

       int fillArea = Math.abs(end - start) + 1;

       // 填充范围是否大于最大配对数,如果是的,则只需maxPartens个填充因子就可以了

       boolean isOverPartner=(fillArea - maxPartners)>0? true:false;

       int[]fillElemts=new int[0];

       if (isOverPartner) {

           //定义maxPartners个格子用来装随机从fillArea中取出的填充因子

           fillElemts=new int[maxPartners];

           for(int i=0;i<fillElemts.length;i++){

              fillElemts[i]=start+(int)(Math.random()*fillArea);

           }

           //数组地址范围,计数器、最后地址数组地址范围

           fillArea=maxPartners;

           eCount = new int[fillArea];

           lastAddr = new int[fillArea];

       }else{

           eCount = new int[fillArea];

           lastAddr = new int[fillArea];

       }

       // 填充data[][]

       for (int i = 0; i < arraySize; i++) {

           // 随机产生一张图片索引

           int index = start + (int) (Math.random() * fillArea);

           // 对应索引计数+1

           eCount[index - start] += 1;

           if(isOverPartner){

              //选取抽取出来的元素

              data[i / arrayColums][i % arrayColums]=fillElemts[index-start];

           }else{

              // 将图片名称放入Data

               data[i / arrayColums][i % arrayColums] = index;

           }

           // 将最后出现的地址赋给addrCount[index]保存

           lastAddr[index - start] = i;

 

       }

       // 图素配对开始(去单操作)

       // 从计数数组的最有一个元素开始

       int i = eCount.length - 1;

       // 出现的元素中数量为奇数的元素个数

       int pCount = 0;

       while (i > -1) {

           if (eCount[i--] % 2 == 1) {

              pCount += 1;

           }

       }

       // 如果确实存在奇数个元素

       while (pCount > 0) {

           for (int j = 0; j < eCount.length - 1; j++) {

              for (int k = 1; k < eCount.length; k++) {

                  if (eCount[j] % 2 == 1) {

                     if (eCount[k] % 2 == 1) {

                         // 计数器为奇数的图素地址交换(根据最后图素保存的地址进行交换操作)

                         data[lastAddr[j] / arrayColums][lastAddr[j]

                                % arrayColums] = data[lastAddr[k]

                                / arrayColums][lastAddr[k] % arrayColums];

                         eCount[j] -= 1;

                         eCount[k] += 1;

                         pCount -= 2;//去掉两个奇数素

 

                     }

                  }

              }

           }

       }// 图素配对结束

       return data;

    }

测试结果:

Xx代表方括号里的的数字

LLKTookit.partnerUP(x,x,4,4)

===========[1,15]

8,14,15,14,

10,8,2,1,

15,2,1,10,

14,8,14,8,

==============[-115]

-1,12,6,12,

3,6,6,6,

13,-1,6,15,

15,13,6,3,

==============[-1,-15]

-6,-5,-6,-6,

-9,-6,-6,-1,

-7,-9,-5,-7,

-15,-1,-6,-15,

=============[0,0]

0,0,0,0,

0,0,0,0,

0,0,0,0,

0,0,0,0,

=============[1,1]

1,1,1,1,

1,1,1,1,

1,1,1,1,

1,1,1,1,

==============[-1,-1]

-1,-1,-1,-1,

-1,-1,-1,-1,

-1,-1,-1,-1,

-1,-1,-1,-1,

分析:从代码上看,写得比较繁杂,从运行结果来看,该函数实现的还不错。

总结:这个方法的实现经历最初的内嵌版本,再是分离出来后的不完美版(有兴趣的可以看看,在下面),知道今天改的自认为完美版,一路走来都意味着一次次的进步,和对完美的追求,今天写的这个配对算法和之前写的连线算法一起,作为我暑假连连看游戏制作的最终收获,我觉得,虽然不丰厚,但至少很值得。

 

不完美版代码,在注释中有 “为什么不完美的解释”

以下是word文档

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值