图案解锁---优化版

源代码:

链接:
https://pan.baidu.com/s/1RbBCULYZX3IcueN9dGBClQ 密码:gkhs

主要代码:

//
//  ViewController.m
//  密码解锁---优化
//
//  Created by 许磊 on 2019/2/23.
//  Copyright © 2019年 xulei. All rights reserved.
//

#import "ViewController.h"
#import "ChangablemageView.h"


@interface ViewController ()

//不想被外部访问的信息

/**定义一个保存九个点的可变数组*/
@property (nonatomic,strong) NSMutableArray *dotViewArray;

/**定义一个保存所有线的Tag值得可变数组*/
@property (nonatomic,strong) NSMutableArray *lineTagsArray;

/**定义一个保存所有被选中的点或线的可变数组*/
@property (nonatomic,strong) NSMutableArray *selectedViewsArray;

/**保存上一个被点亮的点的Tag值*/
@property (nonatomic,assign) NSInteger lastSelectedDotTag;

/**定义一个提示接下来的操作的文本框*/
@property (nonatomic,strong) UILabel *hintLabel;

/**记录密码*/
@property (nonatomic,strong) NSMutableString *pwdString;

/**定义一个变量存储密码*/
@property (nonatomic,strong) NSString *password;

/**定义一个变量存储第一次设置的密码*/
@property (nonatomic,strong) NSString *firstPassword;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //初始化
    [self arrayAndStringInit];
    
    //界面布局
    [self UIInit];
    
}

#pragma mark -------creatImageViewWithFrame ---------
//创建UIImageView呈现图片
- (UIImageView *)creatImageViewWithFrame:(CGRect) frame name:(NSString *)imageName{
    
    //创建
    UIImageView *imageView = [[ UIImageView alloc] initWithFrame:frame];
    //添加图片
    imageView.image = [UIImage imageNamed:imageName];
    //不显示
    imageView.hidden = YES;
    //添加
    [self.view addSubview:imageView];
    
    return imageView;
}

#pragma mark -------arrayAndStringInit ---------
//数组初始化
- (void)arrayAndStringInit{
    
    //初始化存放点的数组
    self.dotViewArray = [NSMutableArray arrayWithCapacity:9];
    
    //初始化存放Tag值得数组
    self.lineTagsArray = [NSMutableArray array];
    
    //初始化存放被选中的点或者线
    self.selectedViewsArray = [NSMutableArray array];
    
    //初始化字符串
    self.pwdString = [NSMutableString string];
    
}

#pragma mark -------UIInit ---------
//界面布局
- (void)UIInit{
    
    //创建背景图片
    {
        UIImageView *bgView = [self creatImageViewWithFrame:self.view.bounds name:@"DotLock_Normal"];
        bgView.contentMode = UIViewContentModeScaleAspectFit;
        //不隐藏
        bgView.hidden = NO;
    }
    
    //添加操作图片
    {
        //添加九个点
        [self addDot];
        
        //添加六条横线
        [self addTransverseLine];
        
        //添加六条竖线
        [self addVerticalLine];
        
        //添加八条斜线
        [self addSlantLine];
    }
    
    //提示框布局
    {
        //创建
        self.hintLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 124, self.view.frame.size.width, 50)];
        
        //文本
        // _hintLabel.text = @"请绘制密码";
        
        //字体颜色
        _hintLabel.textColor = [UIColor blackColor];
        
        //对齐方式
        _hintLabel.textAlignment = NSTextAlignmentCenter;
        
        //添加
        [self.view addSubview:_hintLabel];
        
    }
    
    //密码操作
    {
        //获取密码
        //[[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"password"];
        self.password = [[NSUserDefaults standardUserDefaults] objectForKey:@"password"];
        
        if (_password.length == 0) {
            //设置密码
            _hintLabel.text = @"请设置解锁图案";
        } else {
            //输入密码
            _hintLabel.text = @"请绘制解锁图案";
        }
        
    }
    
}

