直接上效果图:
这里是具体代码
//
// 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
}
}