(C#) if文なしでじゃんけん

# 元ネタ
https://qiita.com/ri_/items/5c73dca33cc8401c2600

https://qiita.com/tadsan/items/65d91ba6b50535fc8815

# 概要
剰余算(%)を活用して、**if文なしでの ``勝敗の判定``** を行う。

剰余算(%)を活用すると、値を円環させた形で値を範囲内に丸めることが出来る。簡単で非常に便利で、応用方法もたくさんあるので、布教の意味も含めて兼ねて書いてみた。

# 剰余算による対戦結果表
 ぶっちゃけExcelでテストした(笑)

|player|pc (cpu)  |calc   |result |mod (result) |output (label)|
|:-------|:-------|:------|:------|:------------|:-------------|
|0 (✊)  |0 (✊)  |0 - 0  |0      |**0**        |[0] あいこ     |
|0 (✊)  |1 (✌)  |0 - 1  |-1     |**2**        |[2] 勝ち       |
|0 (✊)  |2 (🖐)  |0 - 2  |-2    |**1**         |[1] 負け       |
|1 (✌)  |0 (✊)  |1 - 0   |1     |**1**         |[1] 負け       |
|1 (✌)  |1 (✌)  |1 - 1   |0     |**0**         |[0] あいこ     |
|1 (✌)  |2 (🖐)  |1 - 2  |-1    |**2**         |[2] 勝ち       |
|2 (🖐) |0 (✊)   |2 - 0  |2     |**2**         |[2] 勝ち       |
|2 (🖐) |1 (✌)   |2 - 1  |1     |**1**         |[1] 負け       |
|2 (🖐) |2 (🖐)   |2 - 2  |0     |**0**         |[0] あいこ    |

* 2つの手の差のベクトルを自然数に正規化して、テーブルにマッピングさせるイメージ。
* ``あいこ``、 ``負け``、``勝ち``、の3パターンのため、3の余りを求めて、``0 ～ 2`` に丸める。
* マイナスの場合は ``除数`` を加えてプラス化さてから余りを求めることで、円環位置をズらさず丸める。

※ ExcelのMOD関数は、はなっからプラス側で値を返すとか、面倒くさいなお前。

# ソース
## ソース (ピックアップ)
```cs:ピックアップ
private static int GetResult(int palyer_hand, int pc_hand) {
    // (1) 基となる差を求める。
    int result = palyer_hand - pc_hand;
    // (2) 除数であまりを求め、±除数の範囲に収める。
    result %= 3;
    // (3) 除数を1回加えることでプラス化。
    result += 3;
    // (4) 再度除数であまりを求め、+除数の範囲に収める。
    result %= 3;
    return result;
}
```

## ソース (全体)
@ri_ さんに倣って、入力想定文字列は ``グー`` 、 ``チョキ`` 、 ``パー``。
@tadsan さんに習って、出力は絵文字に置き換え。
 (+ 検証用に総当りで結果を出力)

* if文なしでじゃんけん(C#) - paiza.IO
https://paiza.io/projects/SDonsIDtCzfYQh6O_lXVbg


* Ideone.com
https://ideone.com/OuRqbr

```CS:C&#x23;
using System;
using System.Collections.Generic;

public class Hello{
    private static readonly Dictionary<string, int> HAND_CODE_DICT = new Dictionary<string, int>() {
        {"グー", 0},
        {"チョキ", 1},
        {"パー", 2},
    };
    private static readonly string[] HAND_LABELS = new string[] {"✊", "✌", "🖐"};
    private static readonly string[] RESULT_LABELS = new string[] {
        "あいこ",
        "あなたの負け",
        "あなたの勝ち"
    };

    private static int GetResult(int palyer_hand, int pc_hand) {
        int result = palyer_hand - pc_hand;
        // -3 < n < 3
        result %= 3;
        // 0 < n < 6
        result += 3;
        // 0 <= n < 3
        result %= 3;
        return result;
    }
    
    public static void Main(){
        // Your code here!
        System.Console.WriteLine("Hellow C#");
    
        foreach(string player_hand in new string[]{"グー", "チョキ", "パー"}) {
            foreach(string pc_hand in new string[]{"グー", "チョキ", "パー"}) {
                int player_hand_code = HAND_CODE_DICT[player_hand];
                int pc_hand_code = HAND_CODE_DICT[pc_hand];
                int result_code = GetResult(player_hand_code, pc_hand_code);
                System.Console.WriteLine(string.Format("[{0} v.s. {1}] {2}", new object[] {
                    HAND_LABELS[player_hand_code],
                    HAND_LABELS[pc_hand_code],
                    RESULT_LABELS[result_code],
                }));
            }
        }
    }
}
```
```text:output
Hellow C#
[✊ v.s. ✊] あいこ
[✊ v.s. ✌] あなたの勝ち
[✊ v.s. 🖐] あなたの負け
[✌ v.s. ✊] あなたの負け
[✌ v.s. ✌] あいこ
[✌ v.s. 🖐] あなたの勝ち
[🖐 v.s. ✊] あなたの勝ち
[🖐 v.s. ✌] あなたの負け
[🖐 v.s. 🖐] あいこ
```

# あとがき
剰余算の活用は、ゲーム系では昔から結構使われるんじゃないかな。シンプルな算術演算のためCPUコストも少なく。コードも複雑にはならないので、結構美味しいテクニック。

私が今まで剰余算をよく使ったのは。

1. キャラクターのアニメーションのループ
2. メニュー画面などでの、画面選択肢のループ
3. キャラクターの向き(角度)のループ
4. テーブル表示で行を交互に色付け

業務系ではあんま活用したいシーンがない様で。(4)で剰余算使っていたときに、年配のSEに驚かれたことがある。

なお、『``連想配列はズルくない？``』とも思ったけど、まぁご愛嬌で。(入力文字列をコード化するしてるだけだから許して)

そう言えば、『``計算機は計算が得意``』 で 『``条件分岐は苦手``』と言う定説は昔からあるけど。コスト的には何倍あるのだろう？:thinking: