Amazon Q CLIでAWSアイコンクイズゲームを作ってみた

# はじめに
Amazon Q Deveopler CLIに関するキャンペーンが開催されています。
Amazon Q CLIでゲームを作って、ブログ記事や動画投稿をすると素敵なTシャツがもらえるそうです。

こちらはAWS Japanによる翻訳記事でわかりやすいです！

https://aws.amazon.com/jp/blogs/news/build-games-with-amazon-q-cli-and-score-a-t-shirt/

元の英語記事です。アイキャッチに設定されているドット絵デザインが素敵なので、こちらのTシャツがもらえると嬉しいですね。

https://community.aws/content/2xIoduO0xhkhUApQpVUIqBFGmAc/build-games-with-amazon-q-cli-and-score-a-t-shirt


## （余談）Amazon Q Developerについて
Amazon Q Develoerは先日のJAWS-UGワークショップで初めて触りましたが、他のAIコードエージェントと同じくフロントエンドアプリはサクッと作ってくれる感じです。
AWSバックエンドもAmazon Q Developerで簡単なチャットアプリを作ってみましたが、会話履歴はDynamoDBに記録し、フロントエンドとのやり取りはAppSyncによるGraphQLと結構モダンなアーキテクチャで作ってくれました！

ただし、リゾルバーをVTLで書いてJavaScript設定のままデプロイしていたので、バグが残っていました・・・
まだまだ最新で情報量が少ないものには対応しづらいのかなーと思いました。


# 簡単な手順
おそらくQ CLIのインストール方法は他で詳しく記載されていますので、簡単な手順だけとします。

## AWS Builder IDを取得する
無償版として利用するにはBuilders IDが必要となります。
Pro版を使う場合、AWSアカウント側での設定により使えるようになるとのこと。

ちなみにAmazon QはAWSクレジットの対象になっているらしく、クレジットの使い道が決まりましたね！

## Amazon Q Develper CLIをインストールする
こちらを参考にAmazon Q Developer CLIをインストールしましょう。
Macの場合は`brew install amazon-q`で行けると思います。

https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-installing.html

Amazon Qの設定画面で、コマンドライン利用などの設定ができますので、有効化されていることを確認しておきます。
![スクリーンショット 2025-06-08 12.31.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3706974/2dce5d04-358a-4ded-afcd-26a42b8fa6ab.png)

## AWS CLIにログインする
AWS CLIがまだインストールされていなければ、合わせてインストールしておきましょう。
`aws configure`で、アクセスキーとシークレットアクセスキーも入れておきます。

## Amazon Qにログインする
ここまで準備ができたら、コマンドライン上で`q login`でログインしましょう。
コマンドラインにURLが表示されるので、ブラウザでアクセスしてBuilders IDで認証しましょう。

## Q CLIを始める
`q chat`でQ CLIがスタートします。
チャットでの対話形式で、アプリを作っていきましょう！


# 作成したゲーム
今回はAWSシンプルアイコンのクイズゲームを作成することにしました。
きっかけは、2025年のJAWS DAYSで開催されたウルトラクイズでもシンプルアイコンのクイズが出され、非常に盛り上がったためです。
次回以降のJAWS FestaやJAWS Daysでもアイコンクイズで正答率を上げるためにこれで練習します！

## Q CLIへの指示内容
Q CLIへの指示は、コマンドライン上でも可能なのですが、今回は仕様書を作っておき、それを理解してゲームを作ってもらいました。
なお、Q Develperは日本語も理解できるので、仕様書は日本語で記述しています。

```specification.md
# 概要
AWSのマネージドサービスのアイコン名を４択から答えるクイズゲームを作成します

# 技術スタック
* Chromeなどのブラウザで動作するゲームとしてください
* バックエンドは作成せずに、html+TypeScript+Cssのようなシンプルな構成としてください

# 基本要件
* クイズは４択で全10問出題されます
* 問題形式の形式は以下のいずれかです
    * (1)アイコンの画像が出題され、そのマネージドサービス名を４択から選択する
    * (2)マネージドサービス名が出題され、アイコン画像を４択から選択する
* 出題させるアイコン画像は全て実際のAWSにあるマネージドサービスとしてください。架空のアイコン画像を作成したり、実際には存在しないAWSサービスは出題しないでください。
* クイズは出題してから10秒間のカウントダウンを初め、0秒までに回答がない場合は不正解としてください。
    * カウントダウンは小数点第1桁秒までを表示してください
* クイズに正解した場合、カウントダウンの残り時間が得点となります。
    * 10問出題後に得点を表示しておいてください。また得点は各モード別にトップ3までは記録しておいてください。
    * なお、小数点の場合は、切り捨ててください。
* 出題レベルをeasy, normal, hardの３つのレベルを設けてください
    * easyは、出題するアイコンはAWS認定試験のCLoud PractitionerやSolution Architect Associateレベルに限定してください
    * normalは、同じアイコンフォルダにあるアイコンから問題を出題してください。例えば、EC2とLambdaとFargateは同じComputeフォルダにあるため、問題の選択肢として含めることができます。
    * hardは、normalに記載の条件に比べ、アイコン同士の画像が類似したものだけを選択肢に含めてください。また、通常のAWS認定試験で出題されないような珍しいサービスアイコンとサービス名称だけにしてください。
        * 例えば、ComuputeフォルダにおけるThinkboxはあまりAWS認定試験では出題されないアイコンです

# アイコン画像
* アイコン画像は以下のパスに格納されているものを使用してください
    * /Users/{username}/appDev/q_game
```

:::note info
今回の開発では、Q CLIでゲームを作る→実際にプレイ→仕様書を修正、というサイクルを繰り返しています。
まさにアジャイル開発のような体験を、AIコードエージェントを使うことで実践できました。
:::

## 作ったゲーム
ゲーム画面の入り口です。
Easy、Normal、Hardの3段階から選べます。
![スクリーンショット 2025-06-08 12.08.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3706974/229d8bed-479c-4c5f-8503-5e4299ab9408.png)

Normalの問題の例です。
出題されるサービス名のアイコンを４択で選択します。
![スクリーンショット 2025-06-08 12.08.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3706974/7cf6f3c1-80b8-4fee-8dbd-46e13d30b7db.png)

Hardの問題例です。
こちらはアイコンのサービス名を４択で選択します。
Hardモードでは、主観ですがあまり馴染みのないサービスかつ似たような名前のサービスが出題されるように指示しています。
![スクリーンショット 2025-06-08 12.09.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3706974/f0c56e0b-b54b-4487-a651-2ff88fc31adf.png)

最後に点数が出ます。
回答時の残り秒数がスコアになるため、早く回答することでハイスコアを狙います。
![スクリーンショット 2025-06-08 12.12.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3706974/3c236403-6cde-4339-8996-61e42c794e27.png)

以下GitHubにもおいてみましたので、ご参考まで。

https://github.com/YukiOgawaP/aws-icon-quiz


## 作ったコードを確認する
今回は３つの難易度でクイズを出題するように指示しているのですが、実コードでは最初に難易度別のカテゴリを作っていました。

なので、これだと何回かやっているうちに答えを覚えてしまいますね・・・
あとTimestreamは別に珍しいサービスではない気が・・・

折角なら画像やサービス名をベクトル化しておき、その類似度を使ってカテゴリ化しておいて出題すると、難しい問題がたくさんできていくのではと思いました。

```script.js
// AWS サービスのデータ - カテゴリ別に整理
const awsServicesByCategory = {
    // Easy レベル - Cloud Practitioner や SAA レベルの基本的なサービス
    easy: [
        { name: "Amazon S3", icon: "png-512/Storage/Simple-Storage-Service.png", category: "Storage" },
        { name: "Amazon EC2", icon: "png-512/Compute/EC2.png", category: "Compute" },
        { name: "Amazon RDS", icon: "png-512/Database/RDS.png", category: "Database" },
        { name: "Amazon DynamoDB", icon: "png-512/Database/DynamoDB.png", category: "Database" },
        { name: "AWS Lambda", icon: "png-512/Compute/Lambda.png", category: "Compute" },
        { name: "Amazon CloudFront", icon: "png-512/Networking-Content-Delivery/CloudFront.png", category: "Networking" },
        { name: "Amazon SNS", icon: "png-512/App-Integration/Simple-Notification-Service.png", category: "Integration" },
        { name: "Amazon SQS", icon: "png-512/App-Integration/Simple-Queue-Service.png", category: "Integration" },
        { name: "Amazon VPC", icon: "png-512/Networking-Content-Delivery/Virtual-Private-Cloud.png", category: "Networking" },
        { name: "Amazon Route 53", icon: "png-512/Networking-Content-Delivery/Route-53.png", category: "Networking" },
        { name: "AWS IAM", icon: "png-512/Security-Identity-Compliance/Identity-and-Access-Management.png", category: "Security" },
        { name: "Amazon CloudWatch", icon: "png-512/Management-Governance/CloudWatch.png", category: "Management" },
        { name: "AWS CloudFormation", icon: "png-512/Management-Governance/CloudFormation.png", category: "Management" },
        { name: "Amazon EBS", icon: "png-512/Storage/Elastic-Block-Store.png", category: "Storage" },
        { name: "Amazon API Gateway", icon: "png-512/App-Integration/API-Gateway.png", category: "Integration" }
    ],
    
    // Normal レベル - 同じカテゴリのサービス
    compute: [
        { name: "Amazon EC2", icon: "png-512/Compute/EC2.png", category: "Compute" },
        { name: "AWS Lambda", icon: "png-512/Compute/Lambda.png", category: "Compute" },
        { name: "AWS Elastic Beanstalk", icon: "png-512/Compute/Elastic-Beanstalk.png", category: "Compute" },
        { name: "AWS Fargate", icon: "png-512/Compute/Fargate.png", category: "Compute" },
        { name: "AWS Batch", icon: "png-512/Compute/Batch.png", category: "Compute" },
        { name: "Amazon EC2 Auto Scaling", icon: "png-512/Compute/EC2-Auto-Scaling.png", category: "Compute" },
        { name: "AWS Lightsail", icon: "png-512/Compute/Lightsail.png", category: "Compute" }
    ],
    storage: [
        { name: "Amazon S3", icon: "png-512/Storage/Simple-Storage-Service.png", category: "Storage" },
        { name: "Amazon EBS", icon: "png-512/Storage/Elastic-Block-Store.png", category: "Storage" },
        { name: "Amazon EFS", icon: "png-512/Storage/EFS.png", category: "Storage" },
        { name: "Amazon S3 Glacier", icon: "png-512/Storage/Simple-Storage-Service-Glacier.png", category: "Storage" },
        { name: "AWS Storage Gateway", icon: "png-512/Storage/Storage-Gateway.png", category: "Storage" },
        { name: "AWS Backup", icon: "png-512/Storage/Backup.png", category: "Storage" }
    ],
    database: [
        { name: "Amazon RDS", icon: "png-512/Database/RDS.png", category: "Database" },
        { name: "Amazon DynamoDB", icon: "png-512/Database/DynamoDB.png", category: "Database" },
        { name: "Amazon Aurora", icon: "png-512/Database/Aurora.png", category: "Database" },
        { name: "Amazon ElastiCache", icon: "png-512/Database/ElastiCache.png", category: "Database" },
        { name: "Amazon Neptune", icon: "png-512/Database/Neptune.png", category: "Database" },
        { name: "Amazon DocumentDB", icon: "png-512/Database/DocumentDB.png", category: "Database" }
    ],
    networking: [
        { name: "Amazon VPC", icon: "png-512/Networking-Content-Delivery/Virtual-Private-Cloud.png", category: "Networking" },
        { name: "Amazon CloudFront", icon: "png-512/Networking-Content-Delivery/CloudFront.png", category: "Networking" },
        { name: "Amazon Route 53", icon: "png-512/Networking-Content-Delivery/Route-53.png", category: "Networking" },
        { name: "AWS Direct Connect", icon: "png-512/Networking-Content-Delivery/Direct-Connect.png", category: "Networking" },
        { name: "Elastic Load Balancing", icon: "png-512/Networking-Content-Delivery/Elastic-Load-Balancing.png", category: "Networking" },
        { name: "AWS Global Accelerator", icon: "png-512/Networking-Content-Delivery/Global-Accelerator.png", category: "Networking" }
    ],
    
    // Hard レベル - 珍しいサービスや類似したアイコン
    hard: [
        { name: "AWS Thinkbox Deadline", icon: "png-512/Compute/Thinkbox-Deadline.png", category: "Compute" },
        { name: "AWS Thinkbox Frost", icon: "png-512/Compute/Thinkbox-Frost.png", category: "Compute" },
        { name: "AWS Thinkbox Krakatoa", icon: "png-512/Compute/Thinkbox-Krakatoa.png", category: "Compute" },
        { name: "AWS Thinkbox Sequoia", icon: "png-512/Compute/Thinkbox-Sequoia.png", category: "Compute" },
        { name: "AWS Thinkbox Stoke", icon: "png-512/Compute/Thinkbox-Stoke.png", category: "Compute" },
        { name: "AWS Thinkbox XMesh", icon: "png-512/Compute/Thinkbox-XMesh.png", category: "Compute" },
        { name: "AWS Snowcone", icon: "png-512/Storage/Snowcone.png", category: "Storage" },
        { name: "AWS Snowball", icon: "png-512/Storage/Snowball.png", category: "Storage" },
        { name: "AWS Snowmobile", icon: "png-512/Storage/Snowmobile.png", category: "Storage" },
        { name: "Amazon FSx for Lustre", icon: "png-512/Storage/FSx-for-Lustre.png", category: "Storage" },
        { name: "Amazon FSx for Windows", icon: "png-512/Storage/FSx-for-WFS.png", category: "Storage" },
        { name: "Amazon FSx for OpenZFS", icon: "png-512/Storage/FSx-for-OpenZFS.png", category: "Storage" },
        { name: "Amazon Timestream", icon: "png-512/Database/Timestream.png", category: "Database" },
        { name: "Amazon Keyspaces", icon: "png-512/Database/Keyspaces.png", category: "Database" },
        { name: "Amazon MemoryDB for Redis", icon: "png-512/Database/MemoryDB-for-Redis.png", category: "Database" }
    ]
};
```


# まとめ
今回はキャンペーンもあったので、Amazon Q CLIを使ってブラウザゲームを作ってみました。
簡単なフロントエンドアプリならVibe Codingでできちゃいますね。
実際の開発でもどんどん活用していきたいと思います。