#pragma mark -------addDot ---------
//添加九个点
- (void)addDot{
    
    int index = 1;
    
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            
            //循环创建九个点
            ChangablemageView *dotImageView =  [ChangablemageView imageViewwithNormalImageName:@"DotLock_Selected" andWrongImageName:@"DotLock_Wrong" frame:CGRectMake(31+j*98, 214+i*97, 62, 62) father:self.view];
            //dotImageView.hidden = NO;
            
            //设置Tag值
            dotImageView.tag = index;
            index++;
            
            //放到存放点的数组中
            [self.dotViewArray addObject:dotImageView];
        }
    }
    
}


#pragma mark -------addTransverseLine ---------
//添加横线
//12 23 45 56 78 89
-(void)addTransverseLine{
    
    int index = 12;
    
    for (int i = 0; i < 6; i++) {
        
        //循环创建六条横线
        ChangablemageView *transverseImageView =  [ChangablemageView imageViewwithNormalImageName:@"DotLock_Normal_Highlight1" andWrongImageName:@"DotLock_Wrong_Highlight1" frame:CGRectMake(90+i%2*97, 233+i/2*99, 38, 22) father:self.view];
        //transverseImageView.hidden = NO;
        
        //赋予Tag值
        transverseImageView.tag = index;
        
        //将Tag值添加到数组中
        [self.lineTagsArray addObject:@(index)];
        
        if ((i+1)%2 == 0 && i != 0) {
            
            index = index + 11;
            
        }
        
        index = index + 11;
        
    }
    
}

#pragma mark -------addVerticalLine ---------
//添加竖线
//14 25 36 47 58 69
-(void)addVerticalLine{
    
    int index = 14;
    
    for (int i = 0; i < 6; i++) {
        
        //循环创建六条竖线
        ChangablemageView *verticalImageView =  [ChangablemageView imageViewwithNormalImageName:@"DotLock_Normal_Highlight2" andWrongImageName:@"DotLock_Wrong_Highlight2" frame:CGRectMake(51+i%3*99, 273+i/3*98, 20, 38) father:self.view];
        //verticalImageView.hidden = NO;
        
        //赋予Tag值
        verticalImageView.tag = index;
        
        //将Tag值添加到数组中
        [self.lineTagsArray addObject:@(index)];
        
        index = index + 11;
        
    }
}

#pragma mark -------addSlantLine ---------
//添加斜线
//右斜 24 35 57 68
//左斜 15 26 48 59
-(void)addSlantLine{
    
    int indexR = 15;
    
    int indexL = 24;
    
    for (int i = 0; i < 4; i++) {
        
        //循环创建四条右斜线
        ChangablemageView *rSlantLine =  [ChangablemageView imageViewwithNormalImageName:@"DotLock_Normal_Highlight3" andWrongImageName:@"DotLock_Wrong_Highlight3" frame:CGRectMake(73+i%2*99, 255+i/2*99, 64, 64) father:self.view];
        //rSlantLine.hidden = NO;
        
        //赋予Tag值
        rSlantLine.tag = indexR;
        
        //将Tag值添加到数组中
        [self.lineTagsArray addObject:@(indexR)];
        
        indexR = indexR +11;
        
        //循环创建四条左斜线
        ChangablemageView *lSlantLine =  [ChangablemageView imageViewwithNormalImageName:@"DotLock_Normal_Highlight4" andWrongImageName:@"DotLock_Wrong_Highlight4" frame:CGRectMake(82+i%2*99, 255+i/2*99, 64, 64) father:self.view];
        //lSlantLine.hidden = NO;
        
        //赋予Tag值
        lSlantLine.tag = indexL;
        
        //将Tag值添加到数组中
        [self.lineTagsArray addObject:@(indexL)];
        
        indexL = indexL +11;
        
        if (i + 1 == 2) {
            indexL = indexL + 11;
            indexR = indexR + 11;
        }
        
    }
}

#pragma mark -------touchesBegan ---------
//开始触摸
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    //获取触摸点的坐标
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self.view];
    
    //判断触摸点有没有在摸一个圆点上
    for (UIImageView *dotView in _dotViewArray) {
        
        //判断
        if (CGRectContainsPoint(dotView.frame, location)) {
            
            //点亮
            dotView.hidden = NO;
            
            //记录这个点的Tag
            _lastSelectedDotTag = dotView.tag;
            
            //保存点亮的点
            [_selectedViewsArray addObject:dotView];
            
            //保存密码 拼接字符串
            [self.pwdString appendFormat:@"%ld", (long)dotView.tag];
            
        }
    }
}

