关于java石头迷阵不可还原的另一种解决方案及其导致的怪异现象

OK,在之前我发布过一篇文章提供了我个人解决石头迷阵中不可还原问题的解决方案,而在今天,我受到一位师兄的灵感启发,编写了另一种解决方案,下面请看我的分析.

首先要知道为什么会产生不可还原的情况,举个简单的例子,将拧好的魔方一个角转动一下就会导致魔方再也无法还原,跟这是同样的道理,偶然之间把对角上的方块交换了或者其它会导致同样结果的情况发生,而这是我们的随机打乱代码:

    public void initData() {//此方法用于初始化数据,即打乱二维数组
        Random r = new Random();//创建对象,准备随机数
        for (int i = 0; i < data.length; i++) {//遍历二维数组中的一维数组
            for (int j = 0; j < data[i].length; j++) {//遍历一维数组中的元素
                int x = r.nextInt(4);//创建两个随机索引
                int y = r.nextInt(4);
                int temp = data[i][j];//接下来三步用于交换原数据与随机数据
                data[i][j] = data[x][y];
                data[x][y] = temp;
                if (data[i][j] == 0) {//在此判断元素是否为零号元素
                    row = i;//不在此定义这两个变量是为了使移动业务能使用这两个变量
                    column = j;// 因此在成员变量位置定义出来
                }
            }
        }
    }

可以看到,利用随机索引以及第三方变量完成交换,这极有可能导致无法还原的情况产生,而如果我们用一下这个方法进行打乱呢?

    public void initData() {//此方法用于初始化数据,即打乱二维数组
        Random random = new Random();//创建对象,准备随机数
        for (int rank = 0; rank <= 100; rank++) {//这是第二种打乱方式
            int r = random.nextInt(4);//创造一个随机数决定空白块的移动方式
            if (r == 0 && column != 0) {//如果r为0且空白块不在最左边则让空白块向左交换
                int temp = data[row][column];
                data[row][column] = data[row][column - 1];
                data[row][column - 1] = temp;
            } else if (r == 1 && row != 0) {//如果r为1且空白块不在最上边则让空白块向上交换
                int temp = data[row][column];
                data[row][column] = data[row - 1][column];
                data[row - 1][column] = temp;
            } else if (r == 2 && column != 3) {//如果r为2且空白块不在最右边则让空白块向右交换
                int temp = data[row][column];
                data[row][column] = data[row][column + 1];
                data[row][column + 1] = temp;
            } else if (r == 3 && row != 3) {//如果r为3且空白块不在最下边则让空白块向下交换
                int temp = data[row][column];
                data[row][column] = data[row + 1][column];
                data[row + 1][column] = temp;
            }
            for (int i = 0; i < data.length; i++) {//每次空白块移动都要重新定位
                for (int j = 0; j < data[i].length; j++) {
                    if (data[i][j] == 0) {
                        row = i;
                        column = j;
                    }
                }
            }
        }
    }

试想一下,如果一个被打乱的16宫格能被还原,那么我们可以将还原方式反过来将一个好的16宫格将其打乱,于是在这里引入随机数r,使得它的界限在0~3中的不同情况,分别让空白块向四个方向进行交换,同时要考虑索引越界问题,因此要追加判断空白块的位置,还要注意每次空白块交换完成要重新定位空白块的位置,我让这段逻辑循环100次,那么理想情况下,空白块就跟周围的方块进行了100次交换,当然了,根据我后来的测试,发现循环次数100还是太少,导致游戏难度极低,因此建议将循环次数提升.

然而,在测试过程中我同样发现了一个奇怪的问题,在之前的文章中,我们所运用的解决方法是使用了逆序数这个概念,而当时我运用了冰川大佬的一个结论:不将空白块带入逆序数的计算的话,对于四阶拼图,空白块在4、2行(行索引为3、1)时,逆序数为偶数才能保证拼图可还原,空白块在3、1行(行索引为2、0)时,逆序数为奇数才能保证拼图可还原.然而在实际测试中却出现

了这样的情况:

 可以看到,在这里空白块在第三行,理应来说逆序数应该为奇数才可以被还原,然而我利用昨天计算逆序数的方法却得出逆序数为12,这是一个偶数,应该不可能被还原才对,然而事实上它却可以被还原(我已经手动还原过,且根据打乱逻辑来说肯定可以原路将其还原),而且我自己数出来的逆序数并没有错也是12(有质疑的可以自己数),而且这种情况时有发生,之前我们得出的逆序数的规律完全失去了作用,逆序数的奇偶无法再判断迷宫是否能够还原.

当然了,我本人对于这种现象也是一头雾水(大一新生),因此也是在此分享出自己的疑惑.

如果这篇文章能为您带来一丝启发那么我会非常荣幸,感谢您看到这里!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值