Skip to content

dahun-lee-daji/swift-pokergameapp

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

124 Commits
 
 
 
 
 
 

Repository files navigation

목표와 의의

  • 개인적 challenge: MVC 패턴과 기본 framework만을 사용하여 진행

    • 이를 통해, 기본기를 다진다!
  • 어플리케이션 설계 목표: 실제 포커와 유사한 어플리 케이션 제작처럼 만들고자 한다.

    • 왜 시작했을까?: CodeSquad의 교육 중 초창기에 진행했던 카드게임 과제는 카드의 앞면, 뒷면을 표현하는 정도였다. 이를 진짜 게임처럼 만들어 보고자 하는 생각이 있었기 떄문.

개발 환경

  • ios 14.4
  • xCode 12.4
  • 외부 라이브러리 X

사용한 기술

  • Coordinator Pattern, Delegate Pattern, Observer Pattern, Singleton Pattern
  • MVC-C, Code-based UI, Notification, bulletin Board, Auto-Layout

사용 시나리오

  1. Start 버튼을 눌러 시작.
  2. 상황에 따라 원하는 Betting Action Button Push
  3. 게임의 결과를 확인하고, 새로운 게임 시작.

주요 기능

  • 플레이어 수 변경 기능
  • 5, 7장 포커 변경 기능
  • 판돈, 기본 배팅금액 변경 기능
  • AI Player의 랜덤 행동 기능
  • 파산자 회생 기능
  • 손패의 족보 계산 기능
  • User fold할 경우, 남은 Player끼리 승패를 가리는 기능.

Play 영상

일반 작동 화면

standard

사용자 fold 시

fold

파산한 Player가 생긴 경우

penniless

소지 금액과 판돈 변경하기

changeSeedMoneyLow

Player수 or GameMode 변경하기

changeGameSettingsLow

Project 구성

프로젝트전체 개정

UI 구성

MainGameViewController UI 계층

스크린샷 2022-05-07 오후 6 35 05

MainGameViewController UI

스크린샷 2022-04-10 오후 4 35 15

스크린샷 2022-04-10 오후 4 35 41

스크린샷 2022-04-10 오후 4 35 55

SeedMoneyViewController UI

스크린샷 2022-05-07 오후 7 48 17

start UI

스크린샷 2022-05-07 오후 7 48 08

Pattern 구성

Coordinator Pattern 구조

KakaoTalk_Photo_2022-05-09-18-45-20

Observer Pattern 구조

KakaoTalk_Photo_2022-05-09-18-45-15

상세 기능

Game Play

  • User는 Start button을 눌러 게임을 시작 할 수 있다.
  • User는 3가지 Betting button을 눌러 게임을 진행 할 수 있다.
  • betting 시 언제나 Player가 먼저 betting한다. 하지만 결과는 한 번에 취합한다.
  • n명의 Player가 동시에 fold하여 승자를 결정 할 수 없을 경우, 판돈( Pot )은 dealer가 갖는다.
  • Call은 다음 배팅금액(CallMoney), Half는 Callmoney+ Pot * 0.5 만큼 배팅한다. Fold는 게임을 포기한다.
  • User가 Fold했을때, 남은 Player는 카드를 받으며, 족보에 맞는 랜덤한 Betting을 하여 게임을 진행한다. 하지만, 최종 결과만 화면에 보여준다.
  • User는 GameStyle에 맞는 카드 장수를 받은 뒤 배팅을 하고 승자를 결정한다.
  • 승자와 그의 족보, 받을 돈을 보여주는 창을 화면에 보여준다.
  • Computer Player는 각자의 손패의 족보에 따라서 행동 확률이 변동한다. 높은 족보를 가질수록 Half하는 경우가 증가하며, Half하지 않는 경우 중 2/3은 Call을 한다.
  • Start 후, 파산한 Player를 회생시킬지 여부를 물어보는 화면을 보여준다. 파산한 Player가 존재한다면 Start Button을 누르는 매번 확인한다.
  • Player는 All-In 할 수 있다. 이 때, All-In금액과 다음 Call할 때의 금액(CallMoney)중 큰 것을 다음 CallMoney로 한다.
  • 초기 배팅금액 보다 적은 금액을 가지고 있는 Player는 시작하자 마자 All-In하는 것을 막기 위해서 시작 후, Fold한다.

Setting

  • User는 gamePlayerSegmentControl를 눌러 게임 인원수를 변경 할 수 있다. 이 때, 전체 게임은 reset된다.
  • User는 gameStyleSegmentControl를 눌러 게임 카드수를 변경 할 수 있다. 이 때, 전체 게임은 reset된다.
  • User는 seedMoneySettingButton을 눌러 모든 Player의 초기 소유 금액과, 초기 배팅금액을 설정 할 수 있다. 이 때, 전체 게임은 reset된다.

고민했던 내용

  • MVC를 잘 구현하고 있는가?

    • Model과 View는 서로 접근하지 아니하고, Controller가 model, view에 접근하며, model과 view는 controller에 접근하지 않는다.
    • 이를 위해 ObserverPattern과 Notification을 사용하여 구현하였다.
  • ViewController가 너무 커져서 줄이기 위한 방법이 필요했다. 이를 해결하기위해서,

    1. 반복적으로 쓰이는 UI를 생성하는 객체(UIMaker)를 만들어 책임을 분리하였다.
    2. 화면 전환의 책임을 분리하고자 Coordinator Pattern을 사용하였다.
  • Coordinator의 책임과 언제, 어떤 객체가 해제해야 할까?

    1. Coordinator는 화면전환의 책임 전체를 가져야 한다고 생각했다. Alert또한 하나의 modal이 present되었다고 생각하므로, 화면전환이라 여겨 Coordinator가 책임을 갖도록 하였다.
    2. Coordinator의 해제 시기는, 해당하는 Coordinator의 VC의 로직이 끝날 때라고 생각하였다. 그러므로, VC는 닫혔으나, 로직이 진행중이라면 해제하지 아니하고, 로직이 끝난 뒤에 해제하도록 하였다.
    3. Coordinator의 해제에 대한 책임은 부모 Coordinator에 있다고 생각하였다. 이를 구현하기 위해, protocol CoordinatorDismissible을 구현하였다.
  • BulletinBoard에서 BulletinBoard의 여백을 누를 때, dismiss되는 이유

    • BulletinBoardStylePresentable을 사용하여 VC를 만들 때, VC.view.backgroundColor = .clear하였고, view를 누를때, VC가 dismiss되게 하였다. 이 때, view가 아닌, bulletinBoard를 터치했을 때, bulletinBoard에 event가 없어 view의 responder가 작동하였다.
    • Responder Chain에서 VC.view를 제외하는 경우를 만들고 싶었지만, 능력의 한계에 봉착함을 느꼈다. 기술부채가 발생하지만, 문제를 해결하기 위해, 좋은 방법이 생각나지 않아, 아무런 수행을 하지 않는 touch event를 bulletinBoard에 추가하였다.
  • 가독성

    • 비슷한 역할을 하는 method의 명명을 통일하였다.
    • 초기 UI를 생성하는 method는 createMoneyLabel, createNameLabel 등 구체화되어 있었으나, 이를 createLabel로 method의 이름을 통일하고 method overloading하여 가독성을 향상 시켰다.
    • Notification.Name을 출발하는 곳과 도착하는 곳을 기재하여 직관적으로 알 수 있도록 하였다.
    • method의 이름과 매개변수에서 어떤 기능과 역할을 하는지 유추 할 수 있도록 노력하였다.
  • 족보 평가 method가 누구의 책임이어야 하는지

    • 족보 평가 method의 책임의 소유를 Deck 혹은 Player사이에서 고민했다. 어느 class에서 책임을 갖더라도 기능상의 불편과 어색함을 초래하지 않았다. 하지만, 실제 게임을 진행하는 사람이 손패의 족보를 계산하므로, Player에서 족보 평가 method의 책임을 갖는 것으로 결정하였다.
  • error처리

    • 초기에 Class TroubleShooter를 작성하여 error를 처리하였다. 해당 class의 주요 method 중, app을 강제 종료 시키는 것이 있었다. 이는 HIG에 적합하지 않으므로, 제거하였다.
    • Class TroubleShooter의 역할이 불필요해져 제거하고, Enum GameError로 error를 관리하였다.
    • 기존 코드는 do try catch문에서 에러 발생시 catch내부에서 return nil하여 에러 발생을 전달하고 있었다. 이를 아래와 같이 작성하여, error를 VC에 전달하고, VC는 error에 관한 alert를 Coordinator에 전달하여 present하도록 구현하였다.
     catch {
      throw error
      }
  • 상호 의존성을 줄이는 방법?

    • 강한 결합을 줄이기 위해 Protocol 및 delegate pattern을 사용했다.
  • UI를 Refresh하는 방법?

    • 기존에 player의 hand가 변경되어 card를 추가로 보여줘야 할 때, 전체 UI를 제거하고, 다시 만드는 방법을 사용했다. 이 방법은 리소스의 소모가 너무 크기 때문에, 필요한 부분만 수정하도록 코드를 개선하였다.
    • 이 때, 다수의 UILabel을 구분 할 방법이 필요했다. UILabel을 상속하여 각 CustomUI를 만드는 방법은 택하지 않았다. 상속하여 CustomUI를 만들때에는, 추가적인 property 혹은 새로운 특정 기능이 추가되지 않기 때문이다. 오직 구분만을 위해서는 tag를 사용함이 옳다 생각하였다.
  • 사용자를 더 재미있게 할 방법은?

    • StartBetting때, StartBetting 금액보다 소지금이 적으면 AIPlayer를 fold하여, 금액이 적은 상대방과 game을 하는 불쾌함을 줄임.
    • AI Player의 행동을 해당 Player의 족보에따라 변하게하여, 상대의 패와 행동을 고려할 필요를 만들어 재미를 느끼게 함.

