0

データを取得する必要のある構造体の配列があります。配列は名前とスコアを保持します。

1つの関数について、最高のスコアと関連付けられた名前を出力する必要があります。複数の場合がある場合は、すべての名前を出力する必要があります。

ベクトルやリストを使用できません。(そうでない場合)同じステップで両方のアクションを実行したいだけです。

これが私がそれを処理する方法です:

void highScorer (  player array[], int size )
{ // highScorer

    int highScore = 0; //variable to hold the total score

    // first loop determines highest score
    for ( int i = 0; i < size; i++ ) {

        if ( array[i].pointsScored > highScore ) {
            highScore = array[i].pointsScored;            
        }
    }
    cout << "\nThe highest scoring player(s) were:\n";
    // second loop finds players with scores matching highScore and prints their name(s)
    for ( int i = 0; i < size; i++ ) {
        // when a match is found, the players name is printed out
        if ( array[i].pointsScored == highScore ) {
            cout << array[i].playerName;
            cout << ", scored ";
            // conditional will output correct grammar
            if ( array[i].pointsScored > 1 ) {
                cout << array[i].pointsScored << " points!\n";
            }
            else {
                cout << array[i].pointsScored << " point!\n";
            }
        }
    }
    cout << "\n"; // add new line for readability
    return;

} // highScorer

これをforループに凝縮したいと思います。誰かがさらに効率的な方法の提案を持っていない限り。データの並べ替えは不要だと思います。さらに、ソートされている場合、1つのステップで複数の「highScore」ケースがあったかどうかをどのように判断できますか。

4

6 に答える 6

3

highScore変数に加えて、たとえば a std::list(または、使用が許可されているものに応じて、手動のリンクされたリストまたは小さな配列) などの 2 番目の変数を作成します。このリストでは、現在のハイスコアを実際に持っている人のインデックスを追跡します。新しいハイスコアが見つかった場合は、そのリストをクリアして、新しいハイスコアを持つ人を追加します。ハイスコ​​アを持っている人が見つかった場合は、その人をリストに追加するだけです。

次に、ループした後、誰がハイスコアを持っているかを再度調べるのではなく、このリストのインデックスを使用してプレーヤーを出力するだけで済みます。

于 2012-09-10T22:18:40.747 に答える
2

解決策の 1 つは、ハイ スコアを検索するときにプレーヤーの名前を記録することです。現在のハイスコアと等しい場合は、追加の名前を「名前のコレクションの文字列」に追加し、それよりも高い場合は名前を空白にして、新しいハイスコアと新しい名前も記録します. ostringstreamバッファを超えないようにするために、名前の出力を として実装します。完了したら、一連の名前を印刷します。

于 2012-09-10T22:19:50.570 に答える
1

最初の (唯一の) パスを通過する限り、最高スコアの一連のインデックスを保持します。完了すると、その最高スコアに対応する一連のインデックスが既に作成されています。私が作成したばかりの言語の擬似コードでは、次のようになります。

int highestSoFar = 0;
list indexesOfHighScore = new list();

for (int i = 0; i < scores.count; i++) {
    if (scores[i] > highestSoFar) {
        highestSoFar = scores[i];
        indexesOfHighScore.empty();
    }
    if (scores[i] == highestSoFar) {
        indexesOfHighScore.add(i);
    }
}

// Now I know the highest score, and all the indexes of entries that correspond to it.

動的リストを使用できない場合は、リストが常に十分な大きさになるように、スコア配列と同じサイズの静的配列にすることができます。

于 2012-09-10T22:20:32.193 に答える
1

現在、最初のループはハイスコアを追跡しています。一致するすべての名前も追跡している場合は、ループが終了したときに名前を出力できます。これらの名前を調べるには 2 番目のループが必要ですが、これは避けられません。

于 2012-09-10T22:21:59.537 に答える
1

ストレージのわずかなコストで、ハイスコアとそれぞれのプレーヤーを同じパスで計算できます。

player ** highScorer (  player array[], int size )
{
    player ** result = new player*[size + 1]; // The +1 handles the case where everyone ties

    int highScore = 0;
    int foundAt = 0;

    for ( int i = 0; i < size; i++ )
    {
        if ( array[i].pointsScored > highScore )
        {
            highScore = array[i].pointsScored;
            foundAt = 0;
        }

        if ( array[i].pointsScored == highScore )
        {
            result[foundAt] = &(array[i]);
            foundAt++;
        }
    }

    result[foundAt] = null; // Stopping condition, hence the +1 earlier

    return result; // Remember to delete[] the resulting array
}

でも。

それはあなたに出力を与えません。結果を出力したい場合は、まだ 2 番目のループが必要です。

void outputScores ( player ** result )
{
    cout << "\nThe highest scoring player(s) were:\n";

    for ( int i = 0; result[i] != null; i++ )
    {
        cout << result[i]->playerName;
        cout << ", scored ";
        if ( result[i]->pointsScored == 1 )
            cout << "1 point!\n";
        else
            cout << result[i]->pointsScored << " points!\n";
    }

    cout << "\n";

    delete [] result;
}

元の質問に答えるために、単一のループで高得点を持つすべてのプレーヤーを見つけ出力する方法はまったくないと思います。スコア配列を事前に並べ替えても、既に持っているものよりも悪いでしょう。

于 2012-09-10T22:52:40.390 に答える
0

一致するインデックスの完全なセットを保持するのではなく、最初と最後だけを保持します。これにより、リスト全体の検索をスキップでき、一意の最高スコアがある場合に 2 番目のパスを完全に回避できます。

void highScorer( player* array, int size )
{
    int highScore = 0;
    int firstHighI = -1, lastHighI = -1;

    for ( int i = 0; i < size; i++ ) {  
        if ( array[i].pointsScored > highScore ) {
            highScore = array[i].pointsScored;
            firstHighI = i;
        }
        if ( array[i].pointsScored == highScore ) {
            lastHighI = i;
        }
    }

    if (firstHighI >= 0) {
        std::cout << "\nThe highest scoring player(s) were:\n";
        for ( int i = firstHighI; i < lastHighI; i++ ) {
            if ( array[i].pointsScored == highScore ) {
                std::cout << array[i].playerName << ", ";
            }
        }

        std::cout << array[lastHighI].playerName << " with a score of " << highScore;
        if ( highScore != 1 ) {
            std::cout << " points!\n";
        }
        else {
            std::cout << " point!\n";
        }
    }
    std::cout << "\n";
}
于 2012-09-10T22:30:26.820 に答える