Rock/Paper/Scissors using C#
My take on this:

For console apps, I like to use a more OOP approach.

A Message class to hold a string array to handle a multiline message, and if the message requires a response a string of the characters allowed, will allow you to replace all those string literals with named variables:

class Message
{
    public String[] message { get; }
    public String choices { get; }
    public Message()
    {
        message = new String[0];
        choices = "";
    }
    public Message(String choices, params String[] message)
    {
        this.message = message;
        this.choices = choices.ToLower();
    }
}


To compliment this class, a static storage class(Messages) to put names to the various messages that will be required.  I put a simple print method in there as well:

static class Messages
{
    public static Message startMessage = new Message("", "Welcome to RockScissorPaper");
    public static Message instructions = new Message("", "When you're ready to play, press the desired number.",
            "The computer will reveal its choice and who won.");
    public static Message rockWins = new Message("", "Rock breaks Scissors.", "Rock wins.");
    public static Message scissorsWins = new Message("", "Scissors cuts Paper.", "Scissors wins.");
    public static Message paperWins = new Message("", "Paper covers Rock.", "Paper wins.");
    public static Message playAgain = new Message("yn\n", "Would you like to play again?(y/n)");
    public static Message continuePlay = new Message("", "Press any key to continue.");
    public static Message choices = new Message("0123", "1 - Rock", "2 - Scissors", "3 - Paper", "0 - Quit", "\nWhich do you choose?");
    public static Message goodbye = new Message("", "Thank you for playing.  Goodbye.");
    public static Message tie = new Message("", "A tie.  You both chose the same.");
    public static Message wrongChoice = new Message("", "You made a wrong choice.  Try again.");

    public static void PrintMessage(TextWriter tOut, Message message)
    {
        tOut.WriteLine();
        foreach (var s in message.message)
        {
            tOut.WriteLine(s);
        }
    }
}


This approach makes it very easy, with minimal refactoring, to create language choices for your app.

For classes that require I/O, I like to keeps things flexible and use base classes instead of hard coding standard I/O.  This makes it very easy to leverage networking at some point.

For the game class(RockScissorPaper), a method to get the user's input, clears a lot of code from the PlayGame method.

private static char GetChoice(TextWriter tOut, TextReader tIn, Message message)
{
    char choice = '\0';
    bool done = false;
    do
    {
        Messages.PrintMessage(tOut, message);
        string response = tIn.ReadLine().ToLower();
        choice = response.Length &gt; 0 ? response[0] : '\n';
        if (message.choices.Contains(choice))
        {
            return choice;
        }
        Messages.PrintMessage(tOut, Messages.wrongChoice);
    } while (!done);
    return choice;
} 


I find an enum for the different states of the game, helps with the decision process to decide a winner:

private enum State
{
    None = 0,
    Tie = 1,
    Rock = 3,
    Scissors,
    Paper
}


Notice the Rock constant starts at 3. This allows simple math and one conditional to decide which player is the winner. Once the winner is decided the switch block to select which message to display is very simple:

private static Message GetWinner(State comp, State player)
{
    if (comp == State.None || player == State.None)
    {
        throw new ArgumentOutOfRangeException("Both 'comp' and 'player' must be 'Rock', 'Scissors' or 'Paper'.");
    }
    int cmptr = (int)comp;
    int plyr = (int)player;
    State winner = State.None;
    if (player == comp)
    {
        winner = State.Tie;
        plyrScore++;
        compScore++;
    }
    else if(plyr % 3 == (cmptr - 1) % 3)
    {
        winner = player;
        plyrScore += 2;
    }
    else
    {
        winner = comp;
        compScore += 2;
    }
    switch (winner)
    {
        case State.Tie:
            return Messages.tie;
        case State.Rock:
            return Messages.rockWins;
        case State.Scissors:
            return Messages.scissorsWins;
        case State.Paper:
            return Messages.paperWins;
        default:
            return new Message("", "");
    }
}


I've incorporated the score calculation here, as well.  I noticed you scored a tie  the same a win.  Typically a tie is considered half a win.  I would prefer to see a win at 2 points and a tie at 1.

With these helper methods done, the game play is almost trivial to code:

static class RockScissorsPaper
{
    private static RandomEngine rnd = new RandomEngine();
    private enum State
    {
        None = 0,
        Tie = 1,
        Rock = 3,
        Scissors,
        Paper
    }
    static int plyrScore = 0;
    static int compScore = 0;
    public static void PlayGame(TextWriter tOut, TextReader tIn, String name, int rounds)
    {
        plyrScore = 0;
        compScore = 0;
        Messages.PrintMessage(tOut, Messages.startMessage);
        for(int round = 0; round &lt; rounds; ++round)
        {
            Messages.PrintMessage(tOut, Messages.instructions);
            int choice = GetChoice(tOut, tIn, Messages.choices) - '0';
            State compChoice = (State)Enum.GetValues(typeof(State)).GetValue((rnd.Next(0, 300) % 3) + 2);
            State playerChoice = (State)(choice + 2);
            tOut.WriteLine($"The player chose {playerChoice}.\nThe computer chose {compChoice}.");
            Messages.PrintMessage(tOut, GetWinner(compChoice, playerChoice));
            tOut.WriteLine($"The score is:\n{name} - {plyrScore}\nComputer - {compScore}");
            Messages.PrintMessage(tOut, Messages.continuePlay);
            tIn.Read();
        }

    }

    private static char GetChoice(TextWriter tOut, TextReader tIn, Message message)
    {
        char choice = '\0';
        bool done = false;
        do
        {
            Messages.PrintMessage(tOut, message);
            string response = tIn.ReadLine().ToLower();
            choice = response.Length &gt; 0 ? response[0] : '\n';
            if (message.choices.Contains(choice))
            {
                return choice;
            }
            Messages.PrintMessage(tOut, Messages.wrongChoice);
        } while (!done);
        return choice;
    }
    private static Message GetWinner(State comp, State player)
    {
        if (comp == State.None || player == State.None)
        {
            throw new ArgumentOutOfRangeException("Both 'comp' and 'player' must be 'Rock', 'Scissors' or 'Paper'.");
        }
        int cmptr = (int)comp;
        int plyr = (int)player;
        State winner = State.None;
        if (player == comp)
        {
            winner = State.Tie;
            plyrScore++;
            compScore++;
        }
        else if(plyr % 3 == (cmptr - 1) % 3)
        {
            winner = player;
            plyrScore += 2;
        }
        else
        {
            winner = comp;
            compScore += 2;
        }
        switch (winner)
        {
            case State.Tie:
                return Messages.tie;
            case State.Rock:
                return Messages.rockWins;
            case State.Scissors:
                return Messages.scissorsWins;
            case State.Paper:
                return Messages.paperWins;
            default:
                return new Message("", "");
        }
    }
}