Skip to content

WhalesJin/2048

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

41 Commits
 
 
 
 
 
 
 
 

Repository files navigation

🔢 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)
    }

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages