Java实现破解老王手机密码:商品秒杀服务倒计时的实现

写在前面

说起破解手机密码,大家可能第一印象想到的方法是暴力穷举,就是列举出所有的可能性,然后一个一个的试,直到正确为止。但是现在的手机都有保护机制,就像《爱情公寓5》里面第七集一样,猜错几次之后,可能要等几个小时后你才能猜下一次了。
在这里插入图片描述
当然,像破解手机密码这种涉嫌违法的事,其实我也不会 咱当然不能干
纳尼?博主那你博客标题是怎么肥事咧?
好吧,我承认我有些标题党了 不要急,请听我娓娓道来!

事出有因

原来,疫情在家期间,我突然发现我表妹和我叔叔,正在桌子上写着什么。
同时,桌子上还摆着一张报纸。我一问才知道他们在做报纸上的一道题目,但是做了很久都没有结果!题目如下:

小王的手机又换了新密码。他发现,有三个特点使新密码很好记:首先,原来的密码和新换的密码都是四个数字;其次,新密码正好是原来密码的四倍;再次,原来的密码从后面倒着写正好是新的密码。
所以,他不费劲就会记住新密码,那么,小王的新手机密码究竟是多少?

等等,博主你不说是老王吗?怎么变成小王了?

有道是,十年生死两茫茫,转眼小王变老王。

本博主本着"快乐编程,用编程改变世界"的理念。当然要用编程解决实际问题,解救人民于水火之中了。然后火速编程,很快就得出了结果,这速度简直让一旁苦算的表妹叹为观止。

方法一

噔噔蹬蹬,代码如下:

/**
 * @author guqueyue
 * @Date 2020/1/28
 * 方法一
 **/
public class Test99 {
    public static void main(String[] args) {

        // 原来的密码和新换的密码都是四个数字, 所以范围在[0000, 9999]
        for (int i = 0000; i <= 9999; i++) {

            /**
             * 分别求出四位密码的千、百、十、个位的数字
             */
            int q = i % 10000 / 1000; // int q = i / 1000;
            int b = i % 1000 / 100;
            int s = i % 100 / 10;
            int g = i % 10 / 1;  // int g = i % 10;

            // 原来的密码从后面倒着写正好是新的密码
            int newPwd = g * 1000 + s * 100 + b * 10 + q;

            // 新密码正好是原来密码的四倍
            if (4 * i == newPwd && i != newPwd){
                System.out.println("原密码为:" + i);
                System.out.println("新密码为:" + newPwd);
            }
        }
    }
}

Output:
在这里插入图片描述

方法二

其实方法一和方法二的唯一差别,就在于求出四位密码的千、百、十、个位的数字部分

	/**
	* 分别求出四位密码的千、百、十、个位的数字
	*/
	int q = i / 1000;
	int b = i / 100 % 10;
	int s = i / 10 % 10;
	int g = i / 1  % 10; // int g = i % 10

觉得不信的,可以自行实验一番,效果是一样的。

除法和取余的特性

到这里,大家可能会有些许疑惑,到底是啥原理呢?
其实聪明的朋友可能已经发现了:
方法一和方法二的差别无非就是先除还是先取余的差别,就这么简单!

首先,我们来了解一下Java中除法与日常生活中存在的不同特性:
若是 整型 / 整型 == 整型直接取整,舍弃掉后面的小数 ,如在Java中: 5 / 3 =1;
若是 整型 / 浮点型 == 浮点型,如在Java中:5 / 3.0 = 1.6666666666666667。
也就是说,当参与/运算的两个操作数都是整数时,表示整数除法;否则,表示浮点除法

代码示例如下:

/**
 * @author guqueyue
 * @Date 2020/3/16
 * 除法
 **/
public class Test101 {
    public static void main(String[] args) {
        System.out.println("5 / 3 = " + (5 / 3));
        System.out.println("5 / 3.0 = " + (5 / 3.0));
    }
}

Output:
在这里插入图片描述
我们再来看两行代码以及它们的输出结果:

System.out.print(1314/10);
System.out.print(1314%10);

Output:
在这里插入图片描述
What? 1314先除10,再余10,然后拼接出来还是1314?
难道是1314这个数字有魔法,会一生一世永恒不变的吗?当然不是
不要急,我们再来看一组代码:

/**
 * @author guqueyue
 * @Date 2020/3/21
 * 除法和取余
 **/
public class Test102 {
    public static void main(String[] args) {
        System.out.println("=====除法和取余的数字为10=====");
        System.out.print(1314/10 + " ");
        System.out.println(1314%10);

        System.out.println("=====除法和取余的数字为100=====");
        System.out.print(1314/100 + " ");
        System.out.println(1314%100);

        System.out.println("=====除法和取余的数字为1000=====");
        System.out.print(1314/1000 + " ");
        System.out.println(1314%1000);
    }
}

Output:
在这里插入图片描述
所以,大家发现了吗?

当我们对于十进制的数,进行进制n倍数的整除或者取余的时候,只需从右往左数n位。此时,若是整除,则舍弃右边;若是取余,则舍弃左边。其他解码规则为乘法的数字同样适用,如计时所用的60进制。

所以当我们需要获取一个数字不同单位上的具体数字时,其实只需要把左右两边的数字舍弃即可,要么先舍弃右边,要么先舍弃左边,其实就是先除还是先取余的区别!
如当我们需要获取520的百位数字:

System.out.println(520 / 10 % 10); // 先舍弃右边(0),再舍弃左边(5)
System.out.println(520 % 100 / 10); // 先舍弃左边(5),再舍弃右边(0)

秒杀倒计时

嗯~~~,这下我明白了,可是这跟秒杀倒计时有什么关系呢?
不急,我们先打开京东的首页,找到京东"秒杀",点击右键选择"检查",看一下来自京东程序员小哥的秒杀倒计时是怎么写的。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
简直是毫不费劲的就根据命名规则就找到了京东小哥.js文件的src:
http://misc.360buyimg.com/mtd/pc/index_2019/1.0.0/static/js/seckill.chunk.js

复制粘贴,然后打开浏览器输入查看:
在这里插入图片描述
结果,一看傻眼了,被加密了,什么东西都看不出来(•́へ•́╬)
但是别慌,我把自己以前练手写的倒计时的代码供大家参考:

       /**
         * 倒计时方法
         */
        function djs() {
            /**
             * 分别获取当前时间以及商品秒杀开始时间相差的毫秒数,便于计算倒计时
             */
            var times = startTime.getTime() - now.getTime();

            if (times <= 0){
                // 秒杀已经开始,商品可以秒杀
                goBtn();
                return;
            }

            // 秒杀还未开始,计算倒计时,还剩多少h/m/s/ms
            var h = parseInt(times/1000/60/60);
            var m = parseInt(times/1000/60%60);
            var s = parseInt(times/1000%60);
            var ms = parseInt(times%1000);

            // 自定义的方法,格式化倒计时时间,若数字小于10补0,如3:23:9, 格式化为03:23:09
            var djsTime = formatTime(h) + ":" + formatTime(m) + ":" + formatTime(s);
            // 渲染页面
            $("#djs").html(djsTime);

            // 通过定时器使得倒计时每秒准确刷新
            mytime = setTimeout(function () {

                if (count >= 60){
                    console.log("主动获取服务器的时间!");
                    // 重新获取服务器的时间
                    getServerNow();
                    count = 0;
                } else {
                    now.setSeconds(now.getSeconds() + 1);
                    now.setMilliseconds(now.getMilliseconds() + ms);
                    count++;
                }

                djs();

            }, 1000 + ms)
        }

其他的代码我们暂时不用管它,我们现在只需要注意这段代码:

 // 秒杀还未开始,计算倒计时,还剩多少h/m/s/ms
 var h = parseInt(times/1000/60/60);
 var m = parseInt(times/1000/60%60);
 var s = parseInt(times/1000%60);
 var ms = parseInt(times%1000);

其中times是用于计算秒杀倒计时商品的剩余时间(毫秒数),
parseInt()函数可解析一个字符串,并返回一个整数,默认采用十进制解析。

那么朋友们,你们看出来这段代码的意思了吗?
为了直观显示,我把这段代码改动一下:

 // 秒杀还未开始,计算倒计时,还剩多少ms,方便调整定时器
var ms = parseInt(times % 1000);
 // 离秒杀开场总计还剩余多少秒
 var ss = parseInt(ss/1000);
 // 计算倒计时,还剩多少h/ms/s
 var h = parseInt(ss/60/60);
 var m = parseInt(ss/60%60); // var m = parseInt(ss%3600/60);
 var s = parseInt(ss%60);

其实原理和之前是一样的,只不过ms到s的进制为1000,h、m、s之间是60进制而已!

发布了20 篇原创文章 · 获赞 166 · 访问量 8910

猜你喜欢

转载自blog.csdn.net/Qizhi_Hu/article/details/104720571
今日推荐