Skip to content

Latest commit

Β 

History

History
296 lines (230 loc) Β· 8.95 KB

README.md

File metadata and controls

296 lines (230 loc) Β· 8.95 KB

πŸ”’ 1024!


πŸ“– λͺ©μ°¨


πŸ€ μ†Œκ°œ

같은 숫자 λΈ”λŸ­μ„ λ§€μΉ­μ‹œμΌœ 더 큰 숫자λ₯Ό λ§Œλ“€μ–΄λ³΄μ„Έμš”! λͺ©ν‘œ 점수 1024! (단, λΈ”λŸ­ 합성은 μ„Έλ‘œλ§Œ κ°€λŠ₯!)


πŸ’» μ‹€ν–‰ ν™”λ©΄

κ²Œμž„ μ‹€ν–‰ κ²Œμž„ 성곡 κ²Œμž„ μ‹€νŒ¨

πŸ› οΈ μ‚¬μš© 기술

κ΅¬ν˜„ λ‚΄μš© 도ꡬ
아킀텍쳐 MVC
UI UIKit
μ• λ‹ˆλ©”μ΄μ…˜ CoreAnimation

πŸ‘€ Diagram

πŸ“ UML


🧨 νŠΈλŸ¬λΈ” μŠˆνŒ…

1️⃣ λΈ”λŸ­ 연쇄 ν•©μ„±

🚨 문제점

  • λΈ”λŸ­μ΄ λ‹¨κ³„μ μœΌλ‘œ μŒ“μ—¬μžˆμ„ λ•Œ, μ—°μ‡„μ μœΌλ‘œ 합성이 λ˜μ–΄μ•Ό ν•˜λŠ”λ° 제일 μœ„μ— μžˆλŠ” λΈ”λŸ­λ§Œ ν•©μ„±λ˜κ³  λ©ˆμΆ”λŠ” 문제점이 λ°œμƒν•˜μ˜€μŠ΅λ‹ˆλ‹€.
    (예λ₯Ό λ“€μ–΄, λΈ”λŸ­μ΄ μ•„λž˜λΆ€ν„° 4, 2 μˆœμ„œλ‘œ μŒ“μ—¬μžˆκ³  2λ₯Ό μΆ”κ°€ν•˜λ©΄ 2+2=4, 4+4=8이 λ˜μ–΄μ„œ 8λΈ”λŸ­μ΄ 남아야 ν•˜λŠ”λ° 4λΈ”λŸ­ 두 κ°œκ°€ μŒ“μ—¬μžˆλŠ” μƒνƒœμ—μ„œ λ©ˆμΆ”λŠ” ν˜„μƒ)

πŸ’‘ 해결방법

  • GameLogic클래슀의 validatePositionλ©”μ„œλ“œμ—μ„œ λΈ”λŸ­μ΄ 합쳐지면 pointArrayλ₯Ό λ°˜ν™˜ν•˜λ©΄μ„œ ν•¨μˆ˜μ™€ ν•¨κ»˜ μžλ™μœΌλ‘œ μ’…λ£Œλ˜μ—ˆλ˜ for문을 더 이상 ν•©μ³μ§ˆ λΈ”λŸ­μ΄ 없을 λ•Œ breakλ₯Ό ν•˜κ³  κ·Έ μ™ΈλŠ” κ°€μž₯ μ•„λž˜μͺ½κΉŒμ§€ λ°˜λ³΅ν•  수 μžˆλ„λ‘ μ½”λ“œλ₯Ό μˆ˜μ •ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

