マーチンゲール法とは、勝つまでは賭け金を倍にしていく方法です。どんなに負け続けても1回勝てばすべての負けを取り戻すことができるので一見、丁半博打の必勝法のようにみえます。しかしマーチンゲール法は危険な方法です。必ず最後は破産します。
マーチンゲール法は勝つまでは賭け金を倍、倍と増やしていくため相当の軍資金を用意しなければなりません。そして何度もこの方法を繰り返しているとどこかでとんでもない連敗をすることになります。これをプログラミングで証明してみることにします。
サイコロをふたつ用意して目の和が偶数であれば勝ち、奇数であれば負けとします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public partial class Form1 : Form { Random Random1 = new Random(); bool IsWin() { int i1 = Random1.Next(6) + 1; int i2 = Random1.Next(6) + 1; if ((i1 + i2) % 2 == 0) return true; // 偶数なら勝ち。そうでないなら負け。 else return false; } } |
ボタンがクリックされたら最初の所持金は10000円、最初の賭け金は100円で負けたら賭け金を2倍にして勝った場合は賭け金を元の100円に戻して破産するまで丁半博打を繰り返します。最後に結果を可視化するためにBitmapを作成して表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
public partial class Form1 : Form { Bitmap Bitmap1 = null; private void button1_Click(object sender, EventArgs e) { const int start = 100; // 最初の賭け金 const int startMoney = 10000; // 所持金 int moneyCarried = startMoney; // 現在の所持金 int bet = start; // 賭け金 int successiveDefeatsCount = 0; // 連敗数 List<int> moneyCarrieds = new List<int>(); int i = 0; while(true) { i++; moneyCarried -= bet; if (IsWin()) { moneyCarried += bet * 2; bet = start; successiveDefeatsCount = 0; } else { successiveDefeatsCount++; bet *= 2; } moneyCarrieds.Add(moneyCarried); if (moneyCarried <= 0) { // 破産したらループを抜ける break; } if (checkBox1.Checked && successiveDefeatsCount >= (int)numericUpDown1.Value) { bet = start; successiveDefeatsCount = 0; } } // 結果を表示 label1.Text = String.Format("最初の所持金は{0:#,0} 最初の賭け金は{1:#,0}とする", startMoney, start); label2.Text = String.Format("破産するまでの回数:{0:#,0} 最高額:{1:#,0} 負債:{2:#,0} 連敗数:{3:#,0}", i, moneyCarrieds.Max(), moneyCarried, successiveDefeatsCount); // 結果を可視化するためにBitmapを生成する Bitmap1 = GetBitmap(moneyCarrieds); Invalidate(); } } |
Bitmapを生成する処理を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
public partial class Form1 : Form { Bitmap GetBitmap(List<int> moneyCarrieds) { int bitmapWidth = ClientSize.Width; int max = moneyCarrieds.Max(); int bitmapHeight = ClientSize.Height; Bitmap bitmap = new Bitmap(bitmapWidth, bitmapHeight); Graphics graphics = Graphics.FromImage(bitmap); graphics.Clear(Color.White); int count = 0; int lineWidth = bitmapWidth / moneyCarrieds.Count; foreach (int money in moneyCarrieds) { double d = 1d * bitmapHeight * money / max; double d2 = 1d * bitmapWidth * count / moneyCarrieds.Count; // 幅が2以上の場合は矩形を描画する // 幅が1の場合は直線を描画して破産までの過程をグラフにする if (lineWidth > 1) graphics.FillRectangle(Brushes.Black, new Rectangle(new Point((int)d2, 0), new Size(lineWidth + 1, (int)d))); else graphics.DrawLine(Pens.Black, new Point((int)d2, 0), new Point((int)d2, (int)d)); count++; } graphics.Dispose(); bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); return bitmap; } } |
フィールド変数のBitmapがnullでない場合はこれをフォーム上に描画します。
1 2 3 4 5 6 7 8 9 10 |
public partial class Form1 : Form { protected override void OnPaint(PaintEventArgs e) { if(Bitmap1 != null) e.Graphics.DrawImage(Bitmap1, new Point(0, 0)); base.OnPaint(e); } } |