Rock Paper Scissors without arrays and if-statements, how to reduce As working on a little private programming challenge, I tried "Rock Paper Scissors" without arrays or if-statements. It works as intended, though, I am sure this can be done a little bit more optimized. Especially in the context of Math/Programming.

What I try to achieve:


Create 2 Players, one Computer one Human. 
They both can make a Gesture (Rock, Paper or Scissors at Random or to Choose for the Human Player). 
The value of each Gesture is calculated into a Score 
The calculated Scores are calculated into a Winner of the Duel


The Players are two classes that implement an abstract class.
The Winner and Gesture are Enums with specified values

The random Method just sets a random Gesture value for the player like:

 public void Random() =&gt; _gesture = (Gesture)_random.Next(0, 3);


The score for a single Hand is created as if it were points on a circle at 0, 120 and 240 degrees


((double)(_winner + 1) * 3 + (double)_gesture * 2) % 6 * Math.PI / 3;


The opposite hand is done the same, however, it starts at 180 degrees ( 180, 300, 60 degrees)

I try to find the position of both hands on the circle and calculate that into a unique value that results in a winner.

(Winner)(Math.Round(Math.Sin(other.Score() - this.Score())) * -(int)_winner);


This all works nice, however I suppose that the latter both rules could be reduced.

double Score() =&gt; ((double)(_winner + 1) * 3 + (double)_gesture * 2) % 6 * Math.PI / 3;
public Winner Duel(Player other) =&gt; (Winner)(Math.Round(Math.Sin(other.Score() - this.Score())) * -(int)_winner);


Complete code:

using System;

namespace RockPaperScissors
{
    public enum Winner
    {
        Draw = 0,
        Computer = -1,
        Human = 1
    }

    public enum Gesture
    {
        Rock = 0,
        Paper = 1,
        Scissors = 2,
    }

    public abstract class Player
    {              
        private static readonly Random _random = new Random(DateTime.Now.Millisecond);
        private readonly Winner _winner;  
        protected Gesture _gesture;    

        protected Player(Winner winner)
        {
            _winner = winner;
        }

        public Gesture Gesture =&gt; _gesture;
        public void Random() =&gt; _gesture = (Gesture)_random.Next(0, 3);
        double Score() =&gt; ((double)(_winner + 1) * 3 + (double)_gesture * 2) % 6 * Math.PI / 3;
        public Winner Duel(Player other) =&gt; (Winner)(Math.Round(Math.Sin(other.Score() - this.Score())) * -(int)_winner);
    }

    public class Computer : Player
    {
        public Computer() : base(Winner.Computer)  { }
    }

    public class Human : Player
    {
        public Human() : base(Winner.Human) { }
        public void Choose(Gesture gesture) =&gt; _gesture = gesture;
    }

    class Program
    {

        static void Main(string[] args)
        {
            Computer computer = new Computer();
            Human human = new Human();

            for(int i = 0; i &lt; 10; i ++)
            {
                computer.Random();
                human.Random();

                Console.WriteLine($"Computer does {computer.Gesture}, Human does {human.Gesture}");
                Console.WriteLine($"Winner = {computer.Duel(human)}");
                Console.WriteLine($"Winner = {human.Duel(computer)}");

                Console.ReadLine();
            }
        }
    }
}
This will do

int a = _random.Next(0, 3);
int b = _random.Next(0, 3);
int winner = (a - b + 4) % 3 - 1;


There is no need to subtract angles in radians or degrees as you can simply use integers. Technically a - b is sufficient to determine the winner and + 4 % 3 - 1 wraps it to the -1/0/+1 interval.