Rock, Paper, Scissors. C++ I'm a beginner in programming and I would like to have feedback and tips to improve. He's a simple command line program. It's a Rock, Paper, Scissors game.

I guess I could use an enum for the "Attack", but I don't know how to use it with cout after that...

Thanks!

#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;cstdlib&gt;
#include &lt;ctime&gt;

using namespace std;

enum class Result
{
    win = 1,
    loss = -1,
    tie = 0
};

string ResultToString(Result result)
{
    switch (result)
    {
    case Result::win:
        return "WIN!";
    case Result::loss:
        return "LOSS!";
    default:
        return "TIE!";
    }
}

string DeterminePlay(char playAbbreviation)
{
    if (playAbbreviation == 'r')
    {
        return "Rock";
    }
    else if (playAbbreviation == 'p')
    {
        return "Paper";
    }
    else
    {
        return "Scissors";
    }
}

Result DetermineResult(char playerPlay, char computerPlay)
{
    if (playerPlay == 'r' &amp;&amp; computerPlay == 's')
    {
        return Result::win;
    }
    else if (playerPlay == 'p' &amp;&amp; computerPlay == 'r')
    {
        return Result::win;
    }
    else if (playerPlay == 's' &amp;&amp; computerPlay == 'p')
    {
        return Result::win;
    }
    else if (playerPlay == 's' &amp;&amp; computerPlay == 'r')
    {
        return Result::loss;
    }
    else if (playerPlay == 'r' &amp;&amp; computerPlay == 'p')
    {
        return Result::loss;
    }
    else if (playerPlay == 'p' &amp;&amp; computerPlay == 's')
    {
        return Result::loss;
    }
    else
    {
        return Result::tie;
    }
}

int GenerateRandomNumber(int min, int max)
{
    srand((int)time(0));
    int number{(rand() % max) + min};
    return number;
}

char GenerateComputerPlay()
{
    char computerPlay{};
    int number{GenerateRandomNumber(1, 3)};
    switch (number)
    {
    case 1:
        computerPlay = 'r';
        break;
    case 2:
        computerPlay = 'p';
        break;
    default:
        computerPlay = 's';
    }
    return computerPlay;
}

int main()
{
    setlocale(LC_ALL, "");
    char play{'y'};
    while (play == 'y')
    {
        char computerPlay{};
        char playerPlay{};

        cout &lt;&lt; "--- Rock, Paper, Scissors ---" &lt;&lt; endl &lt;&lt; endl;

        while (playerPlay != 'r' &amp;&amp; playerPlay != 'p' &amp;&amp; playerPlay != 's')
        {
            cout &lt;&lt; "Enter a choice : (R)ock, (P)aper, (S)cissors : ";
            cin &gt;&gt; playerPlay;
            playerPlay = tolower(playerPlay);
        }

        cout &lt;&lt; endl &lt;&lt; "You played " &lt;&lt; DeterminePlay(playerPlay) &lt;&lt; endl;

        computerPlay = GenerateComputerPlay();
        cout &lt;&lt; "The computer played " &lt;&lt; DeterminePlay(computerPlay) &lt;&lt; endl;

        Result result{DetermineResult(playerPlay, computerPlay)};
        cout &lt;&lt; "It's a " &lt;&lt; ResultToString(result) &lt;&lt; endl &lt;&lt; endl;

        cout &lt;&lt; "Play again?" &lt;&lt; endl &lt;&lt; "(Y)es" &lt;&lt; endl &lt;&lt; "(N)o" &lt;&lt; endl;
        cin &gt;&gt; play;
        play = tolower(play);
    }
    return 0;
}
This is a good exercise in doing things in a more data-driven way. This will result in clearer separation of concepts (i.e., game logic) and allow for more customization easily.

So consider (skipping updating the main program):

#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;cstdlib&gt;
#include &lt;ctime&gt;
#include &lt;cctype&gt;
#include &lt;set&gt;
#include &lt;map&gt;

enum Choice
{
    Rock = 1,
    Paper = 2,
    Scissors = 3
};

enum class Result
{
    Win,
    Loss,
    Tie
};

const std::set&lt;std::pair&lt;Choice, Choice&gt; &gt; wins =
{
    { Rock, Scissors },
    { Scissors, Paper},
    { Paper, Rock }
};

const std::map&lt;Result, std::string&gt; result_strings = 
{
    { Result::Win, "WIN!" },
    { Result::Loss, "LOSS!" },
    { Result::Tie, "TIE!" }
};

const std::map&lt;char, std::string&gt; play_abbreviations =
{
    { 'r', "Rock" },
    { 'p', "Paper" },
    { 's', "Scissors" }
};

std::string ResultToString(Result result)
{
    // TODO: Decide how to handle the case of input being unrecognized.
    return result_strings[result];
}

std::string DeterminePlay(char playAbbreviation)
{
    // TODO: Decide how to handle the case of input being unrecognized.
    return play_abbreviations[playAbbreviation];
}

Result DetermineResult(Choice playerPlay, Choice computerPlay)
{
    if (playerPlay == computerPlay)
    {
        return Result::Tie;
    }
    else
    {
        return wins.find(std::make_pair(playerPlay, computerPlay)) != wins.cend() ? Result::Win : Result::Loss;
    }
}

int GenerateRandomNumber(int min, int max)
{
    // TODO: Look at &lt;random&gt; to see how this is done better.
    srand(std::time(0));
    return (rand() % max) + min;
}

Choice GenerateComputerPlay()
{
    const int number = GenerateRandomNumber(1, 3);
    return static_cast&lt;Choice&gt;(number);
}


What we did here was that built the logic of who wins into a data structure, which is essentially a directed graph (more precisely, it's a directed 3-cycle). The winner determination now consist of checking whether the input is an arc in our graph; otherwise it's a loss if no such arc exists and a draw if the arc is a self-loop.

Notice also the possibilities you obtain by a having a result_strings: you could put in more "output texts" for a win for instance, so maybe sometimes you'd like to tell the user "WIN!", but other times you could print "GREAT JOB!" or "NICE!"; that'll end up a nightmare from a maintenance and logic point of view if the number of possible strings grows large.