고급 Golang 게임 서버 개발: 마작 타일의 추상화 및 구현

마작 타일(Mahjong Tiles) 추상화 및 인코딩 실습

마작 게임 비즈니스를 한 문장으로 설명하면 다음과 같습니다:

  • 세 명 모드 <두 방 세 명>은 바라기동그라미 두 가지 패턴을 사용하며 총 72 장의 카드가 사용됩니다.
  • 네 명 모드 <끝까지 싸우기>는 바라기, 동그라미, 만자 세 가지 패턴을 사용하며 총 108 장의 카드로 구성됩니다.

단계별 Mahjong Server 개발

  • 단일 아키텍처를 통해 Mahjong Server 비즈니스 이해 → 나노 분산 게임 서버(Nano Distributed Game Server) + 마이크로서비스로 리팩토링.
  • 데모: go-mahjong-server

타일(Tiles) 추상화

타일 구조체 정의

type Tile struct {
    CardID   int
    Pattern  int
    Number   int
    Position int
}
  • CardID: 108 장의 카드를 0~107 범위의 고유 ID로 표시합니다.
  • Pattern: 세 가지 패턴(바라기, 동그라미, 만자)을 0~2로 구분합니다(0: 바라기, 1: 동그라미, 2: 만자).
  • Number: 각 패턴당 9 종류의 숫자를 1~9로 나타냅니다(예: 1바라기, 9바라기, 1동그라미, 9동그라미 등).
  • Position: 위치를 나타내며 바라기는 1~9, 동그라미는 11~19, 만자는 21~29 범위로 지정됩니다.

표를 통한 이해

세 가지 패턴과 각 패턴의 위치(Position)를 아래 표로 확인할 수 있습니다:

바라기 (1 ~ 9) 동그라미 (11 ~ 19) 만자 (21 ~ 29)
1 1바라기 11 1동그라미 21 1만자
2 2바라기 12 2동그라미 22 2만자
3 3바라기 13 3동그라미 23 3만자
4 4바라기 14 4동그라미 24 4만자
5 5바라기 15 5동그라미 25 5만자
6 6바라기 16 6동그라미 26 6만자
7 7바라기 17 7동그라미 27 7만자
8 8바라기 18 8동그라미 28 8만자
9 9바라기 19 9동그라미 29 9만자

108 장의 모든 카드 ID 번호는 다음과 같이 나뉩니다:

바라기 (0 ~ 35) 동그라미 (36 ~ 71) 만자 (72 ~ 107)
0 1바라기 36 1동그라미 72 1만자
1 1바라기 37 1동그라미 73 1만자
... ... ...
35 9바라기 71 9동그라미 107 9만자

ID로부터 타일 가져오기

아래 함수는 주어진 ID를 통해 해당 타일 정보를 반환합니다.

func GetTileFromID(cardID int) *Tile {
    if cardID < 0 || cardID >= 108 {
        panic("잘못된 타일 ID")
    }
    
    pattern := (cardID / 4) / 9
    number := ((cardID / 4) % 9) + 1
    position := pattern*10 + number
    
    return &Tile{
        CardID:   cardID,
        Pattern:  pattern,
        Number:   number,
        Position: position,
    }
}

유닛 테스트 작성

GetTileFromID 함수의 정확성을 검증하기 위한 유닛 테스트 코드입니다.

func TestGetTileFromID(t *testing.T) {
    tests := []struct {
        name string
        id   int
        want *Tile
    }{
        {"1바라기", 0, &Tile{CardID: 0, Pattern: 0, Number: 1, Position: 1}},
        {"1바라기", 1, &Tile{CardID: 1, Pattern: 0, Number: 1, Position: 1}},
        {"9바라기", 35, &Tile{CardID: 35, Pattern: 0, Number: 9, Position: 9}},
        {"1동그라미", 36, &Tile{CardID: 36, Pattern: 1, Number: 1, Position: 11}},
        {"9동그라미", 71, &Tile{CardID: 71, Pattern: 1, Number: 9, Position: 19}},
        {"1만자", 72, &Tile{CardID: 72, Pattern: 2, Number: 1, Position: 21}},
        {"9만자", 107, &Tile{CardID: 107, Pattern: 2, Number: 9, Position: 29}},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got := GetTileFromID(tt.id)
            if !reflect.DeepEqual(got, tt.want) {
                t.Errorf("GetTileFromID(%d) = %v, want %v", tt.id, got, tt.want)
            }
        })
    }
}

테스트 실행 방법:

cd internal/game/mahjong 
go test -v tile_test.go tile.go mahjong.go

태그: Golang GameServer Mahjong

6월 2일 18:26에 게시됨