编程探究智能手机的图案解锁

概述

    图案解锁是现今智能手机比较常见的解锁方式,用户通过在3×3的点阵中绘制图案来设置密码,解锁时,也通过实时绘制图案来实现解锁验证。例如,下图就是几个解锁的图案示例:

下文中笔者通过编程对图案解锁的情况进行探究,主要计算一些统计信息。首先给出图案解锁中对于图案绘制的规则,然后说明为实现相关计算而进行编程的思路,最后根据程序输出结果说明一些统计信息。

绘图规则

    对于目前图案解锁的实现,在绘制解锁图案过程中,需要遵循如下的规则:

(1) 绘制的图案是一条经过若干个点的折线轨迹,至少要经过4个点。

(2) 点阵中每个点只能经过1次,轨迹中也一定没有回路。

(3) 点阵中任意两点,均可以通过一条边直连,水平的边、竖直的边,倾斜的边均合法,如下图所示:

(4) 如果两点之间的边经过了第三个点,则只有位于边中部的点已被经过,该边才有效。这里为了便于说明,将点阵中的各个点进行编号,如下:

此时,轨迹:2->1->3->5是正确的,当从点1到达点3时,点2已经被经过,因此可以从点1到达点3,而轨迹1->3->2->5则是错误的,因为从点1到达点3是,点2未被经过,不能从点1到达点3,如下图:


以上为图案的绘制规则。

编程分析

    接下来通过编程来对图案解锁的情况进行分析,这里主要关注一些统计信息,包括:不同密码的种类数、不同图案的种类数以及图案和密码的对应关系。

·边的分类

    为了便于编程实现,首先对边进行分类。根据上文中对于绘图规则的描述,这里将绘图中用到的边划分为如下的4类:
(1)直边:连接相邻两个点的水平边和垂直边称为直边,在解锁图案中,可以使用的直边有12条。
(2)45度斜边:45度倾斜的连接两个相邻点的边称为45度斜边,在图案中,可以使用的45度斜边有8条。
(3)26度斜边:除45度斜边外,图案中还可以使用另一种斜边,该边的倾斜度大约为26度,在图中,可用的26度斜边也有8条。
(4)跳边:连接两个不相邻的点的边称为跳边,通过跳边连接的两个点中间一定会经过第3个点,这个点我们称其为“中介点”,根据上文中的绘图规则,只有中介点已经被经过是,跳边才合法。在图案中,跳边有8条。根据边的倾斜情况,跳边还可以细分为直跳边和斜跳边。

下图描述了4种类型的边的情况:


在Java代码中,我们用整型常量代表每一种边的类型,同时用邻接矩阵的方式表示图中任意两点的边,代码如下:

/**
     * Edge types.
     */
    private static final int NONE = 0,   // 无边 
                         STRAIGHT = 1,   // 直边
                         DECLINE_45 = 2, // 45度斜边
                         DECLINE_26 = 3, // 26度斜边
                         SKIP_STRAIGHT = 4, // 直跳边
                         SKIP_DECLINE = 5; // 斜跳边
    /**
     * The accessible matrix of each vertex. for each element matrix[i][j] is
     * the type of edge <i, j>.
     */
    private static int[][] matrix = new int[][] {
            { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE },
            { NONE, NONE, STRAIGHT, SKIP_STRAIGHT, STRAIGHT, DECLINE_45, DECLINE_26, SKIP_STRAIGHT, DECLINE_26, SKIP_DECLINE },
            { NONE, STRAIGHT, NONE, STRAIGHT, DECLINE_45, STRAIGHT, DECLINE_45, DECLINE_26, SKIP_STRAIGHT, DECLINE_26 },
            { NONE, SKIP_STRAIGHT, STRAIGHT, NONE, DECLINE_26, DECLINE_45, STRAIGHT, SKIP_DECLINE, DECLINE_26, SKIP_STRAIGHT },
            { NONE, STRAIGHT, DECLINE_45, DECLINE_26, NONE, STRAIGHT, SKIP_STRAIGHT, STRAIGHT, DECLINE_45, DECLINE_26 },
            { NONE, DECLINE_45, STRAIGHT, DECLINE_45, STRAIGHT, NONE, STRAIGHT, DECLINE_45, STRAIGHT, DECLINE_45 },
            { NONE, DECLINE_26, DECLINE_45, STRAIGHT, SKIP_STRAIGHT, STRAIGHT, NONE, DECLINE_26, DECLINE_45, STRAIGHT },
            { NONE, SKIP_STRAIGHT, DECLINE_26, SKIP_DECLINE, STRAIGHT, DECLINE_45, DECLINE_26, NONE, STRAIGHT, SKIP_STRAIGHT },
            { NONE, DECLINE_26, SKIP_STRAIGHT, DECLINE_26, DECLINE_45, STRAIGHT, DECLINE_45, STRAIGHT, NONE, STRAIGHT },
            { NONE, SKIP_DECLINE, DECLINE_26, SKIP_STRAIGHT, DECLINE_26, DECLINE_45, STRAIGHT, SKIP_STRAIGHT, STRAIGHT, NONE } 
    };
矩阵中第i行第j列记录了点i到点j之间的边的类型,由于数组下标从0开始,而我们的编号为1-9,因此在邻接矩阵中有冗余的第0行和第0列,编号为0的点不存在,因此和其他点的边也不存在,记为NONE,另外,同一个点之间也没有边,因此第i行第i列的元素总是NONE。

·跳边的规则

    根据前文中对于跳边的描述,只有中介点被经过时,跳边才可用,我们需要在代码中将这些规则记录下来,这里采用Map容器来存储,其中key值为跳边的端点,value值为中介点,为了便于表示,这里将key值转换为字符串,格式为"v1#v2",其中v1和v2是端点的编号,代码实现如下:

/**
     * The condition for the condition accessible.
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值