GithubHelp home page GithubHelp logo

jinios / swift-cardgameapp Goto Github PK

View Code? Open in Web Editor NEW

This project forked from code-squad/swift-cardgameapp

0.0 0.0 0.0 12.53 MB

솔리테어 카드게임앱 - 코드스쿼드 미션 (2018.04 - 2018.05)

Swift 100.00%

swift-cardgameapp's People

Contributors

godrm avatar jinios avatar

Watchers

 avatar

swift-cardgameapp's Issues

DeckView에 카드가 드래그되면 카드뷰가 없어지는 문제

카드덱과 관련된 위치에 카드뷰가 드래그되면 카드뷰가 사라지는 문제

  • 카드덱에 있던 카드뷰가 다른 스택, 혹은 파운데이션으로 으로 옮겨졌는데 rule에 맞지 않아 리턴되는 경우
  • 스택에 있던 카드뷰가 카드덱으로 옮겨졌는데 다시 스택으로 돌아오는 경우
  • 이때 카드모델은 그대로 존재하지만 카드뷰만 없어지는 현상임
  • 드래그 제스쳐가 끝나거나 시작한 위치가 deck인 경우 서브뷰들을 모델대로 업데이트하는 로직이 없어서 발생하는듯

우측 상단에 Stack에 표시한 카드 제외한 나머지를 CardDeck으로표시

  • 카드스택에 표시한 카드를 제외하고 남은 카드를 우측 상단에 뒤집힌 상태로 쌓아놓는다.
  • 맨위에 있는 카드를 터치하면 좌측에 카드 앞면을 표시하고, 다음 카드 뒷면을 표시한다.
  • 만약 남은 카드가 없는 경우는 우측에도 빈 카드를 대신해서 반복할 수 있다는 이미지(refresh)를 표시한다.

드래그 앤 드롭 - UIPanGestureRecognizer의 .ended구현

(이미 사용자가 뷰 내에서 원하는 곳까지 드래그를 마친 상태. 뷰만 옮겨져있음)

.ended 일때의 로직 flow

  • 카드위치 확인 - movableViews의 마지막 위치가 toFrame위치 내부에 진입했는지확인
    • (toFrame 값의 origin에서 오른쪽/하향 방향으로 카드 가로세로 위치 내부인지 확인)
  • 모델에서 확인 - 해당 toFrame에 현재 movable cards들이 위치할 수 있는지
  • 애니메이션적용 - 모델에서 확인한 값이 true이면 사용자가 드래그를 놓은 위치에서 카드스택의 맞는 위치까지 animation적용

animation complete후 모델이 제대로 업데이트되지 않는 문제

image

  • 그림에서 보면 맞는 위치에 드래그 후 게임 룰에 맞게 뷰가 옮겨진 것을 알 수 있음 ( A♥️, 9♦️)
  • 하지만 원래 위치에있던 카드모델이 제거되지 않았기때문에 뷰를 reload하면서 원래 위치에도 또 뷰가 그려짐
  • 바뀐 위치에 있는 카드뷰는 movableView로 removeFromSuperView되어야 하는 대상임.
  • 모델 업데이트하는 부분 수정하여 뷰와 싱크 맞추기
  • CardGameManager.ruleCheck()

subclass CardImageView의 사이즈는 속성으로 고정하고 VC에서 origin만 부여하여 생성하는 방법

Q. 어차피 카드 이미지의 크기는 모두 똑같고, 계산해놓은 카드 이미지 사이즈을 알 수 있기 때문에 CardImageView에 속성을 지정해놓은것처럼 사이즈도 fix시키고, VC에서는 origin만 알려주고 생성하면 더 효율적이지 않을까?

<예상되는 문제점>

  • 지금은 cardSize라는 computed property가 VC에 있기때문에, VC의 루트 뷰 frame 기준으로 카드의 가로, 세로 길이를 구한 것을 코드만 봐도 알 수 있다. 하지만 만약 이 값을 CardImageView내부에서 바로 상수로쓰면, 다른 사람은 이 값이 어떻게 구해진건지 알 수 없다.
  • 또한 루트뷰에 추가되는 서브뷰이므로 사이즈를 계산하고 부여하는게 VC에서 바로 볼 수 있는게 더 자연스러울 수도 있다.
  • 또한 만약 디바이스가 변경된다면 루트뷰의 frame이 달라지기때문에 상수로 선언한 카드사이즈가 다른 디바이스 뷰 상에서는 맞지 않을 수 있다.
  • 매번 subView의 크기를 루트뷰의 frame에 따라 계산해야한다면, subView에서는 superView의 frame을 알아와서 계산하고, 계산한 값을 init()내부에서 size로 fix할 수 있는지? 만약 가능하다면 이 방법이 자연스러운건지?_?

