2012-03-29 3 views
11

많은 (바라건대 수천 명의) 플레이어가 서로 특정 카드 게임을 동시에 진행할 게임 사이트를 설계하고 있습니다. 데크는 standart 52 카드 갑판입니다. 각 카드에는 양복과 계급이 있습니다. 카드는 항상 셔플, 거래, 선택, 주문, 재생됩니다. 내 질문은 Card 열거 형, 구조체 또는 클래스 수 있습니까?카드 사용 : 열거 형 또는 구조체 또는 클래스이어야합니까?

  • 열거 형의 경우 : 각 카드는 0..51 바이트로 두십시오. 그래서 카드는 아주 작은 공간을 차지할 것입니다. 손을 8 바이트의 비트 세트로 나타낼 수 있습니다. 필요한 경우 주어진 카드의 수트와 랭킹을 매우 빠르게 계산할 수 있습니다 (예 : suit (n) = n/13). 이것은 매우 효율적입니다. 카드에 대한 메소드를 작성해야한다면, 확장 메소드를 통해 작성하십시오.

  • 구조체의 경우 : 아니요, 이것은 기계어 작성과 같습니다. 카드는 간단한 구조이며, 거의 데이터를 보유하지 않으며, 불변이며, 작습니다. 많은 동작을하지 않으므로 구조체로 만들어 수동 데이터 구조로 취급하십시오. 필요에 따라 주어진 카드에서 0..51의 색인을 매우 빨리 계산할 수 있습니다.

  • 클래스의 경우 : 아니요, 객체 지향적 인 사고 방식은 아닙니다. Card 클래스를 만듭니다. 불변으로 만드십시오. 정확히 52 개의 인스턴스를 생성하십시오. 카드 풀이 그 인스턴스를 보유하게하십시오. 그래서 스페이드의 여왕이 필요하면 카드 풀에 그 카드를 요청합니다. 계속 진행되는 수천 개의 게임이있을 때에도 오직 하나의 스페이드 여왕이있을 것입니다. 원하는 경우 카드에 0..51의 색인 필드를 저장하십시오.

나는 마지막 옵션 (클래스)을 향하여 기울어지고 있지만 확실하지 않습니다. 나는 성능에 대해별로 걱정하지 않는다. 나는 그 길을 따라 좀 더 심각한 실수를 저 지르게 될 것입니다. 내가 걱정하는 것은 나의 전체 견해가 틀릴 수도 있다는 것이다; 어쩌면 이것은 매우 쉬운 결정이며 다른 모든 사람들이 가지고있는 지식을 부족하기 때문에 망설이지 만.

당신은 어떻게 생각하십니까?

편집 : 카드의 행동에 관하여. 나는 카드가 다른 카드에 대해서만 알 것이라고 생각한다. 예를 들어 "누가 다리에서 누가 우 수"에 대한 부분적인 순서를 정의 할 수 있습니다. 갑판에 대해 아무 것도 알 필요가 없습니다. 그리고 이것은 서버 측 코드가 될 것입니다. 확실히 화면 등에 자신을 그려야 할 필요는 없습니다.

+1

사람들의 의견을 묻는 것처럼 이것은 아마도이 사이트에 대한 건설적인 질문이 아닙니다. 그건 내 본능이 옳다는 것입니다. : P –

+0

'카드'는 어떤 행동을합니까? 얼굴을 뒤집어 놓았는지 또는 그것이 테이블 위에 놓여있는지를 알 수 있습니까? 그 뒤가 어떤 색인지 등을 알기 위해 어느 데크가 왔는지 기억합니까? –

+0

'CardPool'은 좋은 아이디어라고 생각하지 않습니다. 초기 및 불필요한 최적화처럼 보입니다. –

답변

13

근본적인 문제는 물론 의 내가 논리적으로 불리는 , 또는 일을 모델링하고있는 것입니다? 그 이유는 값 유형과 참조 유형을 먼저 "값 유형"및 "참조 유형"이라고합니다.

신원이있는 물리적 인 물체를 취급하는 것과 같은 방식으로 "카드"를 참조로 취급 하시겠습니까? 예를 들어, 두 개의 표준 카드 데크로 동시에 재생되는 Canasta를 모델링한다고합시다. 두 다른 스페이드의 퀸을 추적하고이를 과 다르게 취급하고 싶습니까??

값을으로 처리 하시겠습니까? 숫자를으로 처리 하시겠습니까? 당신은 숫자가 그들의 가치에 의해서만 구별되기 때문에 "이 숫자 6은 저기 숫자 6과 다릅니다"라고 말하지 않습니다.

+1

+1 * 정확한 * 점수입니다. 질문은 '참조'또는 '가치'가 아니라 ** 게임 **이거나 게임을 만드는 행동 모델입니다. – Tigran

+0

감사합니다. 내가 생각하기에 숫자 같은 카드를 취급 할 것입니다. 하지만 이것은 까다 롭습니다. 대안은 메모와 함께 불변의 참조 유형을 만드는 것이므로 어쨌든 스페이드의 여왕이 하나만 존재하게됩니다. 솔직히이 경우 값이되고 참조가되는 것의 차이를 알 수 없습니다. (그렇지 않은 경우가 없으며, 변경 불가능한 memoized 참조 유형은 항상 값 유형과 의미 상 동일합니까?) –

+5

@AliFerhat : Correct; 불변의 memoized 참조 유형은 값 유형과 매우 유사하게 동작합니다. 기본적으로 모든 "카드"는 싱글 톤이됩니다. 카드에있는 정보의 양이 참조의 크기보다 작 으면, 나는 싱글 톤을 만들 이유가 거의 없다. 간접 접근은 무엇을 사나요? –

2

각 카드를 숫자로 표현한 다음 열거 형과 클래스 모두로 래핑 할 수 있습니다. 또한 클래스 가질 수

public enum Card 
{ 
    HeartsAce = 0, 
    Hearts2 = 1, 
    // ... and so on 
} 

int nCard = 16; 
Card myCard = (Card)nCard; 

:

public class Card 
{ 
    private readonly int _nSuitNumber = 0; 
    private readonly int _nCardNumber = 0; 

    public Card(int a_nNumber) 
    { 
     _nSuitNumber = a_nNumber/13; // 1 = Hearts, 2 = Diamonds ... 
     _nCardNumber = a_nNumber % 13; // 1 = ace, 2 = two 
    } 
} 

을 또는 더 나은 아직 그들을 결합 공 (51)을 사이에 각 번호가 카드를 나타내는 경우, 당신은 다음 열거 할 수 있습니다.

public class Card 
{ 
    private readonly Suit _suit; 
    private readonly Value _value; 

    public Card(int a_nNumber) 
    { 
     _suit = (Suit)(a_nNumber/13); // 0 = Hearts, 1 = Diamonds ... 
     _value = (Value)(a_nNumber % 13 + 1); // 1 = ace, 2 = two 
    } 

    public Suit Suit 
    { 
     get { return _suit; } 
    } 

    public Value Value 
    { 
     get { return _value; } 
    } 

    public int ToNumber() 
    { 
     return (int)_suit * 13 + ((int)_value - 1); 
    } 
} 

public enum Suit 
{ 
    Hearts = 0, 
    Diamonds = 1, 
    Clubs = 2, 
    Spades = 3 
} 

public enum Value 
{ 
    Ace = 1, 
    Two = 2, 
    Three = 3, 
    Four = 4, 
    Five = 5, 
    Six = 6, 
    Seven = 7, 
    Eight = 8, 
    Nine = 9, 
    Ten = 10, 
    Jack = 11, 
    Queen = 12, 
    King = 13, 
} 

