見出し画像

大"帝"富豪

今日も今日とてChatGPT-4oくんの実力を確認。プログラム回も兼ねる感じで進めていきたいと思います。


大富豪のコード

私「Pythonで遊べる、大富豪を作りたいと思います。コードを考えてもらえますか」

import random

# カードとランクの定義
suits = ['♠', '♥', '♦', '♣']
ranks = ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2']
deck = [rank + suit for suit in suits for rank in ranks]

# カードの強さを定義
card_strength = {rank + suit: (i + 3) % 13 + 3 for i, rank in enumerate(ranks) for suit in suits}

# プレイヤークラスの定義
class Player:
def __init__(self, name):
self.name = name
self.hand = []

def play_card(self, current_strength):
playable_cards = [card for card in self.hand if card_strength[card] > current_strength]
if not playable_cards:
return None
selected_card = random.choice(playable_cards)
self.hand.remove(selected_card)
return selected_card

# ゲームのセットアップ
def deal_cards(players, deck):
random.shuffle(deck)
while deck:
for player in players:
if deck:
player.hand.append(deck.pop())

def main():
# プレイヤーの作成
player = Player("あなた")
ai = Player("AI")

players = [player, ai]

# カードを配る
deal_cards(players, deck)

# ゲーム開始
current_strength = 0
turn = 0

while True:
current_player = players[turn % 2]
print(f"\n{current_player.name}のターンです")
print(f"あなたの手札: {', '.join(player.hand)}")

if current_player == player:
while True:
selected_card = input("カードを選択してください (例: 3♠, パスは'pass'):")
if selected_card == 'pass':
selected_card = None
break
elif selected_card in player.hand and card_strength[selected_card] > current_strength:
player.hand.remove(selected_card)
break
else:
print("無効なカードです。再度選択してください。")
else:
selected_card = ai.play_card(current_strength)

if selected_card:
print(f"{current_player.name}が{selected_card}を出しました")
current_strength = card_strength[selected_card]
else:
print(f"{current_player.name}はパスしました")
current_strength = 0

if not current_player.hand:
print(f"{current_player.name}の勝ちです!")
break

turn += 1

if __name__ == "__main__":
main()

ChatGPTの出力

コンピュータとプレイヤーの、2人対戦ゲームのようです。ちゃんと「3」が弱くて「2」が強いことはわかっているよう。ジョーカーはありませんね。

例えば疑問に思ったら

疑問に思ったところは、聞いてみることができるのが面白いところ。「card_strength = {rank + suit: (i + 3) % 13 + 3 for i, rank in enumerate(ranks) for suit in suits} の部分が理解できませんでした。解説してもらえますか」と聞いてみます。

もちろんです。この部分のコードは、各カードの強さを定義するための辞書を作成しています。この辞書 `card_strength` は、カードの文字列表現(例:'3♠'、'A♦'など)をキーとして、カードの強さを値として持っています。

以下にコードを詳しく解説します:

```python
card_strength = {rank + suit: (i + 3) % 13 + 3 for i, rank in enumerate(ranks) for suit in suits}
```

### 分解して解説:

1. **リストの準備**:
```python
suits = ['♠', '♥', '♦', '♣']
ranks = ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2']
```
- `suits`は4つのスート(トランプの柄)を表しています。
- `ranks`は13種類のランク(数字と絵札)を表しています。大富豪のルールでは、通常「3」が最も弱く、「2」が最も強いとされています。

2. **辞書内包表記**:
```python
{rank + suit: (i + 3) % 13 + 3 for i, rank in enumerate(ranks) for suit in suits}
```
この部分は、辞書内包表記と呼ばれるもので、簡潔に辞書を作成する方法です。

3. **キーの生成**:
```python
rank + suit
```
- これはカードを文字列として表現します。例えば、ランクが'3'でスートが'♠'の場合、'3♠'というキーが生成されます。

4. **カードの強さを計算**:
```python
(i + 3) % 13 + 3
```
- `enumerate(ranks)`は、`ranks`リストの各要素とそのインデックス(`i`)を返します。
- `i + 3`は、カードの強さを3から始まる連続した数字に変換するためのものです(`3`を`3`、`4`を`4`、...、`A`を`12`、`2`を`13`とするため)。
- `% 13`を使って結果を0から12の範囲に収め、`+ 3`で最終的な強さの値を3から15の範囲に調整しています。
- `i + 3` の結果を `13` で割った余りを計算することで、ランクを循環させています。例えば、`A`(インデックスは10)は`13`で割った余りは`0`、`2`(インデックスは11)は`1`、というようになります。
- その後、`+ 3` してカードの強さを最終的に3から15の範囲に設定します。

5. **結果の辞書**:
- この計算により、各カードに対応する強さの値が決定されます。例えば:
```python
'3♠': 3, '4♠': 4, ..., 'A♠': 14, '2♠': 15, ...
```

### 具体例:

- ランク'3'(インデックス0):
```python
(0 + 3) % 13 + 3 = 3 + 3 = 6
```
- ランク'4'(インデックス1):
```python
(1 + 3) % 13 + 3 = 4 + 3 = 7
```
- ランク'2'(インデックス12):
```python
(12 + 3) % 13 + 3 = 15 % 13 + 3 = 2 + 3 = 5
```

このようにして、各カードの強さが辞書 `card_strength` に保存され、ゲームのロジックで利用できるようになります。

ChatGPTの出力

めちゃくちゃ詳しく解説してくれる!!!(しかも、実際は色付きのコードで、みやすさも凄いです)

見やすくて詳しい

改良も加えてくれるよ

「これまでに誰も思いついていないような追加ルールを1つ加えたいです。コードも含めて提案してもらえますか?」

