名前ビンゴゲームで良い感じのソフトが無かったのでスプレッドシートとGoogle Apps Scriptで作った

# 名前ビンゴゲームとは

[名前ビンゴゲームとは](https://www.google.com/search?q=%E5%90%8D%E5%89%8D%E3%83%93%E3%83%B3%E3%82%B4%E3%82%B2%E3%83%BC%E3%83%A0%E3%81%A8%E3%81%AF)

ビンゴゲームの数字の代わりに人名をマス目に書いておき、用意した任意の人名を取り上げてマス目を埋めていくゲーム。

自分の名前を真ん中にしたり、人名の縛りを今年入社した人にしたりする。

# 事の発端

弊社での忘年会でよく行なっており、いつもは300円くらいの手動ビンゴマシンをくるくるやっていた様子で、
今年は忘年会会場にプロジェクタがあるので投影してできたら良いよね。となったは良いけれど、いい感じの名前ビンゴ用のソフトが転がっていなかった。
ま、作れば良いか。となって作った。

# スクリプトの内容

- スプレッドシート実物： https://docs.google.com/spreadsheets/d/1jR9p6zF20RlGWNompLvxYd6_9XPlDwbKaW7kwUFRY20/edit?usp=sharing
  - まずは上記リンクからシートをみなさんのマイドライブ等にコピーしてください
  - コピーの仕方：[ファイル]→[コピーを作成]を選択してお好きな場所にコピーしてください。

- スクリプトの在り処
  - スプレッドシートの[ツール]→[スクリプトエディタ]で見れます。

- 実装
  - 以下の3ファイルで実装していました。
    - start.gs:抽選を行い、結果を管理するスクリプト
    - reset.gs:結果や体裁を初期化するスクリプト
    - ui.gs:スプレッドシート上から操作できるようにUIメニューを追加するスクリプト

```js:start.gs
function START() {
  // 要素全てを取得
  var all_item_sheet = SpreadsheetApp.getActive().getSheetByName('数字要素リスト');
  var all_item_data = all_item_sheet.getDataRange().getValues();
  // 数字と要素の辞書を取得
  var num_item_dic = get_num_item_dic(all_item_sheet);
  // 数字と結果を表示するシートを取得
  var bingo_sheet = SpreadsheetApp.getActive().getSheetByName('ビンゴ');

  // 残り要素数を取得
  var item_counter = Object.keys(num_item_dic).length;
  // 残り要素がなければ[おわり]を表示
  if(item_counter == 0) {
    set_bingo_value(bingo_sheet, 'おわり');
    return;
  }
  
  // ランダムに数字を1つ選択
  var random_id = parseInt(Math.floor(Math.random() * item_counter));
  // 数字から要素を取得
  var item = num_item_dic[random_id];
  // 結果を表示するシートに要素を表示
  set_bingo_value(bingo_sheet, item);
  // 取得済み要素にカウンタを入れる
  set_done(all_item_sheet, item);
  // 結果をシートに列挙する
  var counter = all_item_data.length - item_counter;
  show_result(bingo_sheet,counter, item);
}

// 結果をビンゴ表示シートに表示する
function show_result(bingo_sheet, counter, item) {
  // 結果シートに結果を書き出し
  var result_sheet = SpreadsheetApp.getActive().getSheetByName('結果');
  var lastRow = result_sheet.getLastRow();
  result_sheet.appendRow([counter, item]);
  
  var result_data = result_sheet.getDataRange().getValues();
  var result_range = bingo_sheet.getRange('H1:I' + result_data.length);
  
  result_range.setValues(result_data)
    .setHorizontalAlignment('center')
    .setFontSize(15);
}

// 選ばれた要素に済を入れる
function set_done(num_item_sheet, name) {
  var num_item_data = num_item_sheet.getDataRange().getValues();
  var num_item_dic = {}
  for(i = 1; i < num_item_data.length; i++) {
    if(num_item_data[i][1] == name){
      num_item_sheet.getRange(i + 1, 3).setValue('済');
      break;
    }
  }
}

// 名前と要素の対応情報を取得
function get_num_item_dic(all_item_sheet) {
  var num_name_data = all_item_sheet.getDataRange().getValues();
  var num_name_dic = {}
  var counter = 0
  for(i = 1; i < num_name_data.length; i++) {
    if(num_name_data[i][2] == '済') {
      continue;
    }
    num_name_dic[counter] = num_name_data[i][1];
    counter++;
  }
  return num_name_dic;
}

// ビンゴの表示部分
function set_bingo_value(bingo_sheet, value){
  var range = bingo_sheet.getRange('A1:F24');
  range.setBackground('black');           // 黒背景
  range.setFontColor('white');            // 白文字
  range.setFontSize(144);                 // 文字の大きさ
  range.setHorizontalAlignment('center'); // 中央揃え
  range.setVerticalAlignment('middle');   // 中央寄せ
  range.setValue(value);
}
```

```js:reset.gs
// 初期化
function reset() {
  // ビンゴシートをスタート表記にする
  var bingo_sheet = SpreadsheetApp.getActive().getSheetByName('ビンゴ');
  var range = bingo_sheet.getRange('A1:F24');
  range.setBackground('black');           // 黒背景
  range.setFontColor('white');            // 白文字
  range.setFontSize(144);                 // 文字の大きさ
  range.setHorizontalAlignment('center'); // 中央揃え
  range.setVerticalAlignment('middle');   // 中央寄せ
  range.setValue('START');
  
  bingo_sheet.getRange('H2:I1000').clear();
  
  // 済マークを消す
  var num_item_sheet = SpreadsheetApp.getActive().getSheetByName('数字要素リスト');
  var num_item_data = num_item_sheet.getDataRange().getValues();
  for(i = 1; i < num_item_data.length; i++) {
    num_item_sheet.getRange(i + 1, 3).setValue('');
  }
  
  // 結果を消す
  var result_sheet = SpreadsheetApp.getActive().getSheetByName('結果');
  var result_data = num_item_sheet.getDataRange().getValues();
  for(i = 1; i < result_data.length; i++) {
    result_sheet.getRange(i + 1, 1).setValue('');
    result_sheet.getRange(i + 1, 2).setValue('');
  }
}
```

```js:ui.gs
// スプレッドシートが開かれたら自動的に実行される関数
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('[BINGO]')
    .addItem('スタート!!', 'START')
    .addSeparator()
    .addSubMenu(
      ui.createMenu("初期化メニュー")
        .addItem('初期化実行', 'reset'))
    .addToUi();
}
```

# 各シートの説明

- コピーされたスプレッドシートがある前提で話を進めます。
- コピーをしてスプレッドシートを開くと[ツール][アドオン]の右に[BINGO]があると思います。
  - この名前ビンゴはこの[BINGO]を操作して動かしていきます。
  - <img width="644" alt="スクリーンショット 2019-12-16 18.22.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120339/5c5a1f2b-852d-5844-f718-80adc990add0.png">
- 次に[数字要素リスト]シートで出力される人名を入力しましょう。
  - <img width="644" alt="スクリーンショット 2019-12-16 18.25.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120339/95a698b4-0062-a85b-c1c4-c6f548d46abd.png">
- [数字要素リスト]シートを開くと数字とアルファベットが並んでいると思います。
  - A列は、IDなので1から末行まで数を振ってもらえればと思います。
  - B列は、a,b,cを人名に置き換えてもらえればと思います。
  - C列は、BINGOを始めた際に既に出た人名を出さないためのチェック用の列になりますので気にしないでください。
  - <img width="189" alt="スクリーンショット 2019-12-16 18.27.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120339/f45ee575-0e61-5639-62fd-2febf02a8128.png">
- 次に[結果]シートはBINGOを始めた際の出目の順番と結果を記録しておくシートなので触る必要はありません。

# 使い方

- [数字要素リスト]シートのB列に人名を列挙しましょう。
  - [数字要素リスト]シートのA列が人名と同じ数まであるか確認してください。
- まずはとりあえず初期化しましょう
  - [BINGO]→[初期化メニュー]→[初期化実行]
  - スクリプトの実行権限を求められたら許可をしてあげてください。
  - [スクリプトを実行しています]と出て、[スクリプトが完了しました]となるのを数秒待ちましょう。
  - これで初期化完了です。
- ビンゴの始まりです。
  - [BINGO]→[START!!]を押すと[ビンゴシート]に人名が表示されると思います。
  - また[ビンゴシート]右側の番号と結果列にそれまで回したビンゴの結果が列挙されていきます。
  - 1回実行した結果
    - <img width="962" alt="スクリーンショット 2019-12-16 18.40.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120339/7a2e5ce7-a409-47a6-5dd9-d3d5f66b8216.png">
  - 5回実行した結果
    - <img width="962" alt="スクリーンショット 2019-12-16 18.41.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120339/08aeb776-b74f-0649-e056-5a0c9579e1b3.png">
- 上記のような感じで使ってもらえればと思います。
  - 味気ない感じなのは3時間程度で作ったものだからです。ご容赦ください。。。

# 課題点
- 音が鳴らない
  - 抽選中のドラムロールは鳴らないの？と言われた。ちょっと音のことは考えてなかった…
- 複数人が同時にビンゴになった場合はじゃんけんになるの？じゃんけんだと時間かかりそう。
  - 確かに。考えていなかった。じゃんけんする時間がもったいないのでルーレットとかも追加しようと思う。

という感じで人名ビンゴゲームのツールをスプレッドシートとGASで作りました。
様々な会で良いように使ってもらえたらと思います。