はじめに
if
を使わずにじゃんけんします。
じゃんけんの結果はC#8の機能の switch式 を使って受け取ります。
先駆者様
個人ブログとのクロスポストです。
勝敗判定
じゃんけんのルールとして、->
の右側が強いものとすると、 Rock
-> Paper
-> Scissors
-> Rock
の関係性が成り立ち、3つの手を周期として勝敗が決まります。
ここで、Rock
を0、Paper
を1、Scissors
を2として、関係性をそれぞれ1の距離を持った有効グラフだとすると、自分の手と相手の手の距離が1では負け、距離が2では勝ち、距離が0(3)ではあいこのような表現することができます。
このことから、相手の手 - 自分の手
を計算することで距離を求めることができます。
しかし、自分の手が2で、相手の手が0だった場合、0 - 2 == -2
のように、距離が負数になってしまいます。このとき、じゃんけんは3つの手を周期としているため、自分の手や相手の手を3つ移動させたところで手は変わらず、勝敗は変わりません。つまり、距離に3を足したり、3で剰余を取ったとしても勝敗は変わりません。このことから、(相手の手 - 自分の手 + 3) % 3
とすることで、距離を0、1、2の3つにすることができ、負数と3以上になることを避けることができます。
実装
Rps
(じゃんけん) クラスに Hand
(グー、チョキ、パー) と Result
(引き分け、負け、勝ち) の enum
を定義することで、Battle
関数の引数と戻り値にそれぞれ意味を持たせます。
C#の enum
は、既定値として int
の0をとり、要素が増えるにつれて1増えます。そのため、この場合は、 Rock (0)
、 Paper (1)
、 Scissors (2)
のようにそれぞれ値を持つことができます。
Battle
関数は、自分の手と相手の手を渡すことで、Result.Draw
、 Result.Lose
、 Result.Win
のいずれかを返します。
public static class Rps
{
public enum Hand
{
Rock,
Paper,
Scissors
}
public enum Result
{
Draw,
Lose,
Win
}
public static Result Battle(Hand own, Hand opponent)
{
var result = ((int)opponent - (int)own + 3) % 3;
return (Result)result;
}
}
呼び出し側では、例に倣ってそれぞれの絵文字を割り当てます。
switch式
を使うことで、Battle
が返す可能性のあるパターンに、 あいこ
、あなたの負け
、あなたの勝ち
を割り当て、一致した要素を result
として受け、自分の手、相手の手と一緒に表示します。 _ => throw new ArgumentOutOfRangeException()
では、対象となる値以外の値として判定された際に該当するアームになります。
public static class Program
{
public static void Main()
{
const string draw = "あいこ";
const string lose = "あなたの負け";
const string win = "あなたの勝ち";
var map = new Dictionary<Rps.Hand, string>
{
[Rps.Hand.Rock] = "✊", [Rps.Hand.Paper] = "🖐", [Rps.Hand.Scissors] = "✌"
};
// var hands = new[] { Rps.Hand.Rock, Rps.Hand.Paper, Rps.Hand.Scissors };
var hands = Enum.GetValues(typeof(Rps.Hand)).Cast<Rps.Hand>().ToArray();
foreach (var own in hands)
foreach (var opponent in hands)
{
// Draw, Lose, Winのままなら
// var result = Rps.Battle(own, opponent).ToString();
var result = Rps.Battle(own, opponent) switch
{
Rps.Result.Draw => draw,
Rps.Result.Lose => lose,
Rps.Result.Win => win,
_ => throw new ArgumentOutOfRangeException()
};
Console.WriteLine($"{map[own]} vs {map[opponent]}: {result}");
}
}
}
実行結果