zoukankan      html  css  js  c++  java
  • iOS:练习题中如何用技术去实现一个连线题

    一、介绍

    本人做的app涉及的是教育行业,所以关于练习题的开发肯定是家常便饭。例如,选择题、填空题、连线题、判断题等,每一种题型都需要技术去实现,没啥多大难度,这里呢,就给出实现连线题的核心代码吧。过了年后,好久没写笔记了,今天就简单开始吧~~~

    二、思想

    采用上下文在画图的方法,首先确定起点和终点的坐标,然后通过两点画一条直线。

    三、代码

    (1)常量定义

    lianXianHeader.h

    //
    //  LianXianHeader.h
    //  LianxianDemo
    //
    //  Created by 夏远全 on 2018/2/9.
    //  Copyright © 2018年 beijing. All rights reserved.
    //
    
    #ifndef LianXianHeader_h
    #define LianXianHeader_h
    
    static CGFloat const BWidth   = 60;  //按钮的宽度
    static CGFloat const BHeight  = 40;  //按钮的高度
    static CGFloat const margin   = 40;  //按钮与屏幕的左边距、右边距
    static CGFloat const Lpadding = 20;  //左边按钮上下间距
    static CGFloat const Rpadding = 40;  //右边按钮上下间距
    
    static NSString* const kBeginPositionNotification = @"kBeginPositionNotification";
    static NSString* const kEndPositionNotification   = @"kEndPositionNotification";
    static NSString* const kClearAllLineNotification  = @"kClearAllLineNotification";
    static NSString* const kFreshDrawLineNotification = @"kFreshDrawLineNotification";
    
    #endif /* LianXianHeader_h */
    View Code

    (2)连线模型

    lianXianModel.h

    //
    //  LianXianModel.h
    //  LianxianDemo
    //
    //  Created by 夏远全 on 2018/2/8.
    //  Copyright © 2018年 beijing. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    @interface LianXianModel : NSObject
    @property (nonatomic, strong) NSArray  *questions;
    @property (nonatomic, strong) NSArray  *options;
    @property (nonatomic, strong) NSArray  *relationships;
    @end
    View Code

    lianXianModel.m

    //
    //  LianXianModel.m
    //  LianxianDemo
    //
    //  Created by 夏远全 on 2018/2/8.
    //  Copyright © 2018年 beijing. All rights reserved.
    //
    
    #import "LianXianModel.h"
    
    @implementation LianXianModel
    
    @end
    View Code

    (3)绘制连线

    lianXianDrawView.h

    //
    //  LianxianDrawView.h
    //  Ubbsz
    //
    //  Created by 夏远全 on 2018/2/9.
    //  Copyright © 2018年 beijing. All rights reserved.
    //
    //
    
    #import <UIKit/UIKit.h>
    
    @interface LianxianDrawView : UIView
    
    @end
    View Code

    lianXianDrawView.m

    //
    //  LianxianDrawView.m
    //  Ubbsz
    //
    //  Created by 夏远全 on 2018/2/9.
    //  Copyright © 2018年 beijing. All rights reserved.
    //
    
    
    #import "LianxianDrawView.h"
    #import "LianXianHeader.h"
    
    
    @interface LianxianDrawView()
    {
        NSMutableArray *pointArray; //存储当前的一对坐标,起始点和终止点
        NSMutableArray *lineArray;  //存储全部的连线,每一条连线就是一对坐标
        NSString       *startPointString; //当前起点
        NSString       *endPointString;   //当前起点
        CGFloat        lineWidth;
    }
    
    @end
    
    @implementation LianxianDrawView
    
    
    //对进行重写,以便在视图初始化的时候创建并设置自定义的Context
    - (id)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame]) {
            
            [self setupDefaultValue];
            [self regesterNotification];
        }
        return self;
    }
    
    //初始值
    - (void)setupDefaultValue{
        
        pointArray=[[NSMutableArray alloc]init];
        lineArray=[[NSMutableArray alloc]init];
        lineWidth = 2.0f;
        self.backgroundColor = [UIColor colorWithRed:238/255.0 green:243/255.0  blue:248/255.0  alpha:1];
    }
    
    //注册通知
    - (void)regesterNotification{
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(toucheBegin:) name:kBeginPositionNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(toucheEnd:) name:kEndPositionNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(clearLine:) name:kClearAllLineNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(freshNeedsDisplay:) name:kFreshDrawLineNotification object:nil];
    }
    
    //对drawRect进行重写
    - (void)drawRect:(CGRect)rect
    {
        
        //获取当前上下文,
        CGContextRef context=UIGraphicsGetCurrentContext();
        CGContextBeginPath(context);
        CGContextSetLineWidth(context, lineWidth);
        //线条拐角样式,设置为平滑
        CGContextSetLineJoin(context,kCGLineJoinRound);
        //线条开始样式,设置为平滑
        CGContextSetLineCap(context, kCGLineCapRound);
        
        //查看lineArray数组里是否有线条,有就将之前画的重绘,没有只画当前线条
        if ([lineArray count] > 0) {
    
            for (int i=0; i < [lineArray count]; i++) {
                NSArray * array=[NSArray arrayWithArray:[lineArray objectAtIndex:i]];
                if ([array count] > 0 && [array count]%2 == 0) {
                    
                    CGContextBeginPath(context);
                    CGPoint myStartPoint = CGPointFromString(array.firstObject);
                    CGContextMoveToPoint(context, myStartPoint.x, myStartPoint.y);
                    
                    CGPoint myEndPoint = CGPointFromString(array.lastObject);
                    CGContextAddLineToPoint(context, myEndPoint.x,myEndPoint.y);
                    
                    CGContextSetStrokeColorWithColor(context,[[UIColor grayColor] CGColor]);
                    CGContextSetLineWidth(context, lineWidth);
                    CGContextStrokePath(context);
                }
            }
        }
    }
    
    //接收起点按钮点击通知事件
    - (void)toucheBegin:(NSNotification *)notification{
       
        CGRect beginFrame = [notification.object CGRectValue];
        CGPoint startPoint = CGPointMake(CGRectGetMaxX(beginFrame), CGRectGetMidY(beginFrame));
        startPointString = NSStringFromCGPoint(startPoint);
        
        if (pointArray.count==0) {
            [pointArray addObject:startPointString];
        }
        else{
            [pointArray replaceObjectAtIndex:0 withObject:startPointString];
        }
    }
    
    //接收终点按钮点击通知事件
    - (void)toucheEnd:(NSNotification *)notification{
        
        CGRect endFrame = [notification.object CGRectValue];
        CGPoint endPoint = CGPointMake(CGRectGetMinX(endFrame), CGRectGetMidY(endFrame));
        endPointString = NSStringFromCGPoint(endPoint);
        
        if (pointArray.count==2) {
            [pointArray replaceObjectAtIndex:1 withObject:endPointString];
        }
        else{
            [pointArray addObject:endPointString];
        }
        
        [self clearSomeHistoryLineView];
        [self addLA];
        [self setNeedsDisplay];
    }
    
    //接收清除按钮点击通知事件
    - (void)clearLine:(NSNotification *)notification{
        [self clearAllLineView];
    }
    
    
    //接收重新绘制通知事件
    - (void)freshNeedsDisplay:(NSNotification *)notification{
        
        NSArray *relationslineArray = notification.object;
        lineArray = [NSMutableArray arrayWithArray:relationslineArray];
        [self setNeedsDisplay];
    }
    
    //添加连线
    -(void)addLA{
        NSArray *array = [NSArray arrayWithArray:pointArray];
        [lineArray addObject:array];
        [pointArray removeAllObjects];
    }
    
    //清除所有的连线
    - (void)clearAllLineView
    {
        [pointArray removeAllObjects];
        [lineArray removeAllObjects];
        [self setNeedsDisplay];
    }
    
     //移除历史交叉重复的连线
    - (void)clearSomeHistoryLineView{
        
        NSMutableArray *arrayM = [NSMutableArray array];
        for (int i=0; i < [lineArray count]; i++) {
            NSArray *array = [NSArray arrayWithArray:[lineArray objectAtIndex:i]];
            if ([array count] > 0) {
    
                NSString *hisBePointString = array.firstObject;
                NSString *hisEnPointString = array.lastObject;
    
                if ([startPointString isEqualToString:hisBePointString] || [endPointString isEqualToString:hisEnPointString]) {
                    [arrayM addObject:array];
                }
            }
        }
        [lineArray removeObjectsInArray:arrayM];
    }
    
    //移除通知
    -(void)dealloc{
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    
    @end
    View Code

    (4)计算尺寸

    LianXianFrameUitity.h

    //
    //  LianXianSizeUitity.h
    //  LianxianDemo
    //
    //  Created by 夏远全 on 2018/2/9.
    //  Copyright © 2018年 beijing. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    #import "LianXianModel.h"
    
    @interface LianXianFrameUitity : NSObject
    
    + (CGRect)calculateSizeWithModel:(LianXianModel *)lianxianModel;
    
    @end
    View Code

    LianXianFrameUitity.m 

    //
    //  LianXianSizeUitity.m
    //  LianxianDemo
    //
    //  Created by 夏远全 on 2018/2/9.
    //  Copyright © 2018年 beijing. All rights reserved.
    //
    
    #import "LianXianFrameUitity.h"
    #import "LianXianHeader.h"
    
    @implementation LianXianFrameUitity
    
    + (CGRect)calculateSizeWithModel:(LianXianModel *)lianxianModel{
        
        NSUInteger questionsCount = lianxianModel.questions.count;
        NSUInteger optionsCount = lianxianModel.options.count;
        
        CGFloat LHeight = questionsCount * (BHeight+Lpadding) + Lpadding;
        CGFloat RHeight = optionsCount * (BHeight+Rpadding) + Rpadding;
        
        CGFloat kWidth  = [UIScreen mainScreen].bounds.size.width; //默认宽度为屏幕的宽
        
        return CGRectMake(0, 0, kWidth, MAX(LHeight, RHeight));
    }
    
    @end
    View Code

    (5)创建组件

    LianXianComponentsView.h

    //
    //  LianXianComponentsView.h
    //  LianxianDemo
    //
    //  Created by 夏远全 on 2018/2/6.
    //  Copyright © 2018年 beijing. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    #import "LianXianModel.h"
    
    @interface LianXianComponentsView : UIView
    @property (nonatomic, strong) LianXianModel *lianxianModel;
    @end
    View Code

    LianXianComponentsView.m

    //
    //  LianXianComponentsView.m
    //  LianxianDemo
    //
    //  Created by 夏远全 on 2018/2/6.
    //  Copyright © 2018年 beijing. All rights reserved.
    //
    
    #import "LianXianComponentsView.h"
    #import "LianxianDrawView.h"
    #import "LianXianHeader.h"
    
    @interface LianXianComponentsView() {
        NSMutableArray *_leftBtns;
        NSMutableArray *_rightBtns;
        UIButton       *currentLeftBtn;
        CGFloat        borderWith;
    }
    
    @end
    
    @implementation LianXianComponentsView
    
    //对进行重写,以便在视图初始化的时候创建并设置自定义的Context
    - (id)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame]) {
            [self setupDefalutValue];
        }
        return self;
    }
    
    //设置默认值
    - (void)setupDefalutValue{
        
        self.backgroundColor = [UIColor clearColor];
        borderWith = 2.5;
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(restStatus:) name:kClearAllLineNotification object:nil];
    }
    
    
    //接收模型
    -(void)setLianxianModel:(LianXianModel *)lianxianModel{
        
        _lianxianModel = lianxianModel;
        [self setupLianXianUnit];
        
        if (lianxianModel && lianxianModel.relationships.count>0) {
            [self showLianXianResult];
        }
        else{
            [self listClickLeftButton];
        }
    }
    
    //绘制连线选项
    - (void)setupLianXianUnit{
        
        _leftBtns  = [[NSMutableArray array] init];
        _rightBtns = [[NSMutableArray array] init];
    
        CGFloat kWidth   = self.frame.size.width;
        CGFloat kHeight  = self.frame.size.height;
        CGFloat LY = (kHeight-(BHeight+Lpadding)*(self.lianxianModel.questions.count-1) - BHeight)/2;
        CGFloat RY = (kHeight-(BHeight+Rpadding)*(self.lianxianModel.options.count-1) - BHeight)/2;
        
        for (NSInteger i =0; i < self.lianxianModel.questions.count; i++) {
            UIButton *btn = [self createButtonWithFrame:CGRectMake(margin, LY+(BHeight+Lpadding)*i, BWidth, BHeight) title:[NSString stringWithFormat:@"%@",self.lianxianModel.questions[i]] tag:i];
            [self addSubview:btn];
            [_leftBtns addObject:btn];
        }
        
        for (NSInteger i =0; i< self.lianxianModel.options.count; i++) {
            UIButton *btn = [self createButtonWithFrame:CGRectMake(kWidth-margin-BWidth, RY+(BHeight+Rpadding)*i, BWidth, BHeight) title:[NSString stringWithFormat:@"%@",self.lianxianModel.options[i]] tag:i];
            [self addSubview:btn];
            [_rightBtns addObject:btn];
        }
    }
    
    
    -(UIButton *)createButtonWithFrame:(CGRect)frame title:(NSString *)title tag:(NSInteger)tag{
        
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.frame = frame;
        btn.layer.cornerRadius = 5.0;
        btn.layer.borderColor = [UIColor lightGrayColor].CGColor;
        btn.layer.borderWidth = borderWith;
        btn.layer.masksToBounds = YES;
        btn.tag = tag;
        
        [btn setBackgroundImage:[self imageWithColor:[UIColor whiteColor]] forState:UIControlStateNormal];
        [btn setBackgroundImage:[self imageWithColor:[UIColor colorWithRed:138/255.0 green:193/255.0 blue:211/255.0 alpha:1]] forState:UIControlStateHighlighted];
        [btn setBackgroundImage:[self imageWithColor:[UIColor colorWithRed:138/255.0 green:193/255.0 blue:211/255.0 alpha:1]] forState:UIControlStateSelected];
        
        [btn addTarget:self action:@selector(tapBtn:) forControlEvents:UIControlEventTouchUpInside];
        [btn setTitle:title forState:UIControlStateNormal];
        [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        
        return btn;
    }
    
    
    - (UIImage *)imageWithColor:(UIColor *)color
    {
        CGFloat imageW = 20;
        CGFloat imageH = 20;
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(imageW, imageH), NO, 0.0);
        [color set];
        UIRectFill(CGRectMake(0, 0, imageW, imageH));
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image;
    }
    
    
    -(void)tapBtn:(UIButton *)btn{
        
        //判断左边按钮是否处于选择状态,只有首先左边处于此状态下,右边的按钮点击才能进行连线操作(当前仅支持单向连线)
        if ([_rightBtns containsObject:btn]) {
            BOOL isLeftBtnSelected = NO;
            for (UIButton *leftBtn in _leftBtns) {
                if (leftBtn.selected) {
                    isLeftBtnSelected = YES;
                    break;
                }
            }
            if (!isLeftBtnSelected) {
                return;
            }
        }
        
        if ([_leftBtns containsObject:btn]) {
        
            //设置连线起点
            currentLeftBtn.selected = NO;
            currentLeftBtn.layer.borderColor = [UIColor lightGrayColor].CGColor;
            btn.selected = YES;
            currentLeftBtn = btn;
            currentLeftBtn.layer.borderColor = [UIColor colorWithRed:32/255.0 green:199/255.0 blue:251/255.0 alpha:1].CGColor;
            
            //设置终点按钮可以选中状态
            for (UIButton *rightBtn in _rightBtns) {
                rightBtn.layer.borderColor = [UIColor colorWithRed:32/255.0 green:199/255.0 blue:251/255.0 alpha:1].CGColor;
            }
            
            //发送起点通知
            [[NSNotificationCenter defaultCenter] postNotificationName:kBeginPositionNotification object:[NSValue valueWithCGRect:btn.frame]];
        }
        
        
        if ([_rightBtns containsObject:btn]) {
            
            for (UIButton *leftBtn in _leftBtns) {
                if (leftBtn.selected) {
                    
                    //发送终点通知
                    [[NSNotificationCenter defaultCenter] postNotificationName:kEndPositionNotification object:[NSValue valueWithCGRect:btn.frame]];
                    
                    //自动设置起始选择按钮
                    [self listClickLeftButton];
                    
                    break;
                }
            }
        }
    }
    
    //自动设置起始选择按钮
    - (void)listClickLeftButton{
        
        if (!currentLeftBtn) {
            [self tapBtn:_leftBtns[0]];
            return;
        }
        
        NSUInteger tag = currentLeftBtn.tag;
        if (tag < _leftBtns.count-1) {  //自动下移
            [self tapBtn:_leftBtns[tag+1]];
        }
        else{
            [self tapBtn:_leftBtns[0]]; //重新开始
        }
    }
    
    //绘制默认已经连线的选项,此处仅仅做成绩预览使用,不能再编辑
    - (void)showLianXianResult{
        
        for (UIButton *leftBtn in _leftBtns) {
            leftBtn.layer.borderColor = [UIColor lightGrayColor].CGColor;
            leftBtn.selected = leftBtn.userInteractionEnabled = NO;
        }
        
        for (UIButton *rightBtn in _rightBtns) {
            rightBtn.layer.borderColor = [UIColor lightGrayColor].CGColor;
            rightBtn.selected = rightBtn.userInteractionEnabled = NO;
        }
        
        if (self.lianxianModel.relationships.count == 0) {
            return;
        }
        
        NSMutableArray *relationslineArray = [NSMutableArray array];
        
        for (NSString *result in self.lianxianModel.relationships) {
            
            NSString *question = [[result componentsSeparatedByString:@"-"] firstObject];
            NSString *option   = [[result componentsSeparatedByString:@"-"] lastObject];
            NSMutableArray *pointArray = [NSMutableArray array];
            
            for (UIButton *leftBtn in _leftBtns) {
    
                if ([leftBtn.currentTitle isEqualToString:question]) {
                    CGPoint startPoint = CGPointMake(CGRectGetMaxX(leftBtn.frame), CGRectGetMidY(leftBtn.frame));
                    NSString *startPointString = NSStringFromCGPoint(startPoint);
                    [pointArray addObject:startPointString];
                    break;
                }
            }
    
            for (UIButton *rightBtn in _rightBtns) {
    
                if ([rightBtn.currentTitle isEqualToString:option]) {
                    CGPoint endPoint = CGPointMake(CGRectGetMinX(rightBtn.frame), CGRectGetMidY(rightBtn.frame));
                    NSString *endPointString = NSStringFromCGPoint(endPoint);
                    [pointArray addObject:endPointString];
                    break;
                }
            }
        
            [relationslineArray addObject:pointArray];
        }
        
        if (relationslineArray.count > 0) {
            [[NSNotificationCenter defaultCenter] postNotificationName:kFreshDrawLineNotification object:relationslineArray];
        }
    }
    
    
    //重置初始状态
    - (void)restStatus:(NSNotification *)notification{
        
        for (UIButton *leftBtn in _leftBtns) {
            leftBtn.selected = NO;
            leftBtn.layer.borderColor = [UIColor lightGrayColor].CGColor;
            [self tapBtn:_leftBtns[0]]; //重新开始
        }
    }
    
    @end
    View Code

    (6)连线容器

    LianXianContainerView.h

    //
    //  LianXianContainerView.h
    //  LianxianDemo
    //
    //  Created by 夏远全 on 2018/2/8.
    //  Copyright © 2018年 beijing. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    #import "LianXianComponentsView.h"
    #import "LianxianDrawView.h"
    
    @interface LianXianContainerView : UIView
    @property (nonatomic, strong) LianXianComponentsView *componentsView;
    @property (nonatomic, strong) LianxianDrawView *lianXianView;
    @end
    View Code

    LianXianContainerView.m

    //
    //  LianXianContainerView.m
    //  LianxianDemo
    //
    //  Created by 夏远全 on 2018/2/8.
    //  Copyright © 2018年 beijing. All rights reserved.
    //
    
    #import "LianXianContainerView.h"
    #import "LianXianComponentsView.h"
    #import "LianxianDrawView.h"
    #import "LianXianModel.h"
    
    @implementation LianXianContainerView
    
    - (id)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame]) {
            [self setup];
        }
        return self;
    }
    
    - (void)setup{
        
        self.lianXianView = [[LianxianDrawView alloc]initWithFrame:self.bounds];
        self.componentsView = [[LianXianComponentsView alloc] initWithFrame:self.bounds];
    
        [self addSubview:self.lianXianView];
        [self addSubview:self.componentsView];
    }
    
    @end
    View Code

    (7)显示连线

    //
    //  ViewController.m
    //  LianxianDemo
    //
    //  Created by tianjing on 15/3/31.
    //  Copyright © 2015年 tianjing. All rights reserved.
    //
    
    #import "ViewController.h"
    
    #import "LianXianContainerView.h"
    #import "LianXianFrameUitity.h"
    #import "LianXianModel.h"
    #import "LianXianHeader.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        UIButton *clearBtn = [[UIButton alloc] initWithFrame:CGRectMake(50, 50, 100, 40)];
        clearBtn.backgroundColor = [UIColor greenColor];
        [clearBtn setTitle:@"重置" forState:UIControlStateNormal];
        [clearBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
        [clearBtn addTarget:self action:@selector(clear:) forControlEvents:UIControlEventTouchUpInside];
        
        //创建模型
        LianXianModel *lianxianModel = [[LianXianModel alloc] init];
        lianxianModel.questions = @[@"",@"",@""]; /// 左边选项
        lianxianModel.options = @[@"",@"",@""];   /// 右边选项
        //lianxianModel.relationships = @[@"天-世",@"好-夏",@"人-锋"]; /// 连线关系,如果不为空,就只显示,不能编辑
        //clearBtn.hidden = (lianxianModel.relationships.count>0);
        
        //连线视图
        CGRect frame = [LianXianFrameUitity calculateSizeWithModel:lianxianModel];
        LianXianContainerView *containerView = [[LianXianContainerView alloc] initWithFrame:frame];
        containerView.center = self.view.center;
        containerView.componentsView.lianxianModel = lianxianModel;
        
        [self.view addSubview:containerView];
        [self.view addSubview:clearBtn];
    }
    
    
    - (void)clear:(UIButton *)sender{
        [[NSNotificationCenter defaultCenter] postNotificationName:kClearAllLineNotification object:nil];
    }
    
    @end
    View Code

    四、效果

    提示:

    左边按钮每次只有一个处于可连状态,而且每一次连接完会循环自动下移。

    右边所有按钮始终处于可连状态。

    同一个按钮再一次连接新的连线后,之前旧的跟其相关的连线都会被取消。 

     

      

    五、采坑

    如果练习题的界面是放在cell中的,因为复用的问题,在发送起点和终点的通知时,要对通知做唯一标识处理。

    如果不这么做,可能会出现的bug是:上一道做过的连线题的连线会出现在下一道还没有做过的连线题上。

  • 相关阅读:
    远程桌面连接win10问题解决
    为什么n各节点的的二叉链表中有n+1个空链域
    西门子Step7找不到有效授权的解决方法
    表达式树获取函数命名
    逆波兰表达式
    双向循环链表实践
    快速找到未知长度单链表的中间节点
    java的ArrayList(线性表)和LinkedList(双向链表)的深入学习
    23种设计模式中的访问者模式
    23种设计模式中的原型模式
  • 原文地址:https://www.cnblogs.com/XYQ-208910/p/8532379.html
Copyright © 2011-2022 走看看