上班不能摸鱼,就自己写个拼图当消遣吧。
目的就是实现可选33 44 等不同大小的拼图游戏。 涉及知识点是逆序数计算。
class CollectionModel: NSObject {
var isEmpty:Bool = false
var itemIndex:Int = -1
var image:UIImage?
}
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var collectionView: UICollectionView!
var collectionData = [CollectionModel]()
var difficulty:Int = 3
@IBOutlet weak var difficultyTF: UITextField!
@IBOutlet weak var tips1: UILabel!
@IBOutlet weak var tips2: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
func loadSubviews(){
if(self.collectionView != nil){
self.collectionView.removeFromSuperview()
}
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
let itemWidth = self.view.frame.width/CGFloat(difficulty)
layout.itemSize = CGSize.init(width: itemWidth, height: itemWidth)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.sectionInset = .init(top: 0, left: 0, bottom: 0, right: 0)
collectionView = UICollectionView(frame: CGRect(x: 0, y: 258, width: self.view.frame.width, height: self.view.frame.width), collectionViewLayout: layout)
collectionView.dataSource = self
collectionView.delegate = self
collectionView.showsHorizontalScrollIndicator = false
collectionView.showsVerticalScrollIndicator = false
collectionView.isScrollEnabled = false
collectionView.register(UINib(nibName: "KlotskiCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "KlotskiCollectionViewCell")
collectionView.backgroundColor = UIColor(white: 0.95, alpha: 1)
self.view.addSubview(collectionView)
}
@IBAction func test(_ sender: Any) {
difficulty = Int(difficultyTF.text ?? "3") ?? 3
difficulty = difficulty < 3 ? 3 : difficulty
difficulty = difficulty > 6 ? 6 : difficulty
self.collectionData.removeAll()
let randomNumbers = self.getAvailableRandomNumbers(count: difficulty*difficulty-1)
randomNumbers.forEach { index in
let model = CollectionModel()
model.itemIndex = index
model.isEmpty = index == randomNumbers.count-1 ? true : false
self.collectionData.append(model)
}
self.loadSubviews()
self.collectionView.reloadData()
}
func getAvailableRandomNumbers(count:Int) -> [Int]{
var randomArr = [Int](0...count)
repeat{
randomArr.shuffle()
}while !self.checkNumbersAvailable(arr: randomArr)
self.tips1.text = "\(randomArr)"
return randomArr
}
func checkNumbersAvailable(arr:[Int])-> Bool{
var inverseCount = 0
arr.forEach { currentNumber in
let index = arr.firstIndex(of: currentNumber) ?? 0
if index != arr.count-1 {
for i in (index+1)..<arr.count {
let checkNumber = arr[i]
inverseCount += currentNumber > checkNumber ? 1 : 0
}
}
// 这个是针对偶数边长阵列 要计算空白坐标位置,网上看的
if currentNumber == arr.count-1 {
inverseCount += difficulty-1-(index/difficulty)
inverseCount += difficulty-1-(index%difficulty)
}
}
self.tips2.text = "逆序数:\(inverseCount)"
return inverseCount%2 == 0
}
func checkKlotskiSuccess(){
var success = true
for model in collectionData {
let index = collectionData.firstIndex(of: model)
if(index != model.itemIndex){
success = false
break
}
}
if(success){
self.tips2.text = "Congratulation! Success!"
}
}
func checkItemSwap(index:Int)->Int{
let currentModel = self.collectionData[index]
if currentModel.isEmpty { return -1}
let leftIndex = index - 1
if(index%difficulty > 0 && leftIndex >= 0){
if(collectionData[leftIndex].isEmpty == true){
return leftIndex
}
}
let rightIndex = index + 1
if(index%difficulty < difficulty-1 && rightIndex < collectionData.count){
if(collectionData[rightIndex].isEmpty == true){
return rightIndex
}
}
let topIndex = index - difficulty
if(topIndex >= 0 && collectionData[topIndex].isEmpty == true){
return topIndex
}
let bottomIndex = index + difficulty
if(bottomIndex < collectionData.count && collectionData[bottomIndex].isEmpty == true){
return bottomIndex
}
return -1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return collectionData.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "KlotskiCollectionViewCell", for: indexPath) as! KlotskiCollectionViewCell
let model = self.collectionData[indexPath.row]
cell.setCellData(model: model)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let swapIndex = self.checkItemSwap(index: indexPath.row)
guard swapIndex >= 0 else { return }
self.collectionData.swapAt(indexPath.row, swapIndex)
self.collectionView.reloadItems(at: [indexPath, IndexPath(row: swapIndex, section: 0)])
self.checkKlotskiSuccess()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
}
测试按钮和文字提示在XIB上,就不放出来了。 其中备注部分就是要计算空白块的坐标,原理参考的这个老哥的帖子:九宫格避免不可还原