[Go] ゴブレットゴブラーズの通信ゲームを作ってみた


はじめに

ガキ使でゴブレットゴブラーズというボードゲームを紹介していてとても面白そうだったので、Goで作ってみることにしました。

ゴブレットゴブラーズについては以下の記事がわかりやすかったです!
https://kyoheiomi.com/board-game/recommendation/gobblet-gobblers

完成品

画像がないです。

機能

  • ルーム作成
  • 通信対戦
  • 閲覧機能

構成

server-client型で作りました。
serverに対して、clientがポーリングを行いゲームを更新していきます。
インターフェースはjsonを用いています。
以下はパッケージ構成です。

├── cli // ゲームを実行するcliツール群です。
│   ├── cli.go
│   └── util
│       ├── app.go
│       ├── client.go
│       ├── control.go
│       ├── display.go
│       ├── display_util.go
│       ├── model.go
│       ├── screen.go
│       └── util.go
├── go.mod
├── go.sum
├── logic //ゲームのロジックをまとめたところです。
│   ├── board.go
│   ├── game.go
│   ├── piece.go
│   ├── player.go
│   ├── square.go
│   └── type.go
├── server // logicを使って、サーバを立てています
│   ├── handler.go
│   ├── model.go
│   └── server.go
└── web //clientがWebの場合も作る:未実装

logicとserverを分けた理由

  • 今後、インターフェースを変更する場合があると、インターフェースとゲームロジックをすぐに切り分けできるようにするためです。
  • logicで用いているモデルをcliでも利用できるためです。

実装説明

少し実装を説明します。

const P1 P = 1
const P2 P = -1

type Piece struct {
    id   uint
    size Size
    user P
}
type Square struct {
    top    int
    pieces [3]*Piece
}  
type Board [BOARD_MAX][BOARD_MAX]*Square

Pieceには、大きさとユーザ情報を持たせています。
Squareはマスのことで、マスにはコマを最大3つまで置くことができるため、マスの状態を順番ありで保持しておく必要があります。
Boardは、このマスが指定した個数あります。
スライスでなく、配列を用いることで、想定外の処理はpanicになるようにしています。
これらにメソッドを生やしゲームロジックを作成します。
細かいコードは、以下をご覧ください。

ゲームの使い方

  1. serverを立ち上げる
    $ go run server/*.go
  2. ユーザ1が部屋を作成する

    $ go run cli/cli.go -me tida -op yuna
    meオプションが自分の名前,opオプションが相手の名前を入力します。
    すると、ルームIDが払い出されます。(ex a48dec12-2a25-4b61-ad60-95134fd93b24)

  3. ユーザ2が部屋に参加する

    $ go run cli/cli.go -me yuna -room a48dec12-2a25-4b61-ad60-95134fd93b24
    ユーザ1が作成した部屋のルームIDと自分のユーザネームを入力します。
    すると、ゲームが始まります。
    ちなみに、meオプションで設定した名前と部屋が作成された時に登録された名前が一致しない場合、閲覧者としてゲームをみることができます。

  4. ゲーム
    ターン毎にターミナルにコマの配置をしていきます。
    ``` a,A,2(a,Aマスに大きさ2のコマを置く)

    未実装

    WEB版

    今回はtermboxを使いたく、cliを使いましたが、見た目が拙いです。
    ブラウザでもできるようにしたいです。WebAssemblyを使うと、logicのモデルを再利用できるので、便利かもしれないです。
    【Go】WebAssemblyでtrend表示してみた

    エラーハンドリング

    cliのエラーハンドリングが甘いです。

    メモリ管理

    ゲームが終了した後、ゲーム情報を削除していないので、常に残り続けます。

    その他もろもろ

    サービスとして提供するには、例外も含め考慮する点がまだまだアリそうです。

最後に

ゲーム作成は、例外が多く存在するため、考慮すべき点が多くて大変でした。
既存実装の追加改修してくれる人は、ぜひプルリクお願いいたしますmm