#pragma mark -------touchesMoved ---------
//滑动时
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    //获取触摸点的坐标
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self.view];
    
    //判断触摸点有没有在摸一个圆点上
    for (UIImageView *dotView in _dotViewArray) {
        
        //判断
        if (CGRectContainsPoint(dotView.frame, location)) {
            
            //如果这个点没有被点亮
            if (dotView.hidden == YES) {
                
                //是第一个点
                if (_lastSelectedDotTag == 0) {
                    
                    //直接点亮
                    dotView.hidden = NO;
                    
                    //记录这个点的Tag
                    _lastSelectedDotTag = dotView.tag;
                    
                    //保存点亮的点
                    [_selectedViewsArray addObject:dotView];
                    
                    //保存密码 拼接字符串
                    [self.pwdString appendFormat:@"%ld", (long)dotView.tag];
                    
                } else {//不是第一个点
                    
                    //判断上一个点和当前这个点之间有没有直接的线路
                    //获取上一个点和当前这个点的Tag组成的最小两位数
                    NSInteger lineTag = _lastSelectedDotTag > dotView.tag?dotView.tag*10+_lastSelectedDotTag:_lastSelectedDotTag*10+dotView.tag;
                    NSLog(@"%ld",(long)lineTag);
                    
                    //数组里面有这条线
                    if ([_lineTagsArray containsObject:@(lineTag)]) {
                        
                        //点亮
                        dotView.hidden = NO;
                        
                        //点亮线
                        UIImageView *lineImageView = [self.view viewWithTag:lineTag];
                        lineImageView.hidden = NO;
                        
                        //记录这个点的Tag
                        _lastSelectedDotTag = dotView.tag;
                        
                        //保存点亮的点
                        [_selectedViewsArray addObject:dotView];
                        
                        //保存密码 拼接字符串
                        [self.pwdString appendFormat:@"%ld", (long)dotView.tag];
                        
                        //保存点亮的线
                        [_selectedViewsArray addObject:lineImageView];
                        
                    }
                    
                }
                
            }
            
        }
    }
}

#pragma mark -------touchesEnded ---------
//结束触摸
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    //设置密码
    if (_password.length == 0) {
        
        //第一次
        if (_firstPassword.length == 0) {
            
            //保存刚才输入的密码
            self.firstPassword = [NSString stringWithString:_pwdString];
            [self hideAllViews];
            
            _hintLabel.text = @"请确认密码图案";
            
        } else {//第二次
            
            //设置成功
            if ([_firstPassword isEqualToString:_pwdString]) {
                
                self.hintLabel.text = @"设置成功";
                
                //保存密码
                [[NSUserDefaults standardUserDefaults] setObject:_pwdString forKey:@"password"];
                
            } else {
                
                //不一致 重新设置
                self.hintLabel.text = @"两次图案不一致 请重新绘制";
                //换色
                [self showWrong];
                //self.firstPassword = @"";
                
            }
            
        }
        
    } else {//解锁
        
        //密码正确
        if ([self.pwdString isEqualToString:_password]) {
            
            self.hintLabel.text = @"解锁成功";
            
        } else {//密码错误
            
            
            self.hintLabel.text = @"密码错误";
            
            //换色
            [self showWrong];
            
        }
        
        
    }
    
 
    
}

-(void)showWrong{
    
    for (ChangablemageView *imgView in _selectedViewsArray) {
       
        //更换状态
        [imgView changeImageWithStatus:kImageViewStatusWrong];
        
        self.hintLabel.textColor = [UIColor redColor];
        
        //延长一段时间后
        [self performSelector:@selector(hideAllViews) withObject:nil afterDelay:1];
        
    }
    
    
}

#pragma mark -------hideAllViews ---------
//隐藏所有的视图
-(void)hideAllViews{
    
    for (ChangablemageView *imgView in _selectedViewsArray) {
        //隐藏
        imgView.hidden = YES;
        //图片换回去
        [imgView changeImageWithStatus:kImageViewStatusNormal];
    }
    
    self.hintLabel.textColor = [UIColor blackColor];
    
    if ([_hintLabel.text isEqualToString:@"密码错误"]) {
        _hintLabel.text = @"请重新输入";
    }
    
    if ([_hintLabel.text isEqualToString:@"两次图案不一致 请重新绘制"]) {
        _hintLabel.text = @"请重新绘制确认密码";
    }
    
    //清空
    [_selectedViewsArray removeAllObjects];
    _lastSelectedDotTag = 0;
    [_pwdString setString:@""];
    
    
}