싱글탭이벤트 처리 flow변경

  • 현재는 DeckView내부에서 모두처리하므로 view내에 로직도 들어있는 상태임
  • 더블탭 처리flow처럼
    • DeckView에서 이벤트 받음 - CardGameDelegate에게 Notify - Deck담당 Model에게 로직실행 - 로직 실행으로 인해 변경된 상태 VC에 Notify - DeckView에게 redraw호출 로 변경할 것

Stack카드들이 드래그로 움직였을때 도착지점(y 위치)

  • 출발 - 도착 지점이 stack - stack인 경우 y포지션이PositionY.upper.value
  • 이때 움직이는 movableCards의 마지막카드기준으로 PositionY.upper.value가 도착지점이 되어버려서 카드스택자체가 위로 올라갔다가 다시 그려짐
  • movableCards의 첫번째 카드 기준으로 y position 잡기
    image

CardDeck과 GameTable을 표현하는 뷰 만들기

  • CardDeck 인스턴스를 만들고 랜덤으로 카드를 섞고 출력 화면처럼 보이도록 개선한다.
  • 화면 위쪽에 빈 공간을 표시하는 UIView를 4개 추가하고, 우측 상단에 UIImageView를 추가한다.
    • 상단 화면 요소의 y 좌표는 20pt를 기준으로 한다.
    • 7장의 카드 이미지 y 좌표는 100pt를 기준으로 한다.
  • 앱에서 Shake 이벤트를 발생하면 랜덤 카드를 다시 섞고 다시 그리도록 구현한다.

CardGameDelegate클래스를 싱글톤으로 구현

  • Deck, Foundation, StacksView, OneStack 클래스에서 모두 CardGameDelegate(CardGameManageable)가 필요함.
  • 현재 상위모듈에서 하위모듈을 초기화할때 매번 객체를 넘겨주는 방식인데, 한 게임 당 하나의 CardGameDelegate가 필요하고 모든 뷰는 그 객체를 공유하면서 프로그램을 진행해야함
  • 매번 서브뷰를 초기화할때마다 객체를 넘기는 것이 아니라 싱글톤으로 만드는 것이 더 효율적임

1~7장의 카드가 있는 CardStack 표시

  • CardDeck 객체에서 랜덤으로 카드를 섞고, 출력 화면처럼 카드스택 형태로 보이도록 개선한다.
  • 카드스택을 관리하는 모델 객체를 설계한다.
  • 각 스택의 맨위의 카드만 앞카드로 뒤집는다.
  • 앱에서 Shake 이벤트를 발생하면 랜덤 카드를 다시 섞고 처음 상태로 다시 그리도록 구현한다.

deckView에서 카드를 드래그했을때 toInfo()리턴값이 nil인 문제

  • 문제상황: deckView에서 카드를 드래그했을때 앱이 종료됨
  • 원인:
    • 드래그가 끝난 지점인 currentFrame을 rootView기준으로 변환하면 nil이 리턴됨
    • nil로 값이 할당된 toInfo: MoveInfo로 rule을 체크하려고 하면 에러발생
  • 해결: rootView기준으로 origin을 변환할때 deckView에서 움직인 방향을 고려해서 변환하기

더블탭과 카드게임 룰 적용

  • 만약 A카드인 경우 왼쪽 상단의 비어있는 칸으로 UIImageView를 animate 시킨다.
    • 기존에 다른 A카드가 있으면 그 옆으로 이동한다.
  • K카드인 경우 스택 중에서 좌측부터 빈 칸이 있으면 빈 칸으로 이동시킨다.
  • 나머지 2이상 카드인 경우 왼쪽 상단에 같은 모양의 A가 있는 경우는 그 위로 이동시킨다.
  • 상단으로 이동할 수 없는 경우, 스택 중에서 좌측부터 앞면으로 된 카드 중 가장 위에 있는 카드와 다음 조건을 확인하고 조건에 맞으면 그 위로 이동시킨다.
    • 숫자가 하나 큰 카드가 있는지 확인한다. ex) 터치한 카드가 2인 경우 3, 10인 경우 J
    • 모양의 색이 다른지 확인한다. ex) 터치한 카드가 ♠️♣️ 이면 ♥️♦️
  • 스택에서 마지막 카드가 다른 곳으로 이동한 경우 다시 마지막 카드를 앞면으로 뒤집는다

MoveInfo에서 view가 Stack인경우 origin이 다 (0,0)인 문제

각 OneStack뷰들이 따로 나눠져있기때문에 7개의 OneStack뷰 모두 frame.origin은 (0,0)이며, PositionX enum으로 계산할 수 없다.
따라서 아래의 stackColumn() 메소드에서 column이 nil로 리턴되는 문제까지 연쇄적으로 일어난다.

// FrameCalculator.swift
    func stackColumn(originX: CGFloat) -> Int? {
        for x in PositionX.allValues {
            guard x.value == originX else { continue }
            return x.hashValue
        }
        return nil
    }

MoveInfo의 view가 Stack인경우, 드래그액션이 시작된 OneStack이 어떤 스택인지(origin.x값으로 알 수 있도록) 계산하는 로직을 추가한다.

currentFrames값을 RootView기준으로 converting하기

  • 드래그 액션이 다 끝난 지점을 뜻하는 currentFrame
  • currentFrame은 movableViews의 원래 superView기준으로 나온다 (OneStack or FoundationView)
  • RootView의 origin기준으로 변환하여 isInside(point:)를 파악한다.

availableFrame()의 리턴값이 CGPoint(x:0.0, y:0.0)인 문제

  • drag가 끝난지점부터 toPoint까지 animate시키는 부분에서 카드가 (0,0)위치로 animate됐다가 돌아오는 현상.
  • 원인1 : FrameCalculator.availableFrame()에서 toPoint가 (0,0)으로 리턴
  • 원인2 : ViewController의 toInfo()에서 MoveInfo의 index가 nil로 리턴

* toPoint: cardStack(or foundation)까지 카드가 옮겨질 딱 맞는 위치

Card 객체에따라 카드 이미지 만들기

<관련 요구사항>

  • Card 객체에 파일명을 매치해서 해당 카드 이미지를 return 하는 메소드를 추가한다.
  • Card 객체가 앞면, 뒷면을 처리할 수 있도록 개선한다.

CardImage의 Frame에서 origin을 계산하는 객체 수정- 카드 크기만 고정

StackView들을 7개로 나누면서 Deck, Foundation, StacksView에서 카드 Frame의 origin을 계산하는 방법이 달라짐. (특히 x좌표)
특히 x좌표는 PositionX라는 enum으로 저장되어있고 모든 카드이미지의 크기또한 고정값이라 매번 CardMaker클래스에서 계산할 필요성이 없어보임.

  • 카드크기또한 PositionX, PositionY처럼 고정된 값으로 놔두고 달라진 origin값만 각 뷰에서 부여하는 방식으로 CardFrame을 초기화하는 방법이 좋을 것 같다!

CGRect의 contains() 기능 확장

해당 CGRect내부에 CGPoint가 있는지 확인하는 메소드 구현하기

  • 해당 CGPoint가 어떤 뷰(CardDeck, Stacks, Foundation view중 1)인지 리턴

DeckManageable과 StackManageable을 합치고 CardGameDelegate클래스로 구현

<이유>

  • 카드게임이 진행되기위해서는 카드 52장이 있는 하나의 카드덱으로 stack과 deck을 구성해서 게임을해야한다.
  • 지금처럼 DeckManageable(CardDeckDelegate)와 StackManageable(CardGameDelegate)을 에서 따로 cardDeck을 가지고있으면 한 게임에 두 카드덱이 존재하게된다.
  • 또한 현재 DeckManageable이 가진 기능이 많지 않으므로 따로 관리할 필요성이 없어서 합쳐서 게임을 총괄적으로 진행하는 모델인 CardGameDelegate하나로만 게임을 관리하기로했다.

Step3 PR 코멘트

  • CardStack 속성 Private으로 지정하고 Stack을 ViewController에서 사용할때 관리하는 객체 분담해보기
From JK:
- private 에서 다시 public으로 바뀐건가요? 여기에 접근하는 경우가 있다면 메소드를 만들어서 해결하는 방법을 고려해보세요.
- 여기서 사용하는 stacks 자체를 별도 객체로 만드는 건 어떨까요?
- 객체 역할과 책임에서 상위 객체에 있는 코드를 하위 객체에게 좀 더 위임해도 좋을 것 같습니다.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.