- プレイヤーの前にA・B・Cの3つのドアがあり、3つとも扉は閉じている。
- そのうち1つのドアの奥には景品の自動車があり、残りはハズレのヤギがいる。
- プレイヤーはドアを1つ選択する。ここではドアを開けない。
- 正解のドアを知っているモンティは、残ったドアのうちハズレのドアを開ける。
- モンティは「今なら選択を変更してもいいですよ」とプレイヤーに問いかける。
サンプル・プログラムの実行例
ランダムに1万回のドア開け試行を行い、ドアを変えない場合のアタリ確率は $ \displaystyle \frac{1}{3} $ に、変えた場合のアタリ確率は $ \displaystyle \frac{2}{3} $ に収束することが分かる。試行回数は横軸に対数目盛として示している。
この結論については。いくつかの数学的解説があるが、条件付き確率の問題として、ベイズの定理を用いるのが王道である。
サンプル・プログラム
| MontyHall.php | サンプル・プログラム本体 |
| pahooInputData.php | データ入力に関わる関数群。 使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 1.4.0 | 2026/04/05 | PHP8.5対応, pahooInputData.php導入 |
| 1.3.0 | 2023/05/05 | グラフにフッタを追加 |
| 1.2 | 2022/04/17 | PHP8対応,リファラ・チェック改良 |
| 1.1 | 2018/06/05 | JpGraph 4.2.1対応 |
| 1.0 | 2018/02/11 | 初版 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 2.0.1 | 2025/08/11 | getParam() bug-fix |
| 2.0.0 | 2025/08/11 | pahooLoadEnv() 追加 |
| 1.9.0 | 2025/07/26 | getParam() 引数に$trim追加 |
| 1.8.1 | 2025/03/15 | validRegexPattern() debug |
| 1.8.0 | 2024/11/12 | validRegexPattern() 追加 |
準備:pahooInputData 関数群
また、各種クラウドサービスに登録したときに取得するアカウント情報、アプリケーションパスワードなどを登録した .pahooEnv ファイルから読み込む関数 pahooLoadEnv を備えている。こちらについては、「各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。
準備:JpGraphライブラリ
Moore.php
53: // JpGraph:include_pathが通ったディレクトリに配置すること
54: require_once('jpgraph/jpgraph.php');
55: require_once('jpgraph/jpgraph_line.php');
56: require_once('jpgraph/jpgraph_log.php');
57:
JpGraph は、サーバ側(PHP側)でグラフを画像データとして生成し、クライアントへ配信する。このため、GDライブラリが有効化されていることが前提である。
また、使用する機能によってインクルードする PHPファイルの種類が異なることに留意してほしい。
公式サイトからダウンロードしたファイルを解凍したら、include_path が通ったディレクトリに配置してほしい。
凡例やラベルに日本語を使う場合は、日本語フォント(TrueTypeファイル)を用意しておく。これについても、アシアル社のサイトに詳しい説明がある。
具体的には、フォント・ファイルを格納したフォルダを "jpg-config.inc.php" の定数 TTF_DIR および MBTTF_DIR に設定してやる。
実際に使うフォントは "jpgraph_ttf.inc.php" の定数 MINCHO_TTF_FONT、PMINCHO_TTF_FONT、GOTHIC_TTF_FONT、PGOTHIC_TTF_FONT に設定されている。デフォルトで設定されているのは IPA の無償フォントで、文字情報技術促進協議会の IPAフォントから入手できる。
準備:各種定数など
MontyHall.php
49: // 各種定数(START) ===========================================================
50:
51: // エラー表示用フォント・ファイル名;各自の環境に合わせて
52: define('FONT', '../../../../common/font/ipagp.ttf');
53:
54: // JpGraph(各自の環境に合わせて)
55: require_once('jpgraph/jpgraph.php');
56: require_once('jpgraph/jpgraph_log.php');
57: require_once('jpgraph/jpgraph_line.php');
58:
59: // ドア識別子
60: define('DOOR_LABEL', 'ABC');
61:
62: // 試行回数
63: $Counter = 10000;
64:
65: // 各種定数(END) ===============================================================
ドア識別子をA・B・C・D‥‥のように増やすことも可能で、増やしたとしてもドアを変更した方がアタリ確率がアップすることが分かる。
解説:モンティ・ホール問題
MontyHall.php
142: /**
143: * モンティ・ホール問題(1回)
144: * @param なし
145: * @return array(介入なし,介入あり)
146: */
147: function MontyHall_once() {
148: $doors = array();
149: makeDoors($doors);
150:
151: // プレイヤーがドアを1つ選ぶ
152: $user = getRandomDoor($doors);
153: $doors[$user]['status'] = TRUE;
154:
155: // モンティがドアを1つ開ける
156: make_seed();
157: do {
158: $monty = getRandomDoor($doors);
159: } while ($doors[$monty]['hit'] == TRUE);
160: $doors[$monty]['status'] = TRUE;
161:
162: // プレイヤーはドアを変えない
163: if ($doors[$user]['hit']) $res0 = TRUE;
164: else $res0 = FALSE;
165:
166: // プレイヤーはドアを変える
167: $user = getRandomDoor($doors);
168: if ($doors[$user]['hit']) $res1 = TRUE;
169: else $res1 = FALSE;
170:
171: return array($res0, $res1);
172: }
冒頭に記したゲームのルールを、そのままプログラムに落とし込んである。
MontyHall.php
175: /**
176: * モンティ・ホール問題
177: * @param int $n = 試行回数
178: * @return array 確率配列
179: */
180: function MontyHall($n) {
181: $prob = array();
182: $cnt0 = 0;
183: $cnt1 = 0;
184:
185: for ($i = 0; $i < $n; $i++) {
186: list($res0, $res1) = MontyHall_once();
187: if ($res0) $cnt0++;
188: if ($res1) $cnt1++;
189: $prob[$i][0] = (float)$cnt0 / ($i + 1);
190: $prob[$i][1] = (float)$cnt1 / ($i + 1);
191: }
192:
193: return $prob;
194: }
解説:グラフを描く
MontyHall.php
196: /**
197: * グラフ描画
198: * @param array $items データ
199: * @param int $year_min 最小年
200: * @param int $year_max 最大年
201: * @return object graphオブジェクト
202: */
203: function drawGraph($items, $n) {
204: $plotdata = array();
205:
206: // プロット配列を作成
207: for ($i = 0; $i < $n; $i++) {
208: $data_x[$i] = $i; // 横軸
209: $data_y0[$i] = $items[$i][0];
210: $data_y1[$i] = $items[$i][1];
211: }
212:
213: // グラフ描画処理開始
214: $graph = new Graph(600, 500, 'auto');
215: $graph->SetScale('loglin', 0.0, 1.0); // X軸:対数,Y軸:小数
216: $graph->SetBackgroundGradient('#FFFFCC','#FFFFCC', GRAD_HOR, BGRAD_MARGIN);
217:
218: // タイトル、凡例などの設定
219: $graph->img->SetImgFormat('png');
220: $graph->img->SetMargin(60, 60, 20, 40);
221: $graph->title->SetFont(FF_PGOTHIC, FS_NORMAL, 16);
222: $graph->title->Set('モンティ・ホール問題');
223: $graph->xaxis->title->SetFont(FF_PGOTHIC);
224: $graph->xaxis->SetTitle('試行回数','center');
225: $graph->yaxis->title->SetFont(FF_PGOTHIC);
226: $graph->yaxis->title->Set('当たり確率');
227: $graph->yscale->ticks->Set(0.1);
228: $graph->yaxis->SetTitleMargin(40);
229: // フッタを設定する.
230: $graph->footer->right->SetFont(FF_PGOTHIC, FS_NORMAL, 10);
231: $graph->footer->right->Set('produced by JpGraph');
232:
233: // ドアを変更しない場合
234: $plotdata[0] = new LinePlot($data_y0);
235: $plotdata[0]->SetLegend('ドアを変更しない'); // 凡例
236: $graph->Add($plotdata[0]);
237:
238: // ドアを変更する場合
239: $plotdata[1] = new LinePlot($data_y1);
240: $plotdata[1]->SetLegend('ドアを変更する'); // 凡例
241: $graph->Add($plotdata[1]);
242:
243: // 色指定は最後に
244: $plotdata[0]->SetColor('#0000FF'); // 色
245: $plotdata[0]->SetWeight(2); // 太さ
246: $plotdata[1]->SetColor('#FF0000'); // 色
247: $plotdata[1]->SetWeight(2); // 太さ
248:
249: // 凡例
250: $graph->legend->SetFont(FF_PGOTHIC); // フォント
251: $graph->legend->SetColumns(1); // 表示列数
252: $graph->legend->SetPos(0.15, 0.85, 'right', 'bottom'); // 位置
253:
254: return $graph;
255: }
参考サイト
- PHPとJpGraphで人口ピラミッドを表示する:ぱふぅ家のホームページ
- JpGraph公式サイト

(2026年3月15日)PHP8.5対応, pahooInputData.php導入