@end

//
//  ChangablemageView.h
//  密码解锁---优化
//
//  Created by 许磊 on 2019/2/23.
//  Copyright © 2019年 xulei. All rights reserved.
//

#import <UIKit/UIKit.h>

//图片的状态
typedef enum {
    kImageViewStatusNormal,
    kImageViewStatusWrong
} kImageViewStatus;

@interface ChangablemageView : UIImageView

/**表示正常图片的名字*/
@property (nonatomic,strong) NSString *normalImageName;

/**表示错误图片的名字*/
@property (nonatomic,strong) NSString *wrongImageName;

//根据状态改变
- (void)changeImageWithStatus:(kImageViewStatus)status;

//类方法创建图片
+(ChangablemageView *)imageViewwithNormalImageName:(NSString *)normal andWrongImageName:(NSString *)wrong frame:(CGRect)frame father:(UIView *)fatherView;

@end

//
//  ChangablemageView.m
//  密码解锁---优化
//
//  Created by 许磊 on 2019/2/23.
//  Copyright © 2019年 xulei. All rights reserved.
//

#import "ChangablemageView.h"

@implementation ChangablemageView

-(void)changeImageWithStatus:(kImageViewStatus)status {
    
    //正确图片
    if (status == kImageViewStatusNormal) {
        self.image = [UIImage imageNamed:_normalImageName];
    } else{//错误图片
        self.image = [UIImage imageNamed:_wrongImageName];
    }
    
}

+(ChangablemageView *)imageViewwithNormalImageName:(NSString *)normal andWrongImageName:(NSString *)wrong frame:(CGRect)frame father:(UIView *)fatherView{
    
    //创建
    ChangablemageView *imgView = [[ChangablemageView alloc] initWithFrame:frame];
    
    //图片名称
    imgView.normalImageName = normal;
    imgView.wrongImageName = wrong;
    
    //图片
    imgView.image = [UIImage imageNamed:normal];
    
    //状态
    imgView.hidden = YES;
    
    //添加
    [fatherView addSubview:imgView];
    
    return imgView;
}

@end

运行结果:

运行结果

附一:界面布局

1.背景图片
2.操作图片
3.加点
4.加线

附二:逻辑

  • 1.如何记录密码
    图案->密码

  • 2.如何点量点
    用一个数组保存九个点的对象 滑动过程中 实时判断触摸点有没有在九个对象中的某一个上

  • 3.点亮线
    a.触摸点必须在一个圆点上
    b.上一个点和当前这个点得有线路
    c.当前这个点没有被点亮过
    (给每一条线添加一个Tag值,两个点的Tag值组成的最小两位数)
    (用一个数组保存所有线条的Tag值)

  • 4.路径是否可到达
    只需要判断连个点组成的两位数有没有在数组里面
    如果在数组里面 说明有这条路径
    如果不在说明没有线路 记录上一个被点亮的点

附三:步骤

1.添加线条的Tag值
2.将Tag值添加到数组里面NSNumber(或转化)
3.定义一个变量 记录 上一个被点亮的点的Tag值
4.定义一个数组用于保存所有点亮的点和线
5.记录密码---每一个圆点的Tag值拼接的字符串
6.设置密码过程
7.密码错误 显示红色 切换图片视图显示的图片,自定义一个继承于UIImageView的类

附四:个人改进点

可以重写initWithFrame,自定义图案解锁

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,259评论 4 61
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,148评论 1 32
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 11,186评论 6 13
  • 听同事说工资太低了,果断辞职另觅出路。又面试了一家,希望有好消息。
    镇魂女孩阅读 106评论 0 0
  • 南怀瑾说:“佛教道教我还是相信睡觉,中药西药也不如九点睡觉。” 随着年龄的增大,睡眠的重要性越来越凸显出来。这不,...
    嫣然逢春阅读 789评论 0 3