Chat GPTが一般公開されてから2周年を迎えるにあたり、ボブは昨年よりも一段と手応えのあるものを提供したいと考えていました。私は、AIが完全に開発したゲームを提案するのが良い小さな挑戦になると思いました。誤解のないように言っておきますが、ここで言う「開発」とは、これまで私がやってきたようにAIを加速や効率化のツールとして使うことではなく、人工知能が書いたコードに一切手を加えずに「完全な」ゲームを作り上げることを目指すものです。これが実際にはそれほど簡単な挑戦ではありません。

AIツールはプログラミングを大幅に加速するものの、知能を持っているわけではなく、提示されたリクエストを開発し、適切に整形するだけです。個人的には、Unityで「AI Toolbox」という最初期のツールの1つを使っています。このツールは信頼性が高く、定期的にアップデートされています。仕組みは簡単で、ツールにシンプルな言葉でC#スクリプトの作成(または修正)を依頼すると、すぐにそのまま使えるスクリプトが手に入ります。(言語モデルへの適切な指示の仕方が理解できれば、非常に良い結果が得られます。)注意しておきたいのは、AI Toolboxは開発者が自分でできないことを提供してくれるわけではないという点です。なぜなら、適切な依頼の仕方がわからない場合、良い結果を得ることができないからです。しかし、このツールを使えば、数分かかるスクリプトの記述やドキュメントの調査をほぼ瞬時に終わらせることができます。完全なプロジェクトでは、これにより何時間も節約できるのです!
例を挙げましょうか?例えば、シンプルなコマンドシステムが必要だとします。その場合、私はAIツールに次のような依頼をします:

スクリプト名:Commandes
アプリケーションを終了する。
インスペクター内:
プライベート文字列nomEcranTitre
プライベートGameObjectfenêtreAide
動作:
F1キーが押された場合:fenêtreAideが非表示なら表示し、表示中なら非表示にする。
F2キーが押された場合:nomEcranTitreという名前のシーンを読み込む。
ESCキーが押された場合:
アプリケーションを終了する。
その結果、例外を考慮し、完全に機能するスクリプトを手に入れることができます:

なかなか良いですよね?内容としては、スクリプトはとてもシンプルですが、最初のウィンドウを書くのは、2番目のウィンドウを書くよりずっと速いです。特に、Chat GPT(AI Toolboxで使用されている言語モデル)はタイプミスに対して非常に寛容ですが、C#はそうではないという点が大きな違いです!次に、UnityからPDFを開く例を見てみましょう。

スクリプト名:
「OuverturePdf」
関数:
public OuvrirPdf(string nomPDF)OuvrirPdf内で、nomPDFという名前のPDFファイルを開く。
フランス語と英語の素敵な混合をしましたね(「fonction public」)!そして、見た目はシンプルなコマンドでも、正確な構文を見つけるためにドキュメントを探し回る必要があり、これには簡単に5分から10分かかることがあります。しかし、人工知能を使えば、ビシッ!と、瞬時にスクリプトが得られます:

明確で機能的で、usingも組み込まれています…つまり、素晴らしい仕上がりですね!人工知能は、開発者にとって貴重な味方です。しかし、開発者が手動で生成したスクリプトを再度修正する必要がないほど、AIは進化しているのでしょうか?ボブはその点を確認します!
目次
ロードマップ

