[C++] 256 SDL : テトリス画面にベストスコア5つを表示 その4 CSVファイル更新

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

テトリスのプレイ記録をCSVファイルに保存し、起動時・リスタート時にスコアベスト5を表示するようにしました。XMLでの苦労とは打って変わってのイージーモードでした。

これで最低限の機能を実装しました。ホールド機能などのワールドルールに準拠するかどうかはこれから考えます。

ネット麻雀の待ち牌表示やツモ切り表示のようなヌルい機能はいらない派なので多分実装しないでしょう。

struct Entry {
    int score;
    string date;
    string playtime;
};

vector<Entry> ReadCSV(const string& filename) {
    vector<Entry> entries;

    std::ifstream infile(filename);
    if (!infile) {
        cerr << "Failed to open file: " << filename << endl;
        return entries;
    }

	std::string line;
    std::getline(infile, line); // ヘッダ行を読み飛ばす
    while (std::getline(infile, line)) {
        std::istringstream iss(line);
        std::string score_str, date, playtime;
        std::getline(std::getline(iss, score_str, ','), date, ',');
        std::getline(iss, playtime, ',');
        int score = std::stoi(score_str);
        entries.push_back({score, date, playtime});
    }

    return entries;
}

int GetScoreAndDate() {
	vector<Entry> entries = ReadCSV(csvFile);

    // スコアで降順ソート
    sort(entries.begin(), entries.end(),
              [](const Entry& a, const Entry& b) { return a.score > b.score; });

    // 上位5件を取得して、スコアと日付をvectorに格納
    for (int i = 0; i < std::min(5, static_cast<int>(entries.size())); ++i) {
        scores.push_back(entries[i].score);
        string date = entries[i].date;
		replace(date.begin(), date.end(), '-', '/');
		dates.push_back(date.substr(5, 5));
    }

    return 0;
}

void CopyFile(const std::string& src_file, const std::string& dst_file) {
    std::ifstream src(src_file, std::ios::binary);
    std::ofstream dst(dst_file, std::ios::binary);
    dst << src.rdbuf();
}

void AddDataToCSV()
{
	std::ofstream outfile(csvFile, std::ios_base::app); // ファイルを追記モードで開く
    if (!outfile) {
        cerr << "Failed to open file: " << csvFile << endl;
        return;
    }

    outfile << m_score << "," << startTime << "," << elapsedTime << endl;

	// バックアップを作成する
    if (fs::exists(csvFile)) {
        CopyFile(csvFile, csvFileBackup);
    }
}

[C++] 255 SDL : テトリス画面にベストスコア5つを表示 その3 CSVファイル読み込み ChatGPT

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

テトリスのプレイ記録をCSVファイルにまとめ、起動時にこれを読み込んでスコアのベスト5を表示させるようにします。

まずテスト用のCSVファイルについて、これを読み込んで必要なデータをvectorにまとめるコードをChatGPTに書いてもらいました。

内容を検証したところ正常に動作して、最後にvectorの内容を出力してくれるという120点の出来でした。ハマると素晴らしいコードを書いてくれます。

Q:
score,date,playtime
0,2020-03-01 14:20:30,25:00
800,2020-03-03 19:10:45,20:30
500,2020-03-07 08:15:20,15:00
300,2020-03-01 15:22:00,12:30
20,2020-02-20 23:55:09,10:00
1000,2020-02-07 23:55:09,10:00 
C++でこのcsvファイルを読み込み、scoreで降順ソートして上位5件のscoreと月/日をそれぞれvector<int>,vector<string>にして下さい。

以下は、与えられたCSVファイルを読み込み、スコアで降順ソートして上位5件のスコアと日付(月/日)をそれぞれvector<int>とvector<string>に格納するサンプルコードです。

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>

struct Entry {
    int score;
    std::string date;
    std::string playtime;
};

// CSVファイルを読み込み、各行をEntry構造体に変換してvectorに格納する
std::vector<Entry> ReadCSV(const std::string& filename) {
    std::vector<Entry> entries;

    std::ifstream infile(filename);
    if (!infile) {
        std::cerr << "Failed to open file: " << filename << std::endl;
        return entries;
    }

    std::string line;
    std::getline(infile, line); // ヘッダ行を読み飛ばす
    while (std::getline(infile, line)) {
        std::istringstream iss(line);
        std::string score_str, date, playtime;
        std::getline(std::getline(iss, score_str, ','), date, ',');
        std::getline(iss, playtime, ',');
        int score = std::stoi(score_str);
        entries.push_back({score, date, playtime});
    }

    return entries;
}

int main() {
    std::vector<Entry> entries = ReadCSV("scores.csv");

    // スコアで降順ソート
    std::sort(entries.begin(), entries.end(),
              [](const Entry& a, const Entry& b) { return a.score > b.score; });

    // 上位5件を取得して、スコアと日付をvectorに格納
    std::vector<int> top_scores;
    std::vector<std::string> dates;
    for (int i = 0; i < std::min(5, static_cast<int>(entries.size())); ++i) {
        top_scores.push_back(entries[i].score);
        std::string month_day = entries[i].date.substr(5, 5);
        dates.push_back(month_day);
    }

    // 結果を出力
    std::cout << "Top 5 scores:" << std::endl;
    for (int i = 0; i < static_cast<int>(top_scores.size()); ++i) {
        std::cout << top_scores[i] << ", " << dates[i] << std::endl;
    }

    return 0;
}

上記のコードを実行すると、出力結果が表示されます。

Top 5 scores:
1000, 02-07
800, 03-03
500, 03-07
300, 03-01
20, 02-20