設計 - Recursion-Group-C/card-game GitHub Wiki
Card Game App の設計を行います。このページは現在作成中です。
figma参照
prefix に Sub がついているノードはサブアクティビティ。
flowchart TB
style mp fill:#0f0,stroke:#333,stroke-width:4px, color:#000
s((Start)) --> lr{Is login required ?}
lr -->|Yes| login[SubLogin]
lr -->|No| mp(MainPage)
mp --> sl[Select CPU level]
sl --> sg{Select game}
login --> mp
sg --> w[SubWAR]
w --> res[Results]
sg --> r[SubRummy]
r --> res
sg --> bj[SubBlackjack]
bj --> res
sg --> sp[SubSpeed]
sp --> res
sg --> p[SubPoker]
p --> res
sg --> th[SubTexas Hold'em ]
th --> res
res --> cg{Continue game?}
cg -->|Yes| sg
cg -->|No| E((End))
flowchart TB
style lp fill:#0f0,stroke:#333,stroke-width:4px, color:#000
style sp fill:#0f0,stroke:#333,stroke-width:4px, color:#000
style mp fill:#0f0,stroke:#333,stroke-width:4px, color:#000
style prs fill:#0f0,stroke:#333,stroke-width:4px, color:#000
s((Start)) --> lp[LoginPage]
lp --> ha{Has Account?}
ha --> |Yes| rp{Remember password?}
ha --> |No| sp[SignInPage]
sp --> r[Account registration]
r --> lp
rp --> |Yes| l[Access account]
rp --> |No| prs[PasswordResetPage]
prs --> rpc[Reset password]
rpc --> lp
l --> mp[MainPage]
ルールはカジノウォーを採用。
graph TB
St((Start)) --> A
A[Place bet] --> B[Deal 1 card each]
B --> C{Compare cards}
C -->|Player wins| D[Double payout]
C -->|Player loses| E[Lose bet]
C -->|Tie| F[Surrender or War]
F -->|Surrender| G[Lose half, half returned]
F -->|War| H[Bet additional amount]
H --> I[Deal new cards]
I --> J{Compare cards}
J -->|Player wins| K[Return bet, double payout for additional]
J -->|Player loses| L[Lose all bets]
J -->|Tie| M[Double payout for both bets]
D --> N{Continue?}
E --> N
G --> N
K --> N
L --> N
M --> N
N -->|Yes| A
N -->|No| O((End))
ルールはトランプスタジアム参照。
- CREDIT (ゲーム内通貨)はログイン時はゲーム選択時に任意の額持ち込み、ログインしていない時は一定額自動配布される?
- CREDIT は途中追加できるようにするか?
- 参加プレイヤーの人数
flowchart TB
s((Start)) --> A[Initialize player CREDIT]
A --> C[Bet minimum bid or more]
C --> D[Deal cards]
D --> node1{Player's turn}
node1 -->|Hit| F[Deal one more card]
node1 -->|Stand| node2{Dealer's turn}
F --> G{Total exceeds 21?}
G -->|Yes| L
G -->|No| node1
node2 -->|Hit| H[Deal one more card]
node2 -->|Stand| node3{Determine winner}
H --> I{Total exceeds 21?}
I -->|Yes| J[Player wins]
I -->|No| node2
node3 -->|Player's total > Dealer's total| J
node3 -->|Player's total < Dealer's total| L[Player loses]
node3 -->|Player's total = Dealer's total| K[Draw]
J --> node4[Calculate player CREDIT]
L --> node4
K --> C
node5 -->|Yes| C
node5 -->|No| E((End))
node4 --> node6{Meets the minimum bid?}
node6 --> |Yes| node5{Continue the game?}
node6 --> |No| E
ルールはトランプスタジアム参照。
- 加点方式 or 減点方式?
- 勝利条件で設定するマッチ数は固定にするか、設定で変更できるようにする?
- CREDIT の増減の計算方法は?(Speed,War も同様)
flowchart TB
start((Start)) --> A[プレイヤー人数設定]
A --> C[ラウンド開始]
C --> D[初期手札を配る]
D --> node1{プレイヤーのターン}
node1 -->|引く| F[山札または捨て札から1枚引く]
node1 -->|メルド| G[可能ならメルドする]
node1 -->|捨てる| H[カードを1枚捨てる]
F --> G
G --> H
H --> node2{次のプレイヤーのターン}
node2 -->|引く| I[山札または捨て札から1枚引く]
node2 -->|メルド| J[可能ならメルドする]
node2 -->|捨てる| K[カードを1枚捨てる]
I --> J
J --> K
K --> node3{手札がなくなったか?}
node3 -->|Yes| node4{ラウンド終了}
node3 -->|No| node5{山札が尽きたか?}
node5 -->|Yes| node6{山札を2回目に切りなおすか?}
node6 -->|Yes| node7[引き分け]
node6 -->|No| node8[捨て札を切りなおして山札にする]
node8 --> node1
node5 -->|No| node1
node4 --> L[各プレイヤーの得点計算]
L --> M{誰かが100点以上になったか?}
M -->|Yes| N{設定された勝利条件を満たしたか?}
M -->|No| C
N -->|Yes| O[CREDIT計算]
N -->|No| C
node7 --> L
O --> e((End))
ルールはトランプスタジアム参照。
flowchart TB
s((Start)) --> A[ラウンド数を設定]
A --> B[カードを赤と黒のマークに分ける]
B --> C[場札を4枚並べる]
C --> D[Game start]
D --> E[ゲーム進行]
E --> K[ラウンド終了]
K --> L{勝利条件を\n満たしたか?}
L --> |Yes| N[CREDIT計算]
L --> |No| B
N --> End((End))
ゲームの進行は、下記のシーケンス図で示す。
sequenceDiagram
participant Player
participant CPU
participant 手札
participant 台札
loop Until Game Ends
alt 場札がなくなる
Player->>手札: カードを引く
手札->>Player: カードを渡す
end
alt 場札に隣り合ったカードがある
Player->>台札: 台札にカードを置く
alt Playerが先にカードを配置
台札->>Player: 配置確認
Player->>Player: 勝利条件を確認
end
end
alt 場札がなくなる
CPU->>手札: カードを引く
手札->>CPU: カードを渡す
end
alt 場札に隣り合ったカードがある
CPU->>台札: 台札にカードを置く
alt CPUが先にカードを配置
台札->>CPU: 配置確認
CPU->>CPU: 勝利条件を確認
end
end
alt 2人とも出せるカードがない
手札->>台札: 台札にカードを置く
end
end
ルールはトランプスタジアム参照。
flowchart TB
start((Start)) --> A[CREDIT初期化]
A --> SetPlayers[プレイヤー人数設定]
SetPlayers --> Ante[各プレイヤーがアンティを支払う]
Ante --> DealInitialCards[手札を配る]
DealInitialCards --> FirstBettingRound[1巡目のベッティング]
FirstBettingRound --> BetOrCallOrFold[アクションを選択]
BetOrCallOrFold --> turnend{全員のアクション\nが終了したか?}
turnend --> |No| FirstBettingRound
turnend --> |Yes|judgeNocontest{残りのプレイヤーが\n2人以上存在するか}
judgeNocontest --> |No| NoContest1[ノーコンテスト]
judgeNocontest --> |Yes| CardExchange[カード交換]
NoContest1 --> DetermineWinner
CardExchange --> SecondBettingRound[2巡目のベッティング]
SecondBettingRound --> BetOrCallOrFold2[アクションを選択]
BetOrCallOrFold2 --> turnend2{全員のアクション\nが終了したか?}
turnend2 --> |No| SecondBettingRound
turnend2 --> |Yes| Showdown[役の強さを競う]
Showdown --> DetermineWinner[勝者を決定]
DetermineWinner --> PotAndSidePot3[チップを獲得]
PotAndSidePot3 --> judge{CREDITが最低入札要件\nを満たすか?}
judge --> |Yes| Continue{ゲームを続けるか?}
Continue --> |Yes| Ante
Continue --> |No| en((End))
judge -->|No| en
ルールはトランプスタジアム参照。
とりあえずリングゲームのアクティビティ図を下記に示す。
- ルールはリングゲーム or トーナメントゲームどちらにするか
flowchart TB
start((Start)) --> A[CREDIT初期化]
A --> SetPlayers[プレイヤー人数設定]
SetPlayers --> PostBlinds[ブラインド投稿]
PostBlinds --> DealInitialCards[手札を配る]
DealInitialCards --> PreFlopBetting[プリフロップベッティング]
PreFlopBetting --> BetOrCallOrFold[アクションを選択]
BetOrCallOrFold --> turnend{全員のアクション\nが終了したか?}
turnend --> |No| PreFlopBetting
turnend --> |Yes| judgeNocontest1{残りのプレイヤーが\n2人以上存在するか}
judgeNocontest1 --> |No| NoContest1[ノーコンテスト]
judgeNocontest1 --> |Yes| Flop[フロップ配布]
NoContest1 --> DetermineWinner
Flop --> FlopBetting[フロップベッティング]
FlopBetting --> BetOrCallOrFold2[アクションを選択]
BetOrCallOrFold2 --> turnend2{全員のアクション\nが終了したか?}
turnend2 --> |No| FlopBetting
turnend2 --> |Yes| judgeNocontest2{残りのプレイヤーが\n2人以上存在するか}
judgeNocontest2 --> |No| NoContest2[ノーコンテスト]
judgeNocontest2 --> |Yes| Turn[ターン配布]
NoContest2 --> DetermineWinner
Turn --> TurnBetting[ターンベッティング]
TurnBetting --> BetOrCallOrFold3[アクションを選択]
BetOrCallOrFold3 --> turnend3{全員のアクション\nが終了したか?}
turnend3 --> |No| TurnBetting
turnend3 --> |Yes| judgeNocontest3{残りのプレイヤーが\n2人以上存在するか}
judgeNocontest3 --> |No| NoContest3[ノーコンテスト]
judgeNocontest3 --> |Yes| River[リバー配布]
NoContest3 --> DetermineWinner
River --> RiverBetting[リバーベッティング]
RiverBetting --> BetOrCallOrFold4[アクションを選択]
BetOrCallOrFold4 --> turnend4{全員のアクション\nが終了したか?}
turnend4 --> |No| RiverBetting
turnend4 --> |Yes| Showdown[ショーダウン]
Showdown --> DetermineWinner[勝者を決定]
DetermineWinner --> PotAndSidePot3[チップを獲得]
PotAndSidePot3 --> judge{CREDITが最低入札要件\nを満たすか?}
judge --> |Yes| Continue{ゲームを続けるか?}
Continue --> |Yes| PostBlinds
Continue --> |No| en((End))
judge -->|No| en
---
title: Card Game
---
classDiagram
Table <|-- BlackjackTable
Table <|-- PorkerTable
Table <|-- RummyTable
Table <|-- SpeedTable
Table <|-- TexHoldemPorkerTable
Table <|-- WarTable
Player <|-- BlackjackPlayer
Player <|-- PorkerPlayer
Player <|-- RummyPlayer
Player <|-- SpeedPlayer
Player <|-- TexHoldemPorkerPlayer
Player <|-- WarPlayer
Table *-- "1.." Player: players
BlackjackTable *-- "2-7" Player: players
BlackjackTable *-- "1" Player: house
PorkerTable *-- "2-10" Player: players
RummyTable *-- "2-4" Player: players
SpeedTable *-- "1" Player: player
TexHoldemPorkerTable *-- "2-10" Player: players
WarTable *-- "1" Player: player
WarTable *-- "1" Player: house
Table *-- "1" Deck: #deck
Deck *-- "0..53" Card: cards
Player *-- "0..*" Card: -hand
BlackjackPlayer *-- "2.." Card: -hand
PorkerPlayer *-- "5" Card: -hand
RummyPlayer *-- "7..10" Card: -hand
SpeedPlayer *-- "0..25" Card: -hand
TexHoldemPorkerPlayer *-- "2" Card: -hand
WarPlayer *-- "1" Card: -hand
Player ..> GameDecision
BlackjackPlayer ..> GameDecision
PorkerPlayer ..> GameDecision
RummyPlayer ..> GameDecision
SpeedPlayer ..> GameDecision
TexHoldemPorkerPlayer ..> GameDecision
WarPlayer ..> GameDecision
class Table {
<<Abstract>>
-List~int~ betDenominations
#int turnCounter
-string gamePhase
-List~string~ resultsLog
+assignPlayerHands() void
+clearPlayerHandsAndBets() void
+Abstract evaluateAndGetRoundResults() string
+Abstract evaluateMove(Player player) void
+Abstract getTurnPlayer() Player
+Abstract haveTurn() void
+isFirstPlayer() bool
+isLastPlayer() bool
}
class BlackjackTable {
-isBlackjack(Player) bool
-isAllPlayerActionsResolved() bool
-getHandScore(Player) int
}
class PorkerTable {
-getHandScore(Player) int
}
class RummyTable {
-getHandScore(Player) int
}
class TexHoldemPorkerTable {
-getHandScore(Player) int
}
class SpeedTable {
}
class WarTable {
}
class Player {
<<Abstract>>
-string name
-string playerType
-int chips
-int bet
-int winAmount
-string gameStatus
+ Abstract promptPlayer(int nullable userData) GameDecision
+ Abstract getHandScore() int
}
class BlackjackPlayer{
-getAIBetGameDecision() GameDecision
-getAIActionGameDecision() GameDecision
-getUserActionGameDecision() GameDecision
-getHouseActionGameDecision() GameDecision
}
class PorkerPlayer{
-getAIBetGameDecision() GameDecision
-getAIActionGameDecision() GameDecision
-getUserActionGameDecision() GameDecision
}
class RummyPlayer {
-getAIActionGameDecision() GameDecision
-getUserActionGameDecision() GameDecision
}
class SpeedPlayer {
-getUserActionGameDecision() GameDecision
-getHouseActionGameDecision() GameDecision
}
class TexHoldemPorkerPlayer{
-getAIBetGameDecision() GameDecision
-getAIActionGameDecision() GameDecision
-getUserActionGameDecision() GameDecision
}
class WarPlayer {
-getUserActionGameDecision() GameDecision
-getHouseActionGameDecision() GameDecision
}
class Card {
-string suit
-string rank
+getRankNumber(string gameType) int
}
class Deck {
-string gameType
+shuffle() void
+drawOne() Card
+resetDeck() void
}
%% どのようなベットやアクションを取るべきかというプレイヤーの決定を表すクラス
class GameDecision {
- string action
- int amount
}
関数名・変数名 | 説明 |
---|---|
betDenominations | テーブルで可能なベット金額の単位を表す整数の配列。例えば、[5, 20, 50, 100]など。 |
resultLog | 各ラウンド終了時のハウス以外の全プレイヤーの状態を、文字列の配列の形で記録する。 |
turnCounter | ラウンドロビン形式のゲームで現在ターンのプレイヤーを識別するためのカウンター。 |
evaluateMove() | Table.haveTurn()内で呼ぶ関数。Player.promptPlayer()から現在のプレーヤーのgameDecision(ベット方法やアクションなど)を受け取り, それにしたがって、そのプレイヤーのベット、ハンド、GameStatus、チップの状態などを更新する。 |
haveTurn() | ラウンドロビン形式のゲームで、ゲームフローの制御とテーブルの状態を更新する。 |
関数名・変数名 | 説明 |
---|---|
gamePhase | ゲームのフェーズを表す。{'betting', 'acting', 'roundOver', 'endOfGame'}のどれか。 |
assignPlayerHands() | 各プレイヤーにカードを2枚ずつ配布する。 |
evaluateAndGetRoundResults() | すべてのプレイヤーのアクションが終わり、現在のプレイヤーがプレイヤーの配列の最後のプレイヤーである場合に呼び出される。このメソッドは、ブラックジャックの勝敗判定ルールに従ってプレイヤーを更新し、ラウンドが終了してテーブルがクリアされる前の各プレイヤーの状態を表す文字列を返す。この返された文字列は、Table.resultsLogに追加される。gameStatusが'bust', 'broken', 'surrender'となっているプレイヤーなど、既にラウンドが決定しているプレイヤーは一切更新されない。 |
isAllPlayerActionsResolved() | 全てのプレイヤーがセット{'broken', 'bust', 'stand', 'surrender'}のPlayer.gameStatusを持っていればtrueを返し、持っていなければfalseを返す。ハウスを含むプレイヤーは何度も'hit'し続ける可能性があるので、'acting'フェーズがいつ終わるか把握する必要がある。 |
関数名・変数名 | 説明 |
---|---|
promptPlayer() | TableのgamePhaseとPlayerのplayerTypeに応じて、各Playerが取る行動をGameDecisionクラスのオブジェクトとして返す。 |
関数名・変数名 | 説明 |
---|---|
gameStatus | プレイヤーの状態を表す。{'ready', 'broke (no chip)', 'bet', 'surrender', 'stand', 'hit', 'double', 'bust', 'doubleBust', 'push' }のどれか。 |
getAIBetGameDecision() | Table.promptPlayer()内で呼ぶ関数。AIのベット金額を決める。所持金からベット可能な金額をランダムに決定する。 |
getAIActionGameDecision() | Table.promptPlayer()内で呼ぶ関数。AIのアクションを決める。所持金を考慮し、{'hit', 'stand', 'double', 'surrender'}の候補からアクションをランダムに決定する。 |
getUserActionGameDecision() | Table.promptPlayer()内で呼ぶ関数。Userのアクションを決める。所持金を考慮し、{'hit', 'stand', 'double', 'surrender'}の候補からアクションを決定する。bustしない限り、hitは何度でもできる。 |
getHouseActionGameDecision() | Table.promptPlayer()内で呼ぶ関数。Houseのアクションを決める。持ち札のスコアが17未満であれば、17以上になるまで、Hitを続ける |
関数名・変数名 | 説明 |
---|---|
action | 各ゲームで取り得るアクション - Blackjack: {'broke', 'bust', 'bet', 'surrender', 'stand', 'hit', 'double', 'blackjack'} - Porker: {'broke', 'bet', 'check', 'call', 'raise', 'drop', 'draw'} - Rummy: {'meld', 'rummy'} - Speed: {} - TexHoldemPorker: {'broke', 'bet', 'check', 'call', 'raise', 'drop', 'draw'} - War: {'broke', 'bet', 'surrender', 'war'} |
userData | betのアクションがあるゲームでは、bet金額。その他のゲームでは要検討。 |