회고

이 프로젝트는, CodeSquad의 초창기의 간단히 카드를 보여주기만 했던 App을 실제 poker와 유사하게 동작하도록 구현하는 App이다.
도중에 그만두지 않고, 끝까지 계획했던 기능을 전부 구현한 점에 있어서 의미가 있다.
이 프로젝트를 진행하며, Coordinator pattern을 더 정확히 공부했으며, MVC 패턴에 대해 확실히 파악했다고 생각한다. 또한, SOLID 법칙을 따르기 위해 노력했다.
또한, MVC가 아닌, 다른 Architecture를 사용하는 이유를 확실히 느꼈다. ViewController에 너무 많은 책임이 생기며, Code가 너무 많아 원하는 내용을 찾거나 읽는데 어려움이 있다는 것을 알게되었다. 초기에 주어졌던 UI Design, Model의 regacy code를 가독성 좋게 구현하는데 노력을 쏟았다. 이를 통해, regacy code의 개선이 어려움을 배웠고, 간혹 들어본 새로 만드는. 것이 편하다는 말이 어떤 것인지 이해하였다.
프로젝트 파일 내에는, testCode를 작성하려 했던 흔적을 볼 수 있다. 도중에 포기한 내용으로, 아쉬움이 많이 남는다. 하지만, 꼭 필요한 부분에 있어서는 작성되어 있으므로, 절반의 성공이라 생각한다. 추후에 프로젝트를 개선한다면, 꼭 작성하고 싶은 부분이다.
미흡한 점이 많지만, 고민하는 시간이 즐거웠던 프로젝트였다.

일기같은, 개발일지

개발일지로 가는 링크😊 스크린샷 2022-05-18 오후 3 58 10

About

STEP15 포커게임 앱 저장소

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Swift 100.0%