πŸ”€ μ½”λ“œ λ³€ν™”

  • μˆ˜μ • μ „
    final class GameLogic {
    
        // ...
        func validatePosition(tappedX: CGFloat, block: BlockView) -> CGPoint {
        let (line, pointArray) = decideLine(tappedX: tappedX)
    
        for i in 0..<line.list.count-1 {
            if line.hasNext(i) {
                let nextBlockView = line.next(i)
    
                if compareBlockView(block, nextBlockView) {
                    block.updateState()
                    line.insert(block, at: i+1)
                    nextBlockView.removeFromSuperview()
                    return pointArray[i+1]
                }
    
                line.insert(block, at: i)
                return pointArray[i]
            } else if i == line.list.count-2 {
                line.insert(block, at: i+1)
                return pointArray[i+1]
            }
        }
    
        return validatePosition(tappedX: tappedX, block: block)
    }
    
  • μˆ˜μ • ν›„

    final class GameLogic {
    
        // ...
        func validatePosition(tappedX: CGFloat, block: BlockView) -> CGPoint {
        let (line, pointArray) = decideLine(tappedX: tappedX)
        var value: CGPoint = CGPoint(x: 0, y: 0)
    
        for i in 0..<line.list.count-1 {
            if line.hasNext(i) {
                var nextBlockView = line.next(i)
    
                if compareBlockView(block, nextBlockView) == false {
                    line.insert(block, at: i)
                    value = pointArray[i]
                    break
                }
    
                block.updateState()
                line.insert(block, at: i+1)
    
                if i < 5 {
                    nextBlockView.removeFromSuperview()
                    nextBlockView = line.next(i+1)
                }
    
                value = pointArray[i+1]
            } else if i == line.list.count-2 {
                line.insert(block, at: i+1)
                value = pointArray[i+1]
                break
            }
        }
    
        return value
    }
    

2️⃣ Line

🚨 문제점

  • GameLogic λ‚΄ Line을 λ°°μ—΄λ‘œλ§Œ κ΄€λ¦¬ν•˜μ—¬ λΆˆν•„μš”ν•œ μ½”λ“œκ°€ λ§Žμ•˜μŠ΅λ‹ˆλ‹€.

πŸ’‘ 해결방법

  • BlockView의 μ‚½μž… 및 μˆœμ„œ 관리λ₯Ό ν•΄μ£ΌλŠ” Line 객체 μƒμ„±ν•˜μ—¬ Line을 μ‰½κ²Œ κ΄€λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€.

πŸ”€ μ½”λ“œ λ³€ν™”

  • μˆ˜μ • μ „
    final class GameLogic {
        var line1: [Block?] = [nil, nil, nil, nil, nil, nil, nil]
        var line2: [Block?] = [nil, nil, nil, nil, nil, nil, nil]
        var line3: [Block?] = [nil, nil, nil, nil, nil, nil, nil]
        var line4: [Block?] = [nil, nil, nil, nil, nil, nil, nil]
        var line5: [Block?] = [nil, nil, nil, nil, nil, nil, nil]
        // ...
    }
  • μˆ˜μ • ν›„

    final class Line {
        var list: [Block?] = [nil, nil, nil, nil, nil, nil, nil]
    
        func insert(_ block: Block,at index: Int) {
            list.insert(block, at: index)
        }
    
        func hasNext(_ index: Int) -> Bool {
            return list[index + 1] != nil
        }
    
        func next(_ index: Int) -> Block {
            return list[index + 1]!
        }
    }
    final class GameLogic {
        var line1: Line = Line()
        var line2: Line = Line()
        var line3: Line = Line()
        var line4: Line = Line()
        var line5: Line = Line()
        // ...
    }

3️⃣ GameLogic

🚨 문제점

  • Controllerμ—μ„œ μ‚¬μš©μž 선택에 λ§žλŠ” Block μ’Œν‘œλ₯Ό μ°ΎλŠ” λΆˆν•„μš”ν•œ λ‘œμ§μ„ μˆ˜ν–‰ν–ˆμŠ΅λ‹ˆλ‹€.

πŸ’‘ 해결방법

  • GameLogic이 μ‚¬μš©μž 선택에 λ§žλŠ” Line을 μ°Ύμ•„ Block μ’Œν‘œλ₯Ό λ°˜ν™˜ν•˜λ„λ‘ λ³€κ²½ν•˜μ—¬, Controllerμ—μ„œ GameLogic.validatePositionλ₯Ό ν˜ΈμΆœν•˜μ—¬ Block의 μ’Œν‘œλ₯Ό μ„€μ •ν•˜λ„λ‘ ν–ˆμŠ΅λ‹ˆλ‹€.

πŸ”€ μ½”λ“œ λ³€ν™”

  • μˆ˜μ • μ „
     class ViewController: UIViewController {
         
         // ...
         @objc
         private func didTappedGridView() {
             let tappedPointX = tapGestureRecognizer.location(in: view).x
             
             if tappedPointX >= 23, tappedPointX < 93 {
                 block.x = 23
             } else if tappedPointX >= 93, tappedPointX < 163 {
                 block.x = 93
             } else if tappedPointX >= 163, tappedPointX < 233 {
                 block.x = 163
             } else if tappedPointX >= 233, tappedPointX < 303 {
                 block.x = 233
             } else {
                 block.x = 303
             }
         }
     }    
  • μˆ˜μ • ν›„

     final class GameLogic {
         
         // ...
         func decideLine(tappedX: CGFloat) -> (Line, [CGPoint]) {
             if tappedX < 95 {
                 return (line1, pointArray1)
             } else if tappedX >= 95, tappedX < 163 {
                 return (line2, pointArray2)
             } else if tappedX >= 163, tappedX < 231 {
                 return (line3, pointArray3)
             } else if tappedX >= 231, tappedX < 299 {
                 return (line4, pointArray4)
             } else {
                 return (line5, pointArray5)
             }
         }
         
         func validatePosition(tappedX: CGFloat, block: BlockView) -> CGPoint {
             let (line, pointArray) = decideLine(tappedX: tappedX)
             var value: CGPoint = CGPoint(x: 0, y: 0)
             
             // point finding logic
             
             return value
         }
     }
     class ViewController: UIViewController {
         
         // ...
         @objc
         private func didTappedGridView() {
             let tappedPointX = tapGestureRecognizer.location(in: view).x
             let point = gameLogic.validatePosition(tappedX: tappedPointX, block: blockView.blockState)
             
             blockView.frame.origin = point
         }
     }

4️⃣ μ• λ‹ˆλ©”μ΄μ…˜

🚨 문제점

  • 기본적으둜 λΈ”λŸ­μ΄ 생성될 λ•Œ μœ„μΉ˜μ— λ°”λ‘œ λ‚˜νƒ€λ‚˜κΈ° λ•Œλ¬Έμ— λΈ”λŸ­μ΄ μ—¬λŸ¬ 개 μŒ“μ—¬μžˆμ„ 경우 λΈ”λŸ­μ΄ μƒμ„±λ˜μ—ˆλŠ”μ§€ μΈμ‹ν•˜κΈ° νž˜λ“€λ‹€λŠ” λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ μ‚¬μš©μž κ²½ν—˜μƒ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ λΈ”λŸ­ 생성 μ‹œ λˆˆμ— λ„κ²Œ λ§Œλ“€ 방법이 ν•„μš”ν–ˆμŠ΅λ‹ˆλ‹€.

πŸ’‘ 해결방법

  • λΈ”λŸ­ 생성 μ‹œ μ• λ‹ˆλ©”μ΄μ…˜μ„ μΆ”κ°€ν•΄ λˆˆμ— 띄고 보기 μ’‹κ²Œ λ§Œλ“€μ–΄ μ‚¬μš©μž κ²½ν—˜μ„ κ°œμ„ ν–ˆμŠ΅λ‹ˆλ‹€.

πŸ”€ μ½”λ“œ λ³€ν™”

  • μ• λ‹ˆλ©”μ΄μ…˜ μΆ”κ°€

    func runSpringAnimation() {
        let jump = CASpringAnimation(keyPath: "transform.scale")
        jump.damping = 15
        jump.mass = 1
        jump.initialVelocity = 10
        jump.stiffness = 100
        jump.fromValue = 0
        jump.toValue = 1
        jump.duration = jump.settlingDuration
        
        self.layer.add(jump, forKey: nil)
    }