EY-Office ブログ

Gemini 2.5 Proが凄いと聞いて、いつもの画像からReactコンポーネントを作ってもらった

GoogleのAI Gemini 2.5 Proがリリースされ、プログラム作成能力も凄いとの噂ですね!

定番化している画像をもとにAIに生成させたReactコンポーネントシリーズをGemini 2.5 Proでも試してみました。

AI-code-generate Bing Image Creatorが生成した画像を使っています

各AIの生成したReactコンポーネントの結果

  • 元画像
  • Cursor + Claude 3.5
  • Cursor + Claude 3.7(ジャンケン機能あり)
  • Copilot Vision + GPT-4o
  • Cursor + Gemini 2.5 Pro

Gemini 2.5 Pro生成したReactコンポーネント

Gemini 2.5 Proの生成したコードにはジャンケン機能はありませんでしたが、表示が美しいですね。

思考過程

1.  **コンポーネント構造:** `JankenGame` という関数コンポーネントを定義しています。
2.  **TypeScript:**
    *   `Result``Hand` という型エイリアスを定義して、勝敗と手の種類を制限しています。
    *   `GameRecord` インターフェースで対戦履歴データの型を定義しています。
    *   `React.FC` を使用して、関数コンポーネントの型を定義しています。
3.  **Tailwind CSS:**
    *   `className` 属性にTailwindのユーティリティクラスを指定してスタイリングしています。
    *   ヘッダー、ボタン、テーブルなどに `bg-*`, `text-*`, `p-*`, `m-*`, `flex`, `justify-*`, `items-*`, `shadow-*`, `rounded` などのクラスを使用しています。
    *   テーブルは `min-w-full`, `divide-y`, `divide-gray-200` などで基本的なレイアウトと区切り線を追加しています。
    *   `thead``tbody` でヘッダーと本体を分けています。
4.  **データ:** サンプルデータとして `gameHistory` 配列を用意しています。実際のアプリケーションでは、この部分はpropsやstateから動的に取得するように変更する必要があります。
5.  **色分け:**
    *   `getResultColor` 関数で結果(勝ち/負け/引き分け)に応じて文字色を変更するクラスを返します。
    *   `getHandColor` 関数で手(グー/チョキ/パー)および時間列の文字色を(例として)変更するクラスを返します。画像ではグーが赤、パーが青に見えるため、それに応じた色を設定しています。チョキの色は推測です。時間は最新の負けが赤字なので、人間の手の色に合わせるようにしています。

**利用方法:**

1.  このコードを `JankenGame.tsx` としてプロジェクト内に保存します。
2.  Tailwind CSSがプロジェクトに設定されていることを確認してください。(`tailwind.config.js``index.css`/@tailwindディレクティブなど)
3.  他のReactコンポーネントから `import JankenGame from './JankenGame';` のようにインポートして `<JankenGame />` として使用します。

これで、提供された画像に似たUIのReactコンポーネントが作成されます。必要に応じて、色や細かいスタイル、データの取得方法などを調整してください。

生成されたコード

app/JankenGame.tsx

import React from 'react';

type Result = '勝ち' | '負け' | '引き分け';
type Hand = 'グー' | 'チョキ' | 'パー';

interface GameRecord {
  time: string;
  humanHand: Hand;
  computerHand: Hand;
  result: Result;
}

const getResultColor = (result: Result): string => {
  switch (result) {
    case '勝ち':
      return 'text-blue-600';
    case '負け':
      return 'text-red-600';
    case '引き分け':
      return 'text-gray-600';
    default:
      return 'text-gray-900';
  }
};

const getHandColor = (hand: Hand): string => {
    switch (hand) {
        case 'グー':
            return 'text-red-500'; // Example color for Rock
        case 'チョキ':
            return 'text-yellow-500'; // Example color for Scissors
        case 'パー':
            return 'text-blue-500'; // Example color for Paper
        default:
            return 'text-gray-900';
    }
}


const JankenGame: React.FC = () => {
  // Sample data - replace with actual game data
  const gameHistory: GameRecord[] = [
    { time: '10:05:52', humanHand: 'パー', computerHand: 'グー', result: '勝ち' },
    { time: '10:05:51', humanHand: 'チョキ', computerHand: 'チョキ', result: '引き分け' },
    { time: '10:05:50', humanHand: 'グー', computerHand: 'パー', result: '負け' },
  ];

  return (
    <div className="min-h-screen bg-gray-100">
      {/* Header */}
      <header className="bg-blue-600 text-white p-4 shadow-md">
        <div className="container mx-auto flex justify-between items-center">
          <h1 className="text-2xl font-bold">じゃんけん ポン!</h1>
          <nav>
            <a href="#" className="px-3 py-2 rounded hover:bg-blue-700">対戦結果</a>
            <a href="#" className="px-3 py-2 rounded hover:bg-blue-700 ml-4">対戦成績</a>
          </nav>
        </div>
      </header>

      {/* Main Content */}
      <main className="container mx-auto mt-8 p-4">
        <h2 className="text-xl font-semibold text-center mb-6">対戦結果</h2>

        {/* Action Buttons */}
        <div className="flex justify-center space-x-4 mb-8">
          <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-6 rounded shadow">
            グー
          </button>
          <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-6 rounded shadow">
            チョキ
          </button>
          <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-6 rounded shadow">
            パー
          </button>
        </div>

        {/* Game History Table */}
        <div className="bg-white shadow-md rounded-lg overflow-hidden">
          <table className="min-w-full divide-y divide-gray-200">
            <thead className="bg-gray-50">
              <tr>
                <th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                  時間
                </th>
                <th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                  人間
                </th>
                <th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                  コンピュータ
                </th>
                <th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                  結果
                </th>
              </tr>
            </thead>
            <tbody className="bg-white divide-y divide-gray-200">
              {gameHistory.map((record, index) => (
                <tr key={index} className={index % 2 === 0 ? 'bg-white' : 'bg-gray-50'}>
                  <td className={`px-6 py-4 whitespace-nowrap text-sm font-medium ${getHandColor(record.humanHand)}`}>
                    {record.time}
                  </td>
                  <td className={`px-6 py-4 whitespace-nowrap text-sm ${getHandColor(record.humanHand)}`}>
                    {record.humanHand}
                  </td>
                  <td className={`px-6 py-4 whitespace-nowrap text-sm ${getHandColor(record.computerHand)}`}>
                    {record.computerHand}
                  </td>
                  <td className={`px-6 py-4 whitespace-nowrap text-sm font-semibold ${getResultColor(record.result)}`}>
                    {record.result}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </main>
    </div>
  );
  • 一部インデント数が違う部分があったりするのが不思議ですね。他のAIモデルでは見ない現象ですね
  • コメントが英語ですね

これらはプロンプトで指定したら改善されました、さらにコメントも増えました 😁 一部分をのせますね。

// 手の種類に応じた文字色を返すヘルパー関数(時間列にも適用)
const getHandColor = (hand: Hand): string => {
  switch (hand) {
    case 'グー':
      return 'text-red-500'; // グーの例の色
    case 'チョキ':
      return 'text-yellow-500'; // チョキの例の色
    case 'パー':
      return 'text-blue-500'; // パーの例の色
    default:
      return 'text-gray-900';
  }
}

まとめ

Gemini 2.5 Proの生成したReactコードの画面は美しいですね❗ 表示の完成度はClaude 3.7より元画像に近いかもしれませんね(ただし、Claude 3.7はジャンケンのロジックまで生成しているので単純な比較は出来ませんが)。

美しい画面ですがジャンケン結果表示に謎の黄色がありますね。😁
AIモデルにも個性があるのでしょうか❓

- about -

EY-Office代表取締役
・プログラマー
吉田裕美の
開発者向けブログ