이 클래스를 사용하면 숫자 (0-52)와 클래스의 이점을 얻을 수 있습니다. 클래스는 수를 둘러싼 래퍼에 지나지 않습니다. 필요한 모든 연산, 메서드, 속성을 클래스에 추가 할 수 있습니다. 그리고 데이터를 저장하거나 전송할 때 번호 만 사용해야합니다.

+0

감사합니다. 나는 카드가 숫자와 구조체/클래스 사이에서 변환 될 필요가 있음을 원칙으로 동의한다. –

5

는이 struct 또는 class 카드, 카드의 값이 enum해야 확인하고 카드의 소송도 enum입니다.

당신이 class을 사용할 수, 갑판을 위해, 등,

+0

mantioning의 유일한 가치는'enum'을 power off 2 값으로 정의하는 것입니다. 주어진 사용자의 데크에서 카드의 조합을 식별 할 수 있기를 바랍니다. – Tigran

+2

@Tigran 나는 이것으로 무엇을 얻고 있는지 잘 모르겠습니다. – Matthew

+1

@Matthew : 아이디어는 주어진 세트에 각각 존재하거나 존재하지 않는 52 개의 카드가 있다면, 카드 세트는 하나의 긴 정수로 표현 될 수 있다는 것이다. 좋은 개념이고, 유용 할 때가 있습니다. 하나의 어려움은 다양한 목적으로 유용 할 수있는 다양한 인코딩이 있다는 것입니다. – supercat

0

당신이 구축을 위해 노력하고 추상화 것을 고려해 볼 수 있습니다를, card 's의 목록이 포함 Shuffle 등의 작업이 있습니다. 카드가 다른 기능에 의해 전달 된 하위 수준의 객체 인 경우 enum이 더 적합 할 수 있지만 카드를 draw() 또는 그 이상으로 만들려면 더 정교한 것이 필요합니다. 카드가 귀하의 응용 프로그램에 어떻게 적합합니까?

+1

왜 수업이 필요할까요? 구조체는 "draw"메서드를 가질 수 있습니다. –

+0

클래스가 필요하지 않습니다. – simpleigh

0

이 질문은 논리적으로 대답 할 수 있다고 생각합니다. 객체 지향 관점에서 살펴 보겠습니다. 카드에는 두 가지 하위 요소 인 소송 및 가치가 있다고 생각합니다. 해당 금액은 enum이어야합니다. 손 (클래스)에는 아마도 카드 목록이 있어야하는데, 구조 또는 클래스로 카드를 갖는 것이 가장 좋을 것이라고 생각합니다. 손에 쌍이 있는지 확인하려면 손 클래스의 함수가되어야합니다.

다양한 유형의 게임으로 여러 사람이 게임을 할 때 각 덱은 갖고있는 카드의 유형과 개수를 알아야합니다. 하지만이 경우에도 카드 자체는 변경되지 않습니다.

0

내가 열거를 사용하여 클래스 또는 구조체에 가서, 거기에 내부 생성자 둘 것 : 그 동안 카드를 할당했다 (가장 중요)

publlic class PlayingCard 
{ 
    internal PlayingdCard(CardSuit suit, CardFace face) 
    { 
     this.Suit = suit; 
     this.Face = face; 
    } 

    public CardSuit Suit { get; private set; } 

    public CardFace Face { get; private set; } 
} 

이 카드를 관리하는 덱 클래스를 정의하지만,을 그것의 건축 :

public class Deck 
{ 
    private List<PlayingCard> cards = new List<PlayingCard>(); 
    public Deck() 
    { 
     for(var i = 0; i < 4; i++) 
     { 
      for (var j = 1 to 13) 
      { 
       this.cards.Add(new PlayingCard((CardSuit)i, (CardFace)j)); 
      } 
     } 
    } 

    public void Shuffle() { /* implement me */ } 
    public PlayingCard GetNextCard() { /* implement me */ } 

} 

이 방법은 갑판 크기는 고정되고, (나는 확실히 누군가가 그 LINQify하는 방법을 가지고 올 수있어하지만) 얼굴과 옷은 가능한 한 적은 코드로 작성됩니다.