それでは、大富豪に独自のルールを1つ追加してみましょう。新しいルールとして「ランクアップ」ルールを追加します。このルールは、特定の条件を満たすとプレイヤーの出せるカードのランクが一段階上がるというものです。

### 新ルール「ランクアップ」:
- プレイヤーが連続で3ターン勝つと、次のターンからそのプレイヤーの出せるカードのランクが1段階上がります。
- 例えば、通常のターンでは「5」を出せない場面でも、ランクアップしていれば「5」を出すことができます。

このルールを加えるためのコードの変更を以下に示します。

```python
import random

# カードとランクの定義
suits = ['♠', '♥', '♦', '♣']
ranks = ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2']
deck = [rank + suit for suit in suits for rank in ranks]

# カードの強さを定義
card_strength = {rank + suit: (i + 3) % 13 + 3 for i, rank in enumerate(ranks) for suit in suits}

# プレイヤークラスの定義
class Player:
def __init__(self, name):
self.name = name
self.hand = []
self.win_streak = 0
self.rank_up = False

def play_card(self, current_strength):
playable_cards = [card for card in self.hand if card_strength[card] > current_strength]
if not playable_cards:
return None
if self.rank_up:
# ランクアップにより1段階上のカードも出せるようにする
min_strength = min(card_strength[card] for card in playable_cards)
rank_up_cards = [card for card in self.hand if card_strength[card] >= min_strength]
selected_card = random.choice(rank_up_cards)
else:
selected_card = random.choice(playable_cards)
self.hand.remove(selected_card)
return selected_card

# ゲームのセットアップ
def deal_cards(players, deck):
random.shuffle(deck)
while deck:
for player in players:
if deck:
player.hand.append(deck.pop())

def main():
# プレイヤーの作成
player = Player("あなた")
ai = Player("AI")

players = [player, ai]

# カードを配る
deal_cards(players, deck)

# ゲーム開始
current_strength = 0
turn = 0

while True:
current_player = players[turn % 2]
print(f"\n{current_player.name}のターンです")
print(f"あなたの手札: {', '.join(player.hand)}")

if current_player == player:
while True:
selected_card = input("カードを選択してください (例: 3♠, パスは'pass'):")
if selected_card == 'pass':
selected_card = None
break
elif selected_card in player.hand and (card_strength[selected_card] > current_strength or current_player.rank_up):
player.hand.remove(selected_card)
break
else:
print("無効なカードです。再度選択してください。")
else:
selected_card = ai.play_card(current_strength)

if selected_card:
print(f"{current_player.name}が{selected_card}を出しました")
current_strength = card_strength[selected_card]
current_player.win_streak += 1
if current_player.win_streak >= 3:
current_player.rank_up = True
print(f"{current_player.name}はランクアップしました!")
else:
print(f"{current_player.name}はパスしました")
current_strength = 0
current_player.win_streak = 0

if not current_player.hand:
print(f"{current_player.name}の勝ちです!")
break

turn += 1

if __name__ == "__main__":
main()
```

このコードでは、「ランクアップ」ルールを次のように実装しています:
- `Player`クラスに`win_streak`(連勝数)と`rank_up`(ランクアップ状態)を追加しました。
- 連続で3ターン勝利すると、`rank_up`が`True`になり、次のターンからプレイヤーは1段階上のカードも出せるようになります。
- プレイヤーがパスすると連勝数はリセットされます。

この追加ルールにより、戦略的な深みが増し、ゲームがより面白くなるでしょう。

ChatGPTの出力

3連勝すると、ランクアップする、というのは確かに斬新なルール。これとこれで勝てても、最後にこれが残ると最悪だもんなぁ、という状況を少しだけ改善することができますよね。(数字が強くなるのがいいのか、1枚出しが2枚出しになるとか、ランクアップの方法は複数あっていいような気がしますが)

しかもそれを、すぐにコードに「正しい位置に」反映させることができる、というのが本当に凄いと思います。

まとめ

大富豪のコードも、以前より遥かに可読性の高い、すっきりしたコードになっていますし、改良ルールの提案もスマートかつ、その分のコードもササッと表示してくれています。

この3日、「凄いなぁ」しか言っていませんが、おそらくこのあと数日は「凄いなぁ」を言い続けることになるんだろうなぁ、と思っています。

というわけで、ただただ、驚いている、ということだけをお伝えして、今日はこのへんで。ほなね!

例のAI画像のコーナー

大富豪より、ランクアップしてさらに強くなると、何なんでしょうか。

新しいルール「ランクアップ」が追加されたことで、プレイヤーがさらに強力な存在となります。このため、「大富豪」よりも強そうな名前を考えました。以下は5つのアイデアです:

1. **帝王**(ていおう)
2. **覇王**(はおう)
3. **王者**(おうじゃ)
4. **大帝**(たいてい)
5. **無双**(むそう)

これらの名前は、プレイヤーの強力さを強調するのに適していると思います。ゲームに新しいルールとともにこのような名前を付けると、よりインパクトのあるものになるでしょう。

ChatGPTの出力

大帝+大富豪で大帝富豪でしょうかね。

…というわけで、大帝富豪風の画像を出力。

"Create an image of an 'Emperor Tycoon,' a figure wealthier than a billionaire. He should exude unparalleled luxury and power, surrounded by gold, diamonds, and the most opulent symbols of success. His attire should be regal, combining modern and ancient royal elements."

ChatGPTの出力
見出しのはライオンがいてちょっと負けた

いただいたサポートは、きっと、ドイツアマゾンからの送料に変わると思います。 温かいご支援、お待ちしております。