Swift 语言开发之手势处理方面的拼图.

直接上效果图:

这里是具体代码

//
//  ViewController.swift
//  ThePuzzleDemo
//
//  Created by dongqiangfei on 2019/2/18.
//  Copyright © 2019年 飞飞. All rights reserved.
//

import UIKit
class NumsValue {//使用类. 引用类型 修改数据直接就修改了数组里的数据
    var reallyLocatiion = 0 //原来的位置
    var nowLocatiion = 0 // 现在的位置
    var ifMove = false
}

class ViewController: UIViewController {
    
    let screenWidth = Double(UIScreen.main.bounds.size.width)
    let screenHeight = Double(UIScreen.main.bounds.size.height)
    var nums = 3
    var numWidth = (Double(UIScreen.main.bounds.size.width)) / 3
    var dataArr:[NumsValue] = []
    var flag = false
    var middleView = UIView()
    var ifMovedToEnd = false
    var ifOutSide = false
    var blankLocation = 0 //空白图格的位置
    var moveLocation = 0 //当前拖动的图格的位置
    var blankLab = UILabel() //空白label
    var endlocation = 0 // z拖到最终的位置必须和空白是一个位置
    var touchBeginPoint = CGPoint(x:0, y:0)
    var moveTheDirection = 1 /**1 上下 2 左右*/
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.lightGray
        makeTopBtn()
        makeUI()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    func makeTopBtn() {
        let arr = ["初级", "中级", "高级", "骨灰级", "打乱数据","随机挪动一次"]
        for index in 0..<(arr.count) {
            let upSetBtn = UIButton(frame: CGRect(x: (screenWidth / 4) * Double(index % 4), y: Double(index > 3 ? 80 : 30), width: screenWidth / 4 + Double(index == 5 ? 100 : 0), height: 50))
            upSetBtn.setTitle(arr[index], for: .normal)
            upSetBtn.tag = 1000 + index
            upSetBtn.addTarget(self, action: #selector(upSetBtnClick(btn:)), for: .touchUpInside)
            view.addSubview(upSetBtn)
        }
    }
    
    @objc func upSetBtnClick(btn: UIButton) {
        let btnTag = btn.tag
        if btnTag == 1004 { //打乱数据1000次
            upsetAll(arms: 1000)
        } else if btnTag == 1005 { //打乱数据1次
            upsetAll(arms: 1)
        } else { // 3*3 4*4 5*5 6*6
            nums = btnTag - 1000 + 3
            numWidth = (Double(UIScreen.main.bounds.size.width)) / Double(nums)
            middleView.removeFromSuperview()
            makeUI()
        }
    }
    
    func makeUI() {
        middleView = UIView(frame: CGRect(x: 0, y: screenHeight / 2 - screenWidth / 2, width: screenWidth, height: screenWidth))
        middleView.backgroundColor = UIColor.init(red: 250/255.0, green: 250/255.0, blue: 250/255.0, alpha: 1)
        view.addSubview(middleView)
        dataArr.removeAll()
        for index in 0..<(nums*nums) {
            let numLab = UILabel(frame: CGRect(x: numWidth * Double(index % nums), y: numWidth * Double(index / nums), width: numWidth, height: numWidth))
            numLab.font = UIFont.boldSystemFont(ofSize: 40)
            numLab.textColor = UIColor.white
            numLab.textAlignment = .center
            numLab.tag = index + 100
            if index == (nums * nums - 1) {
                numLab.backgroundColor = UIColor.clear
                blankLocation = index
                blankLab = numLab
            } else {
                numLab.backgroundColor = UIColor.init(red: CGFloat(Double(arc4random() % 255) / 255.0), green: CGFloat(Double(arc4random() % 255) / 255.0), blue: CGFloat(Double(arc4random() % 255) / 255.0), alpha: 1)
                numLab.text = "\(index + 1)"
            }
            
            middleView.addSubview(numLab)
            let numsValue = NumsValue()
            numsValue.nowLocatiion = index
            numsValue.reallyLocatiion = index
            dataArr.append(numsValue)
        }
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        ifOutSide = false
        let point = getLabPoint(touches: touches)
        touchBeginPoint = point
        if point.y < 0 || Double(point.y) > (screenWidth) {
            return
        }
        //print("begin\(getLabNums(touches: touches))")
        moveLocation = getLabNums(touches: touches)
        let numValue = dataArr[moveLocation]
        moveLocation = numValue.nowLocatiion
        
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let point = getLabPoint(touches: touches)
        if point.y < -100 || Double(point.y) > (screenWidth + 100) {
            ifOutSide = true
        }
        ifMovedToEnd = true
        
        var xDistance = point.x - touchBeginPoint.x
        if xDistance < 0 {
            xDistance = -xDistance
        }
        
        var yDistance = point.y - touchBeginPoint.y
        if yDistance < 0 {
            yDistance = -yDistance
        }
        
        if xDistance > yDistance { //x 左右挪动
            moveTheDirection = 2
            if point.x - touchBeginPoint.x > 0 { //往右挪动
                if (moveLocation + 1 == blankLocation || moveLocation == blankLocation) && moveLocation%nums != (nums - 1) {
                    //即将拖动的格格 挪到空白位置
                    let thisValue = dataArr[moveLocation]
                    let moveLab = (middleView.viewWithTag(thisValue.reallyLocatiion + 100)) as! UILabel
                    var moveDistance = Double(point.x - touchBeginPoint.x)
                    if moveDistance >= numWidth {
                        moveDistance = numWidth
                    }
                    moveLab.frame = CGRect(x: numWidth * Double(moveLocation % nums) + moveDistance, y: numWidth * Double(moveLocation / nums), width: numWidth, height: numWidth)
                }
            } else { //往左挪动
                if (moveLocation - 1 == blankLocation || moveLocation == blankLocation) && moveLocation%nums != 0 {
                    //即将拖动的格格 挪到空白位置
                    let thisValue = dataArr[moveLocation]
                    let moveLab = (middleView.viewWithTag(thisValue.reallyLocatiion + 100)) as! UILabel
                    var moveDistance = Double(touchBeginPoint.x - point.x)
                    if moveDistance >= numWidth {
                        moveDistance = numWidth
                    }
                    moveLab.frame = CGRect(x: numWidth * Double(moveLocation % nums) - moveDistance, y: numWidth * Double(moveLocation / nums), width: numWidth, height: numWidth)
                }
            }
        } else { //上下挪动
            moveTheDirection = 1
            if point.y - touchBeginPoint.y > 0{ //往下挪动
                if (moveLocation + nums == blankLocation || moveLocation == blankLocation) && moveLocation/nums != (nums - 1) {
                    //即将拖动的格格 挪到空白位置
                    let thisValue = dataArr[moveLocation]
                    let moveLab = (middleView.viewWithTag(thisValue.reallyLocatiion + 100)) as! UILabel
                    var moveDistance = Double(point.y - touchBeginPoint.y)
                    if moveDistance >= numWidth {
                        moveDistance = numWidth
                    }
                    moveLab.frame = CGRect(x: numWidth * Double(moveLocation % nums), y: numWidth * Double(moveLocation / nums) + moveDistance, width: numWidth, height: numWidth)
                }
            } else { //往上挪动
                if (moveLocation - nums == blankLocation || moveLocation == blankLocation) && moveLocation/nums != 0 {
                    //即将拖动的格格 挪到空白位置
                    let thisValue = dataArr[moveLocation]
                    let moveLab = (middleView.viewWithTag(thisValue.reallyLocatiion + 100)) as! UILabel
                    var moveDistance = Double(touchBeginPoint.y - point.y)
                    if moveDistance >= numWidth {
                        moveDistance = numWidth
                    }
                    moveLab.frame = CGRect(x: numWidth * Double(moveLocation % nums), y: numWidth * Double(moveLocation / nums) - moveDistance, width: numWidth, height: numWidth)
                }
            }
        }
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
//        if ifOutSide {
//            print("拖你姥姥家去了")
//        } else {
            endlocation = getLabNums(touches: touches)
        //}
        if ifMovedToEnd && validationIfAdjacent() && (
            ( (moveLocation / nums > blankLocation / nums) && (endlocation <= blankLocation) && moveTheDirection == 1)// 上
            || ( (moveLocation % nums > blankLocation % nums) && (endlocation % nums <= blankLocation % nums) && moveTheDirection == 2) //左
            || ( (moveLocation / nums < blankLocation / nums) && (endlocation  >= blankLocation ) && moveTheDirection == 1) // 下
            || (( (moveLocation % nums < blankLocation % nums) && (endlocation % nums >= blankLocation % nums)) && moveTheDirection == 2) )// 右
        { //拖动了 且 拖到的是空白处  && (endlocation == blankLocation)
            //UI层互换
            exchangeUIAndData()
            print("touchend1")
        } else if (validationIfAdjacent() && (endlocation == blankLocation || (endlocation == moveLocation)) && !ifMovedToEnd){//单击的是相邻挪空白处的那就挪动吧
            exchangeUIAndData()
            print("touchend2")
        } else {
            let thisValue = dataArr[moveLocation]
            let moveLab = (middleView.viewWithTag(thisValue.reallyLocatiion + 100)) as! UILabel
            moveLab.frame = CGRect(x: numWidth * Double(moveLocation % nums), y: numWidth * Double(moveLocation / nums), width: numWidth, height: numWidth)
            print("touchend3")
        }
        ifMovedToEnd = false
    }
    
    func exchangeUIAndData() {
        //空白格格位置换到即将拖动的格格
        blankLab.frame = CGRect(x: numWidth * Double(moveLocation % nums), y: numWidth * Double(moveLocation / nums), width: numWidth, height: numWidth)
        //即将拖动的格格 挪到空白位置
        let thisValue = dataArr[moveLocation]
        let moveLab = (middleView.viewWithTag(thisValue.reallyLocatiion + 100)) as! UILabel
        moveLab.frame = CGRect(x: numWidth * Double(blankLocation % nums), y: numWidth * Double(blankLocation / nums), width: numWidth, height: numWidth)
        
        //互换内部数据
        exchangeValue(startNum: moveLocation, endNum: blankLocation)
        blankLocation = moveLocation
        judgeSuccess()
    }
    
    func getLabNums(touches: Set<UITouch>) -> Int{
        var rankNum = 0
        for touch:AnyObject in touches {//获取用户点击的坐标
            let point = (touch as AnyObject).location(in: middleView)
            let doubleX = Double(point.x)
            let doubleY = Double(point.y)
            rankNum = Int(doubleX / Double(numWidth)) + (Int(doubleY / Double(numWidth))) * nums
            //print("第几个lab:\(rankNum)")
        }
        return rankNum
    }
    
    func getLabPoint(touches: Set<UITouch>) -> CGPoint{
        var point: CGPoint = CGPoint(x: 0,y: 0)
        for touch:AnyObject in touches {//获取用户点击的坐标
            point = (touch as AnyObject).location(in: middleView)
        }
        return point
    }
    
    func validationIfAdjacent() -> Bool {//计算要拖动的格格是否与空白处相邻
        var ifAdjacent = false
        if moveLocation + 1 == blankLocation && (moveLocation % nums != (nums - 1)){
            ifAdjacent = true
        } else if moveLocation - 1 == blankLocation && (moveLocation % nums != 0){
            ifAdjacent = true
        } else if moveLocation + nums == blankLocation && (moveLocation / nums != (nums - 1)){
            ifAdjacent = true
        } else if moveLocation - nums == blankLocation && (moveLocation / nums != 0){
            ifAdjacent = true
        }
        return ifAdjacent
    }
    
    func upsetAll(arms: Int) {//打乱数据
        var replaceLocationArr:[Int] = []
        for _ in 0..<arms {
            replaceLocationArr.removeAll()
            if (blankLocation + 1 < (nums * nums))
                && (blankLocation + 1 > 0)
                && ((blankLocation + 1) % nums) != 0 {
                replaceLocationArr.append(blankLocation + 1)
            }
            
            if (blankLocation - 1 < (nums * nums))
                && (blankLocation - 1 >= 0)
                && ((blankLocation - 1 ) % nums) != (nums - 1) {
                replaceLocationArr.append(blankLocation - 1)
            }
            
            if (blankLocation + nums < (nums * nums))
                && (blankLocation + nums > 0)
                && (blankLocation / nums) != nums - 1 {
                replaceLocationArr.append(blankLocation + nums)
            }
            
            if (blankLocation - nums < (nums * nums))
                && (blankLocation - nums > 0)
                && (blankLocation / nums) != 0 {
                replaceLocationArr.append(blankLocation - nums)
            }
            //在数组里随机选择一个互换
            let armNum = Int(arc4random() % UInt32(replaceLocationArr.count))
            let replaceLocation = replaceLocationArr[armNum]
            
            //互换内部数据
            var resultValue = blankLocation - replaceLocation
            if resultValue < 0 {
                resultValue = -resultValue
            }
            
            //判断是否交换数据错误.
            //print("blank:\(blankLocation + 1) --- replace: \(replaceLocation + 1)")
//            if (blankLocation == 12 && replaceLocation == 13) {
//                print("error")
//            }
            
            exchangeValue(startNum: blankLocation, endNum: replaceLocation)
            blankLocation = replaceLocation
        }
        upSetUI()
        //pirintValue()
    }
    
    func upSetUI() {//打乱数据
        for index in 0..<(dataArr.count) {
            let thisValue = dataArr[index]
            let thisLab = (middleView.viewWithTag(thisValue.reallyLocatiion + 100)) as! UILabel
            thisLab.frame = CGRect(x: numWidth * Double(index % nums), y: numWidth * Double(index / nums), width: numWidth, height: numWidth)
        }
    }
    
    func pirintValue() {// 打印数据
        for value in dataArr {
            print("nowLocation:\(value.nowLocatiion) --- reallyLocation:\(value.reallyLocatiion)")
        }
    }
    
    func judgeSuccess() {
        var yesNums = 0
        for value in dataArr {
            if value.nowLocatiion == value.reallyLocatiion {
                yesNums = yesNums + 1
            }
        }
        if yesNums == dataArr.count {
            let alertVC = UIAlertController(title: "拼图成功喽", message: nil, preferredStyle: .alert)
            let action = UIAlertAction(title: "确定", style: .default) { (alert) in
            }
            alertVC.addAction(action)
            self.present(alertVC, animated: true, completion: nil)
        }
    }
    
    func exchangeValue(startNum: Int, endNum: Int) { //交换数据的s处理方法
        print("start:\(startNum + 1)---enduNum:\(endNum + 1)")
        
        let moveValue = dataArr[startNum]
        moveValue.nowLocatiion = endNum
        let blankVlaue = dataArr[endNum]
        blankVlaue.nowLocatiion = startNum
        
        let temp = dataArr[startNum]
        dataArr[startNum] = dataArr[endNum]
        dataArr[endNum] = temp
    }
    
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值