2

나는 당신이 정말로 여기서 올바른 질문을하고 있다고 생각하지 않습니다. 귀하의 카드를 나타내는 방법은 귀하가 귀하의 카드로하고 싶은 것에 의해 결정되는 사항이어야합니다; 이제 카드를 어떻게 표현할 것인가에 대한 질문에 대답함으로써, 나중에 대면 할 다른 흥미롭고 도전적인 문제를 해결할 수있는 방법으로 자동으로 제한됩니다.

당신이 정말로 생각해야 할 사항은 프로그램의 동작을 구현하는 방법입니다. 예 :

  • "카드"가 처리 될 때 어떤 현상이 발생합니까? 당신은 그 카드를 가지고있는 실재물간에 물리적으로 움직이는 카드를 표출하고 싶습니까? (예 : 갑판, 플레이어의 손, 버리는 더미, 테이블 등), 또는 해당 엔티티가 단순히 카드의 중앙 저장소를 참조하기를 원하십니까? 또는 완전히 별도의 계산 메커니즘을 사용할 수 있습니까?

  • 카드는 어떻게 주문 하시겠습니까? 당신이 구현하기로 선택한 게임은 서로 다른 규칙을 가질 수 있습니다 (예 : 에이스 로우 또는 하이 - 로열 슈트는 모두 동일한 가치가 있습니까? 트럼프 카드가 있습니까?) 이들은 게임 단위로 결정되는 결정입니다 심지어 게임 자체도 바뀌기 때문에 주문에 기반한 카드의 단일 정의만으로는 좋은 추상이되지 않을 수도 있습니다.

    • 어떤 종류의 행동 및 게임 규칙을 카드에 따라 달라 지려고합니까? 카드 자체에 의존성이 있습니까?

    • 카드가 사용자 상호 작용에 관여 할 것인가 아니면 단순히 카드 게임을 정의하는 프로그램 부분에서 사용되는 논리적 개체입니까?

    • 다른 종류의 카드를 사용할 가능성이 있습니까? 원래 질문에서 클래스를 언급했지만 카드가 어떤 종류의 상태, 행동 또는 다른 클래스와 상호 작용을 정의 할 경우 먼저 세부 사항을 염려하기 전에 먼저 카드 인터페이스를 정의하는 것이 좋습니다. 귀하의 질문에 직접 답변으로

- 나는 개인적으로 당신이 대답은 추측과 개인 취향에 따라 의견이 아닌 다른 할 수있는 충분한 정보를 제공했다고 생각하지 않는다; 일반적으로 구현을 시작하기 전에 모든 대답을 찾는 것은 어렵 기 때문에 괜찮습니다. 당신은 세 가지를 모두 시도하고 당신의 필요에 가장 적합한 것을 보길 원할 것입니다. 이러한 종류의 결정을 내리기 만하면 디자인을 제한하지 마십시오. 참조 형식 또는 값 형식 사이를 결정할 때 자신을 요구해야한다

+0

감사합니다. 귀하의 모든 포인트가 정확합니다. 나는 가능한 한 게임 불가지론 자 (game agnostic)로서의 프레임 워크에 대해 꿈꾸는 중이다. 아마도 나는 생각만큼 많은 결실을 맺지 못할 것이다. –

+0

"카드는 어떻게 다루는가"라는 질문은 흥미 롭습니다. 참조 유형으로 카드를 사용하는 한 가지 가능한 이점은 각 카드가 상주하는 곳에 'ICardCollection' 유형을 가진'Location' 속성을 가질 수 있다는 것입니다 (카드의 생성자는'ICardCollection'에 대한 참조를 필요로합니다) 처음에 속할 것입니다). ICardCollection의 구현은 항상 모든 카드가 항상 정확히 하나의 컬렉션에 있어야한다는 불변성을 강요하기 위해 작성 될 수 있습니다. – supercat

관련 문제