私の実験のために、私は「テトリス」を理想的なモルモットとして選びました。なぜテトリスか?主に、私がこれまで自分の技術を磨くために再作成してきたクラシックゲームの中で(昨年春の「Bob le Frog」を思い出してください!)、テトリスだけが私に立ちはだかっているからです。なぜかは分かりませんが、40年以上も情熱を注いで遊んできたこのクラシックゲームを再作成する試みはすべて失敗に終わっています。ゲームの論理の中に、私が理解できていない何かがあるに違いありません。自分が遊ぶときはかなり上手だと思うのですが…とにかく、今こそリベンジの時です!
しかし、この挑戦を達成するためには、私にはロードマップが必要です。まず第一に、私は究極のテトリスを再現しようとは思いません。公式のルールに忠実に、ピクセル単位で再現するつもりはありません。実際、複数の正統バージョンの間には違いがあり、クローンも数多くあります。機能するクローンを手に入れた時点で、私はこの挑戦を達成したとみなします。そして、bobdupneu.frでは、ルールを決めるのはボブだということをお忘れなく!二つ目のことですが、この記事を思いついてから1年以上経ち、過去2回は残念ながら失敗したため、今回はガイドを探すことが必要だと感じました。Valemのテトリスに関するチュートリアルが完璧な手引きとなるでしょう!
ガイドに従うことで、私はChat GPTへのリクエストに集中できるようになります。そして、成功への道筋を維持するために、AIから得るべきもののモデルを手に入れることができます。もしかしたら、3回目がうまくいくかもしれません!
「手動」での準備
挑戦を簡単に保つため、私はUnityのツールのみを使用し、Tetris Guidelineの推奨事項に大まかに従います。Unityで新しい「Universal 2D」プロジェクトを作成し、名前をTetrIAにします。なぜなら、私は面白い人だからです。そして、実験の結果を記事に組み込むため、すぐにWebプロジェクトに切り替えます。
基本的な設定が完了したら、私は10列×20行のグリッド、公式の7つのテトリミノ、そしてシンプルなインターフェースを作成します。この際、ガイドValemの説明に従います。
以下のスクリーンショットが結果を示しています。さて、次はChat GPTに働いてもらいましょう!

実験
大胆にいきましょう!Chat GPTにテトリスのゲームを作成してもらいましょう、シンプルに!

結果は一見興味深いように見えますが…

唯一の小さな問題は、AIが関数に関してはただの空の殻であるということです…

要するに、前にも説明したように、Chat GPTはプログラマーの代わりにはならず、プログラマーは正確な指示を与え、ゲームの全体的な論理を自分で考える必要があります。AIはコードの執筆を加速するだけです。よく頑張ったけれど、やっぱり少しは作業しないといけませんね!
ゲームマネージャー
私はいつも開発を始めるとき、空のオブジェクト「Game Manager」を作成し、ゲームの適切な管理に必要なすべての要素をまとめた「GameManager」スクリプトを添付します。私の最初のChat GPTへのリクエストは少し長いですが、複雑な内容は含まれていません:

スクリプト名:GameManager
スクリプトに関連付けられた公開変数:
int Score, Lignes, Niveau, Vitesse
Text T_Score, T_Niveau, T_Lignes
bool JeuEnCours
スクリプトに関連付けられたプライベート変数:
GameObject p_GameOver
GameObject p_Start
Start()内:
VitesseとNiveauを1に初期化する
ActualiserUI()を呼び出す
p_GameOverを非表示にする
p_Startを表示する
JeuEnCoursをfalseにする
Update()内:
JeuEnCoursがfalseでp_Startが表示されている場合:
プレイヤーがEnterキーを押すと、JeuEnCours = true
JeuEnCoursがfalseでp_GameOverが表示されている場合:
プレイヤーがEnterキーを押すと、nouvellePartie()が呼ばれる
公開関数 ActualiserUI():
T_Score = Scoreを6桁以上で表示
T_Niveau = Niveauを2桁以上で表示
T_Lignes = Lignesを3桁以上で表示
公開関数 GameOver():
JeuEnCours = false
p_GameOverを表示する
プライベート関数 nouvellePartie():
シーンを再読み込みする
これで、私は完全に正しいスクリプトを取得します。ただし、UIで実際に使用しているText Mesh Proに変更するため、手動で変更を加え、また、StartとGame Overの2つのパネルをシリアライズしてInspectorでリンクできるようにします。

これはChat GPTのエラーではなく、後から気づいた細かな点です。したがって、私のスクリプトは次の通りです:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using TMPro;
public class GameManager : MonoBehaviour
{
[Tooltip("Score du joueur")]
public int Score;
[Tooltip("Nombre de lignes complétées")]
public int Lignes;
[Tooltip("Niveau actuel")]
public int Niveau;
[Tooltip("Vitesse du jeu")]
public int Vitesse;
[Tooltip("Texte affichant le score")]
public TextMeshProUGUI T_Score;
[Tooltip("Texte affichant le niveau")]
public TextMeshProUGUI T_Niveau;
[Tooltip("Texte affichant les lignes")]
public TextMeshProUGUI T_Lignes;
[Tooltip("Indique si le jeu est en cours")]
public bool JeuEnCours;
[SerializeField] GameObject p_GameOver;
[SerializeField] GameObject p_Start;
void Start()
{
Vitesse = 1;
Niveau = 1;
ActualiserUI();
p_GameOver.SetActive(false);
p_Start.SetActive(true);
JeuEnCours = false;
}
void Update()
{
if (!JeuEnCours && p_Start.activeSelf)
{
if (Input.GetKeyDown(KeyCode.Return))
{
JeuEnCours = true;
p_Start.SetActive(false);
}
}
if (!JeuEnCours && p_GameOver.activeSelf)
{
if (Input.GetKeyDown(KeyCode.Return))
{
nouvellePartie();
}
}
}
public void ActualiserUI()
{
T_Score.text = Score.ToString("D6");
T_Niveau.text = Niveau.ToString("D2");
T_Lignes.text = Lignes.ToString("D3");
}
public void GameOver()
{
JeuEnCours = false;
p_GameOver.SetActive(true);
}
private void nouvellePartie()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
このコードは完全に機能しており、必要なusingも準備されていて、使用されているコードはかなりエレガントです。ゲームを起動して、すべてが正常に動作していることを確認します(ディスプレイの更新と、Enterキーを押すことで消えるStartパネル)。

テトリス固有のロジックに取り掛かる時が来ました。
テトリミノを移動する
テトリスでは、ゲーム内のテトリミノは自動的に下に移動し、その速度はレベルに応じて増加します。プレイヤーは、ピースを右と左に移動させることができ、1ユニット単位で動かします。また、ピースの降下を加速させることができます。さらに、ピースを時計回りに90度回転させることができ、ピースは常にグリッド内に留まらなければなりません。最も簡単なものから始めましょう:垂直および水平方向の移動。シンプルなリクエストで、短くて完全に機能するスクリプトが作成されます。

スクリプト名:Tetrimino
シーン内でGameManagerスクリプトを持つオブジェクトを探し、プライベート変数 _GM に格納する
もし _GM.JeuEnCours が true ならば:
ゲームオブジェクトは _GM.Vitesse に従って継続的に下に移動する
右矢印キーが押されると、ゲームオブジェクトは1ユニット右に移動し、左矢印キーが押されると1ユニット左に移動する
矢印キーが押されたままであれば、新しい移動が0.2秒ごとに行われる
下矢印キーが押されている間、速度は10倍に増加する

次に、ゲームエリア内にピースを固定する必要があります。念のため、グリッドは10列×20行で構成されています。したがって、各テトリミノの4つの四角形が各移動後にこのグリッド内に収まることを確認し、そうでない場合は移動をキャンセルする必要があります。このため、私はChat GPTに、先ほど作成したスクリプトを修正するように依頼します。

ゲームグリッドを10 x 20のサイズで定義する
ゲームオブジェクトの各移動のたびに、ゲームオブジェクトの子オブジェクトがこのグリッド内に収まっていることを確認し、そうでない場合は移動をキャンセルする 確認は整数値で行う必要がある
リクエストは非常にシンプルですが、Chat GPTが行った作業はかなり重要です。ただし注意が必要です:作成されたコードに複雑な部分はありませんが(ここにこそAIが開発者のアシスタントとしての力を発揮する)、5行のリクエストが3倍以上の行数のコードを生み出します。書式設定も含めて、これらの行のいずれかに誤りがあると、セミコロンを忘れた場合でもコンパイルエラーを引き起こします。したがって、時間の節約は明らかです。今回は、Chat GPTがゲームのグリッドを作成し、それを新しい関数で使用して、テトリミノがゲームエリア内にあることを確認し、既存の関数も新しい要素を考慮して修正しています。シンプルで効果的です!



次はテトリミノを回転させる必要があります。私がガイドとして使っているValemの動画には、7つのテトリミノの回転軸を示す便利な表が表示されています。

したがって、Chat GPTにこの回転ポイントを作成するように依頼する必要があります。この回転ポイントは、各形状のためにインスペクタで調整される位置となり、上方向キーが押されるたびにテトリミノがその形状の周りで90°回転するようにします。
リクエストはシンプルで、生成されたコードはさらにシンプルです:

Vector3型のpublic変数PointRotationを作成する
プレイヤーがキーボードの上矢印キーを押すと、GameObjectはPointRotationを中心に90°回転する
回転がゲームグリッド外にTetriminoを出さないようにする;もし出る場合は回転をキャンセルする

コードは動作しますが…テトリミノが回転すると、もう下に降りず、ベースの方向に移動します(つまり、逆さまになっていると上に移動します!)。私はすぐに問題を特定しました:テトリミノの移動はその向きに対して行われているのですが、グリッドの向きに対して移動すべきです。これをChat GPTに説明し、スクリプトを適切に修正してもらいました。その結果、テトリミノは回転後でも正しく移動するようになりました。次に、ピースの積み重ねと、私が通常詰まってしまうステップである、ラインの消去を管理する必要があります…

GameObjectの動きは、GameObjectの向きではなく、ゲームグリッドに対して表現される

積み重ねとラインの管理

テトリスでは、プレイヤーはテトリミノを積み重ねて隙間を作らないようにしようとします。1行が完全に埋まると(10個のセルがテトリミノのブロックで埋まる)、その行は消えて、プレイヤーにポイントが与えられます。複数の行が同時に消えると、乗数が適用され、消えた行はすぐに上の行からブロックで埋められます。私がつまずいているポイントは、まさにこの最後の部分です:以前の試みでは、行を削除する処理がうまくいきませんでした。でも、今日は私の勝利の日です!必ず成功します!
しかし、テトリミノが積み重ねられるようにするためには、まず複数のテトリミノを用意しなければなりません。そして、ゲームプレイの都合上、次に来るテトリミノを表示することにします。シーンには2つのテトリミノが表示され、そのうち1つはゲーム外(キーボードの操作に反応せず、動かない)です。このように「待機中」のテトリミノは、適切なタイミングでゲームに投入され、次のテトリミノに置き換えられます。ロジック的には特に難しいことはありません。
私はまずシーンに2つの空のゲームオブジェクトを配置します:1つはグリッドの上部、中央に配置した「Spawn」、もう1つはスコアとタイトルの間のマージンに配置した「SpawnProchain」です。次に、Chat GPTにテトリミノの「ゲーム中」状態を作成し、前述の説明通りに次のテトリミノを表示するスクリプトをGameManager内に書くように頼みます。そして、この関数をゲーム開始時に呼び出すことも忘れずに行います。今回も得られた結果は迅速で洗練されています。

EnJeuという公開のブール値を作成します。
もしEnJeuがfalseの場合、移動はできません。


Tetriminoの配列t_Tetriminosをプライベートにし、シリアライズ可能にするspawnとspawnProchainの2つのプライベートでシリアライズ可能なGameObjectを追加NouvellePartieというプライベートなブール値を追加し、初期値はtrueにする
公開関数NouveauTetriminoの追加:
もしNouvellePartieがtrueなら:t_Tetriminosからランダムに2つのテトリミノをインスタンス化
最初のテトリミノはspawnの位置にインスタンス化され、EnJeuをtrueにする
2番目のテトリミノはspawnProchainの位置にインスタンス化され、EnJeuをtrueにするNouvellePartieをfalseに設定する
もしNouvellePartieがfalseなら:spawnProchainにあるテトリミノをspawnに移動し、そのEnJeuをtrueにするt_Tetriminosからランダムにテトリミノをインスタンス化し、そのEnJeuをfalseにしてspawnProchainに配置する

論理的には、新しいテトリミノの出現は、現在のテトリミノがゲームのグリッドの「底」または他のテトリミノに触れているときに発生するべきです。したがって、テトリミノが「停止」した状態を判断する必要があります。テトリミノが停止した時、それはもうゲーム内にはいませんし、NouveauTetrimino() 関数が呼ばれます。私は単にテトリミノがグリッドの下に達したときに関数を呼び出して、テトリミノをゲーム外にして動かさないようにすることもできますが、次のステップでテトリミノを停止させ、グリッドの下に達する前に関数を呼び出す必要があることをすでに知っています(別のテトリミノの上に乗ったとき)。必要なことを今から予測しておきます。

プライベートなブール値
pose = falseを追加
ゲームオブジェクトがグリッドの下端に到達したとき:EnJeu = falsePose = true_GMのNouveauTetrimino()関数を呼び出す

そして、私はアプリケーションを起動すると、ひどく話しかけられました:

プログラミング(またはコーディング)は最終的には2つの簡単なことに集約されます:1)ドキュメントを見つけて読む方法を知っていること、2)エラーメッセージを理解することです。この場合、NouveauTetrimino()関数は存在しない配列の要素を呼び出しているようです。そこで、私は間違っている行を見てみます:


確かに、Chat GPTはグリッドの左側にある待機中のテトリミノから、グリッドの上にある実際にゲーム中のテトリミノに切り替えるために、待機中のテトリミノがspawnポイントの子であると考えました。しかし、唯一の小さな問題は、Unityに対して、次に生成されるテトリミノがnextSpawnの子であることを指示していなかったことです。スクリプトはnextSpawnの子供の配列内の要素を探しているのですが、実際にはその配列は空です(もしあなたが何も理解していなければ、それはUnityのドキュメントをしっかり読んでいないからです!)。これがChat GPTの最初の失敗で、罰を受けるべきです!その間に、私はChat GPTに再度リクエストを送るよりも、ロジックを手動で修正する方が簡単だと感じました。だから、私はこっそりスクリプトを直接変更しましたが、それは私たちの小さな秘密です!


この部分の最終ステップは、テトリミノの積み重ねを管理することです。テトリスでは、テトリミノが構成するブロックの一つが下にあるブロックに「触れる」ことで、テトリミノが固定され、空白のスペースが作られ、時には閉じられた空間ができることになります。この空間の管理がゲームプレイの中心です。したがって、各テトリミノが置かれた位置を記録する必要があります。そのために、最も効果的な方法は、アレクセイ・パジトノフが最初に使用した方法である2次元配列(マトリックス)です。基本的な原則は非常に簡単です。ゲームグリッドは10×20のセル(200セル)で構成され、左下が0,0、右上が9,19です。この番号付けが有効なのは、Valemのアドバイスに従って、私は左下を0,0の位置に移動したからです。簡単に言うと、テトリミノは1単位単位で動くため、その構成ブロックは常にグリッド内の1つのセルに「入っている」ことになります。テトリスの「クラシック」なプログラミングは完全にマトリックスベースですが、私たちのプログラミングはハイブリッド型です。マトリックスは移動には使いませんが、テトリミノ同士の「衝突」を管理するために必要です。簡単に言えば、ChatGPTに空のセルがすべて埋まっている2次元配列(グリッド)を作成するよう依頼し、その後、各テトリミノの移動ごとにそのテトリミノが占めるセルをマトリックスに記録させます。テトリミノがゲーム内で使用されなくなったとき、その最後の位置はマトリックスに保存されます。次のテトリミノが移動する前に、目的のセルが空いているかどうかを確認する必要があります。もし空いていなければ、その動きは不可能となり、もし下に動いているなら、テトリミノは固定され、ゲームから外れます。グリッドはGameManagerが管理し、テトリミノの移動はテトリミノによって制御されます。後はそれだけです!まあ、これが理論です。実際には、ChatGPTから欲しいものを手に入れるのに少し苦労しました。幸い、Valemのビデオを参考にすることができたので、ChatGPTが作成したグリッドを手動で修正し、整数ではなくTransformの配列に変更しました(AIが提案した通りではなく)。そして、何度か試行錯誤を重ねた後、ChatGPTに私が望んでいたものを理解させる魔法のようなプロンプトを見つけました。うまく話せば、彼はいい子なんです!

2次元配列のパブリック変数 “Grille” を作成
Grille内の各セルは、0,0 から 9,19 の範囲のセルを表します。
Grilleが作成されるとき、すべてのセルは空です。



ゲームのグリッドは _GM の二次元配列 Grille によって表されます。
プライベート関数 AjoutGrille() を追加します。
AjoutGrille の中で:
GameObject の各子オブジェクトの位置を _GM.Grille に追加します。
GameObject の下方向の移動がブロックされたときに AjoutGrille() を呼び出します。
IsWithinGrid 関数内で:
_GM.Grille の中で GameObject の子オブジェクトが占めているセルが null でない場合、false を返します。

この関数で、ボブはガラスの天井に達しました:テトリスのクローン作成の試みはいつもここで終わり、次のステップに進んだことがありません。それは最終ステップでもあります。今こそ、グラノーラのパックを食べて(勇気を出して)私の宿敵に立ち向かう時です:ラインの削除!
完全なラインの削除
紙の上では、次のように機能します:テトリミノが置かれると、ラインが形成されているかどうかを確認します。そのためには、上から順にすべての行を確認し、各行にnullが含まれているかどうかを確認します。nullが含まれていれば、その行にはラインがありません。それ以外の場合、その行を削除(その行のすべてのケースをnullに設定)し、その上にある行を1行下げます。この方法でValemの方法を適用します。そして、私はこの点についてChat GPTに指示を与えます。

下方向への移動がブロックされたときに呼び出されるプライベート関数
verifierLigne()を作成します。verifierLigne()内で:
上から順に _GM.Grille のすべての行をチェックし、行内のどの要素も null でない場合、プライベート関数effacerLigne()とabaisserLignes()を呼び出します。effacerLigne()内で:
行のすべての要素を null にします。abaisserLignes()内で:
削除された行の上にあるすべての行を 1 ユニット下げます。

ゲームを起動してみたが、すべてうまくいかない T_T。Valemが提案した解決策を忠実に再現したChat GPTの方法では、複数のラインを同時に削除することを考慮していない、もしくはうまく処理できていない。最初のラインを削除した後、削除されたテトリミノはゲームから消えているが、まだ表示されており、他のテトリミノがその上を通過してゲームが見えなくなってしまう。問題の原因をすぐに特定できたのは、Unityを使いこなしてきた経験があるからだ:複数のラインを同時に削除する際、グリッドのビジュアル更新が正しく機能していない。解決策としては2つある。1) アルゴリズムを最適化して、処理が正しい順序で行われるようにするか、2) 各テトリミノのブロックにタグを付けて問題を雑に解決するか。さて、ボブという怠け者が選んだのはどちらだろうか!

effacerLigne()内で、ライン上にある「Bloc」タグを持つすべてのオブジェクトを削除します。

そして…魔法!ボブはついに彼の宿敵を打ち破り、機能するテトリスをプログラミングしました!喜びと幸せ…Valemのチュートリアルで示されたように、ロジックを小さな関数に分割することで、以前の試行でテストした複雑な関数が自己完結する問題を避けることができました。プログラミングではシンプルさがしばしば最良の方法です。ただし、いくつかの小さな改善があれば完璧です。
改善
ゲームのロジックは整っており、私が加えたい小さな改善点はシンプルですが、ゲームの快適さを向上させるはずです:
- ライン削除時の視覚的および音響的フィードバック
- テトリミノの回転および着地時のバックグラウンドミュージックと音響フィードバック
- スコアの更新、レベルと速度の上昇
- ゲームオーバーの管理および音響的フィードバック
- スペースキーによる回転(上矢印キーに加えて)
最初にバックグラウンドミュージックと、回転、ピースの配置、ライン削除、ゲームオーバーのための4つのオーディオクリップをインポートします。あとはChat GPTに仕事を仕上げてもらいますが、ほぼ問題なく進められます。唯一の問題は、ライン削除の視覚的なフィードバックに関して少し怠けていて(空の関数を作成して、それを完成させるように誘導されました…)、私は一行で簡単な方法を作り、ついでにGameManagerのライン数を削除するたびにインクリメントしました。これはAIに頼むのを忘れていたことです。

追加する:
ピースの回転はスペースキーでも行える
回転時に「回転」音を再生する
移動が下方向でブロックされた時、「配置」音を再生する
ラインが削除された時、「削除」音を再生する
ラインが削除された時、ライン全体に白いフラッシュを表示する
ラインが削除された時、_GM.Niveauに10を掛けたものを_GM.Scoreに追加し、_GM.ActualiserUI()を呼び出す




ゲームオーバーの管理は簡単です:テトリミノの下にブロックがあるかどうかを確認します。もしあれば、ゲームを停止し、終了画面を表示します。私はその後、スクリプトを直接変更して音を再生することを追加しました。

毎回のUpdate()の最初で、もしEnJeuがtrueなら、GameObjectの子供の一つが、グリッド内でnullではないセルと同じ位置にあるかどうかを確認します。 もしそうなら、_GM.GameOver()を呼び出します。


最後に、ゲームマネージャーを少し修正して、10ラインごとにレベルを上げ(そして速度も上げる)ようにします。

これで、私はついに遊べるTetrisを完成させ、少し仕上げをしました。改善を続けることもできますが、これは私の体験の目的ではなく、今はその教訓を引き出すことが重要です。
結論

この経験からどんな教訓を得たか?まず第一に、驚くべきことではありませんが、人工知能は賢くないということです。それは非常に興味深いツールであり、良いアシスタントにはなり得ますが、最終的には非常に進化した検索エンジンにすぎません。すべての思考は、AIをコントロールする人間を通じて行う必要があります。Tetrisの場合、以前のAIを使った試みはいつも行き詰まっていました。私は他の人間の仕事、つまりValemのビデオからインスパイアを受けて、自分の間違いを理解し、Chat GPTから望んでいたものを得ることができました。Chat GPTは私の論理的な誤りを決して修正してくれませんでした。とはいえ、一度コンセプトが明確になれば、Chat GPTが書いたスクリプトを手に入れる方が、自分でドキュメントを探してスクリプトを作るよりもずっと速く、効率的です。実際、AIツールボックスを使ってプログラミングを始めてから1年以上経ち、私は多くのことを学びました。自然言語で自分のニーズを人工知能に伝えることで、最初は動作しないことがあっても、自分ではドキュメントから見つけられなかった情報を得ることができます。Chat GPTは速くタイピングし、ミスをしないだけでなく、非常に効率的な発見の手段にもなります。しかし、注意が必要です。プログラミングでAIの利点を活かすためには、まずプログラミングを知っている必要があります。そうでなければ、提案されたスクリプトを評価したり、致命的なエラーを理解して修正することはできません。そして、良い職人が道具を使いこなすように、AIによる支援を受けた優れたプログラマーは、Chat GPTが正しく解釈できるようにプロンプトを適切に書ける人です。それは簡単な仕事ではありません。この記事で提示した要求の少なくとも3分の1を、私は望んでいた結果を得るために言い換えました。AIツールを使い始めて1年以上経っていますが、それでもそうでした。良い実行者であるAIは、常にその作業を設計し、検証する人間が必要です。要するに、私が以前にも書いたように、あなたの仕事を奪うのは人工知能ではなく、それをうまく活用できる人間です。お分かりの方には、よく伝わるでしょう。
ボブ・デュプニュ
ボブは下記の彼の実験結果、TetrIA(ウィンドウをクリックしてアクティブにしてください)を試してみることを提案します。

