Skip to content

Instantly share code, notes, and snippets.

@yattom
Last active June 20, 2023 23:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yattom/242fa559de0cb8be4480201d1e86a314 to your computer and use it in GitHub Desktop.
Save yattom/242fa559de0cb8be4480201d1e86a314 to your computer and use it in GitHub Desktop.
プログラミングお題: 大富豪の手判定

プログラミングお題: 大富豪の手判定

トランプゲームである大富豪のプログラムを書きましょう。

1. トランプのカード

トランプのカードは、4種類のスート(スペード、ハート、ダイヤ、クラブ)と13のランク(A, 2, 3, 4, 5, 6, 7, 8, 9, J, Q, K) の組み合わせです。またジョーカーもカードです。ひと組のトランプは、全53枚(4スート13ランク+ジョーカー1枚)のカードです。

1-1. 1枚のカードを表現する

1枚のカードを表現してください。クラス、オブジェクトなど、使用する言語でのユーザー定義型を作ってください。その表現をもとに、以下のような機能を実装してください。

  • 文字列表現ができる(人が見て分かるよう、コンソールなどに表示できる)
  • 2枚のトランプを比べて、同じスートか調べられる
  • 2枚のトランプを比べて、同じランクか調べられる

1-2. 強弱の判定

大富豪では、前のプレイヤーよりも強い手を出さないといけません。カードの強弱判定を実装してください。まずは、カード1枚だけの手を考えます。

大富豪では3が一番弱く、4, 5, ... 10, J, Q, K, A と強くなり、2が一番強くなります。ただしジョーカーは他のどのカードよりも強いです。

  • 2枚のカードを比べて、どちらが強いか判定する

1-3. 手の組み合わせ

大富豪では同時に2枚以上の手を作って出すことができます。このような手も比較できるよう、手の強弱の判定を実装してください。ここでは以下のルールとします。

  • 異なるスートで同じランクのカード、2枚以上
  • 同じスートで連続するランクのカード、3枚以上
  • ジョーカーを任意のカードとして使える(このときはジョーカーの強さはそのカードと同じになる)

1-4. シャッフルして配る

2. トランプ2

先の問題ではカードをクラスやオブジェクトで表現しました。こんどは、カードをできるだけプリミティブな方法で表現してください。整数、浮動小数点数、配列、文字列、シンボルなど、使用する言語に合わせて工夫してください。

そのうえで、複数枚の手を比較できる機能を実現してください。

3. ゲームの進行

大富豪は以下のようにゲームを進めます。(最初に手札を配ったり、手札がなくなって上がったりする部分は省略しています。)

  1. 親が最初の手を場に出す
  2. 次のプレイヤーが、場にある手より強い手を出すか、パスする
  3. 各プレイヤーが順番に手を出すかパスしていく
  4. 他のプレイヤー全員がパスし、再び場にあるカードを出したプレイヤーまで順番が回ってきたらそのプレイヤーは親になる
  5. 新しい親が、1から始める

この流れをプログラムで実装してください。

各プレイヤーがどの手を出すか(あるいはパスするか)は、外部から指定できるようにしてください。外部からの指定は、コンソールから入力する、指定するメソッド(API)を提供する、別のプログラムを呼び出す、Web APIで操作するなど、いろいろな考え方ができます。好きな方法を選んでください。

判断が難しければ、APIを提供するようにするのをおすすめします。たとえば、以下のようなテストを書き、テストから呼び出しているメソッドをAPIとして実装していくという進め方ができます。

dfg_test.py:

def test_ゲームを進める():
  game = DaiFuGoGame()
  player1 = Player()
  player2 = Player()
  player3 = Player()
  game.add_player(plyer1)
  game.add_player(plyer2)
  game.add_player(plyer3)

  # 親が手を出す
  assert game.oya == player1
  assert player1.tefuda == ['S3', 'D5', 'HK', 'CA']
  player1.play(['D5'])
  assert game.ba == ['D5']
  
  # 次のプレイヤーが手を出す
  assert game.current_player == player2
  player2.play(['H8'])
  assert game.ba == ['H8']
  
  # 続く

ただしこのサンプルはあくまで一例です。ゲームやプレイヤーやカードを表す方法はたくさん考えられるので、各ペアで相談しながら、できるだけ「小さなステップ」で進めながら、プログラムの構造を成長させてください。

4. 特殊な手、ローカルルール

大富豪にはたくさんの特殊な扱いの手や、ローカルルールがあります。そうした機能を実現してみましょう。

4-1. 革命

同じランクのカード4枚の手を出すと、革命が起こり、カードの強弱が逆転します。

  • 手が革命を起こす手かどうか判定する
  • 革命が起きたときの強弱の判定を実装する

4-2. 禁止上がり

上がりの手として禁止されているものがいくつかあります。手が禁止上がりの手かどうか判定してください。

  • 一番強いランク(2)上がりは禁止
  • ジョーカー上がりは禁止
  • 一番弱いランク(3)上がりは禁止
  • 複数枚の手で、上記を含む手は禁止

4-3. 8切り

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment