[C++] 253 SDL : テトリス画面にベストスコア5つを表示 その1 ChatGPT

[M1 Mac, Monterey 12.6.3, clang 13.0.0, SDL 2.26.2, ChatGPT Plus, NO IDE]

テトリス画面にベストスコア5つを表示するためのxmlファイル作成関数をChatGPTに書かせました。

いともあっさり書いてくれました。検証はしていませんが以下の通りです。おそらく新データは何位であろうと5番目になるはずなので、後で降順ソートが必要でしょう。

ChatGPT Plusは現在月額20ドルですが、今後DAZNのようにハイペースで値上げさせないためにも競合AIの頑張りに期待したいところです。

Q: xmlファイルのentryデータは5個まででscoreが5つの最小値を上回った場合はデータを入れ替える、というコードを書いてください

以下は5つ以下のエントリーがある場合のコードです。

void AddDataToXML(string fileName, string score, string date, string playTime)
{
    // ファイルをパースする
    pugi::xml_document doc;
    pugi::xml_parse_result result = doc.load_file(fileName.c_str());

    if (!result)
    {
        std::cerr << "XMLの読み込みに失敗しました。" << std::endl;
        return;
    }

    // エントリーを格納するノードを取得する
    pugi::xml_node entryNode = doc.child("data").child("entry");

    // 新しいエントリーを作成する
    pugi::xml_node newEntryNode = doc.append_child("entry");
    newEntryNode.append_child("score").text() = score.c_str();
    newEntryNode.append_child("date").text() = date.c_str();
    newEntryNode.append_child("playtime").text() = playTime.c_str();

    // エントリー数をカウントする
    int entryCount = 0;
    for (pugi::xml_node node = entryNode; node; node = node.next_sibling("entry"))
    {
        entryCount++;
    }

    // エントリーが5個未満の場合は新しいエントリーを追加する
    if (entryCount < 5)
    {
        return;
    }

    // スコアが5つの最小値を上回っている場合は新しいエントリーを追加し、古いエントリーを削除する
    pugi::xml_node minScoreNode = entryNode;
    int minScore = std::atoi(entryNode.child_value("score"));
    for (pugi::xml_node node = entryNode.next_sibling("entry"); node; node = node.next_sibling("entry"))
    {
        int scoreVal = std::atoi(node.child_value("score"));
        if (scoreVal < minScore)
        {
            minScoreNode = node;
            minScore = scoreVal;
        }
    }

    if (std::atoi(score.c_str()) > minScore)
    {
        doc.remove_child(minScoreNode);
        doc.append_child(newEntryNode);
    }

    doc.save_file(fileName.c_str());
}

[C++] 252 SDL : テトリス画面に現在時刻と経過時間を表示

[M1 Mac, Monterey 12.6.3, clang 13.0.0, SDL 2.26.2, ChatGPT Plus, NO IDE]

テトリスの画面に現在時刻と経過時間を表示させました。ゲームオーバー時に経過時間をストップさせる仕組みを作るのに一手間掛かりました。メモリを消費する書き方になっていますが、vectorの要素数を常に1個になるようにすれば改善できます。

次はテトロミノのホールド、これから生成するテトロミノの表示あたりでしょうか。このような機能を付けるとかなりヌルくなりますね。

ChatGPTは型推論のautoを多用しますが、使わないよう指示すれば正確な型で書いてくれます。

ここまでプログラミングのハードルが下がるとホビープログラマがかなり増えるのではないでしょうか。あくまで基本を押さえていないと使いこなせないとは思いますが。

extern std::chrono::steady_clock::time_point start;
vector<string> times;

void Game::DrawPlaying( Renderer& renderer )
{
	<中略>

	char text[128];
	snprintf( text, sizeof(text), "Lines: %u", m_numLinesCleared );
	renderer.DrawText( text, 20, 50, 0xffffffff );
	snprintf( text, sizeof(text), "Level: %u", m_level );
	renderer.DrawText( text, 20, 90, 0xffffffff );
	snprintf( text, sizeof(text), "Score: %u", m_score );
	renderer.DrawText( text, 20, 130, 0xffffffff );
	snprintf( text, sizeof(text), "High score: %u", hiScore );
	renderer.DrawText( text, 20, 170, 0xffffffff );

	// 現在日時を取得する
	auto now = std::chrono::system_clock::now();
	auto time_t = std::chrono::system_clock::to_time_t(now);
	std::tm tm = *std::localtime(&time_t);

	// 日時を指定されたフォーマットで文字列に変換する
	std::stringstream ss1;
	ss1 << std::put_time(&tm, "%Y/%m/%d");
	std::string str1 = ss1.str();

	std::stringstream ss2;
	ss2 << std::put_time(&tm, "%H:%M:%S");
	std::string str2 = ss2.str();

	snprintf(text, sizeof(text), "Current time: %s", str1.c_str());
	renderer.DrawText(text, 850, 50, 0xffffffff);

	snprintf(text, sizeof(text), str2.c_str());
	renderer.DrawText(text, 1100, 90, 0xffffffff);

	// 現在時刻を取得する
    std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
	
	// 経過時間を算出する
	std::chrono::milliseconds elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

	// 経過時間を表示する
	if (m_gameState != kGameState_GameOver){
		// 経過時間を"MM:SS"形式で表示する
		snprintf(text, sizeof(text), "Elapsed time: %02d:%02d", elapsed.count() / 1000 / 60, elapsed.count() / 1000 % 60);

		string str(text, text + sizeof(text));
		// cout << "str: " << str << endl;
		times.push_back(str);
		renderer.DrawText(text, 850, 130, 0xffffffff);

	} else {
		string time = times.back();

		// cout << "プレイ時間表示: " << time << endl;
		snprintf(text, sizeof(text), "%s", time.c_str());
		renderer.DrawText(text, 850, 130, 0xffffffff);
	}
}