多人数でのじゃんけん勝敗判定

Q&Aで3人でのじゃんけんの勝敗処理についての質問を見かけたので、自分なりに考えてみました。

多人数での勝敗判定は

- 出された手の種類が2種類の場合のみ勝敗が決定、それ以外はあいこ
- 勝敗が決定する場合はどの手が勝ちか調べ、同じ手を出していたプレイヤーは勝ち、それ以外は負け

こんな感じで判定するのが簡単そうかな、とJavaScriptで作成してみたのが以下。
(Q&AはJavaでの質問でしたが、私はJavaは分かりませんので)

```html:index.html
<!DOCTYPE html>
<html lang='ja'>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>多人数じゃんけんsample</title>
<style>
#computersArea {
  display: inline-flex;
  flex-wrap: wrap;
}
#computersArea div{
  width: 150px;
  margin: 2px;
  padding: 4px;
  background-color: #ddd;
}
.main {
  display: none;
}
#player0 {
  margin-top: 8px;
}
</style>
</head>
<body>
<div class='npSelect'>
  <p>自分を除いた相手プレイヤー(コンピューター)数</p>
  <select id='np'>
    <option value='1'>1</option>
    <option value='2' selected>2</option>
    <option value='3'>3</option>
    <option value='4'>4</option>
    <option value='5'>5</option>
    <option value='6'>6</option>
    <option value='7'>7</option>
    <option value='8'>8</option>
    <option value='9'>9</option>
  </select>人
  <button id='start'>開始</button>
</div>

<div class='main' >
  <div id='computersArea'>
  </div>
  <div>
    <div id='player0'>
    プレイヤー<br>
    &emsp;出した手: <span class='hand'></span><br>
    &emsp;結果: <span class='result'></span><br>
    &emsp;勝数: <span class='winCount'>0</span><br>
    <button value='0'>グー</button>
    <button value='1'>チョキ</button>
    <button value='2'>パー</button>
    </div>
  </div>
</div>

<script>
'use strict';

const obj = {
  players: [],
};

// 相手人数選択 ～ 初期設定
document.getElementById('start').addEventListener('click', () => {
  const np = + document.getElementById('np')?.value ?? 1;

  obj.players = [];
  for(let i = 0; i <= np; i++) {
    obj.players[i] = {
      winCount: 0,
    };
  }

  document.querySelector('.npSelect').style.display = 'none';
  document.querySelector('.main').style.display = 'block';

  const comArea = document.getElementById('computersArea');
  comArea.innerHTML = '';
  for(let i = 1; i <= np; i++) {
    document.getElementById('computersArea').insertAdjacentHTML('beforeend', `
      <div id='player${i}'>
        コンピューター ${i}<br>
        &emsp;出した手: <span class='hand'></span><br>
        &emsp;結果: <span class='result'></span><br>
        &emsp;勝数: <span class='winCount'>0</span><br>
      </div>
    `);
  }

  for(const button of document.querySelectorAll('#player0 button')) {
    button.addEventListener('click', () => {
      judge(+button.value);
    })
  }
});

// 勝敗判定
const judge = n => {
  const handsCheck = [0, 0, 0];

  // 自分の出した手
  obj.players[0].hand = n;
  handsCheck[n]++;

  // コンピューターの手をランダムに決定
  for(let i = 1; i < obj.players.length; i++) {
    const hand = Math.floor(Math.random() * 3);
    obj.players[i].hand = hand;
    handsCheck[hand]++;
  }

  // 全プレイヤーで出された手の種類数
  const numberOfHandTypes = handsCheck.filter(v => v !== 0).length;

  // 2種類の場合は勝敗決定
  if(numberOfHandTypes === 2) {
    const hands = [];
    for(const n in handsCheck) {
      if(handsCheck[n] > 0) hands.push(+n);
    }

    // '勝ち'の手を決定
    const winHand = (3 + hands[1] - hands[0]) % 3 === 1 ? hands[0] : hands[1];

    // 勝敗結果を各プレイヤーに反映
    for(let i = 0; i < obj.players.length; i++) {
      const p = obj.players[i];
      const flag = p.hand === winHand;
      p.result = flag ? 1 : 2;
      if(flag) p.winCount++;
    }
  }
  // 2種類以外の場合は引き分け
  else {
    for(let i = 0; i < obj.players.length; i++) {
      obj.players[i].result = 0;
    }
  }

  // 表示反映
  for(let i = 0; i < obj.players.length; i++) {
    const d = document.getElementById('player' + i);
    d.querySelector('.hand').textContent = ['グー', 'チョキ', 'パー'][obj.players[i].hand];
    d.querySelector('.result').textContent = ['あいこ', '勝ち', '負け'][obj.players[i].result];
    d.querySelector('.result').style.color = ['black', 'blue', 'red'][obj.players[i].result];
    d.querySelector('.winCount').textContent = obj.players[i].winCount;
  }
};
</script>
</body>
</html>
```

####[実動デモ](https://akebi.jp/temp/multiplayer_rps.html)####

想定通り動いているようですが、多人数での勝敗判定を考えるのが目的でしたので、負けたプレイヤーが脱落する勝ち抜きや、最初に何勝したプレイヤーが優勝、といった処理はありません。