ドボンしたプレイヤーが一番上においたカードがドボン返しの対象
ドボンにはドボン返しがあります。そして地域によってルールが違います。これまでのドボン返しはドボンされたプレーヤーにしかできないというルールでやってきました。またドボン返しはカードの合計に対しておこなわれてきました。
しかしローカルルールのなかには、ドボン返しはドボンしたプレイヤーが一番上においたカードを対象とするというものもあります。この場合、ドボン返しによってプレイヤーが一番上においたカードは別のものにかわるので、別のプレイヤーがドボン返しに返すこともできるようになります。このほうがルールとしては面白そうに思えます。
設定ダイアログの変更と追加
ではさっそくそのように変更できるようにしましょう。
まず設定のダイアログに新しい項目を追加します。クラスにも新しいフィールド変数とこれに対する処理を追加する必要があります。
1 2 3 4 5 6 7 8 9 10 |
static public class Config { // ドボン返しはカードの合計ではなく一番上のカードに対して行なう static public bool IsAntiDobonTopCard = true; // ドボン返しは誰でもできる static public bool IsAntiDobonEveryone = true; // その他のフィールド変数は省略 } |
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 |
public class ConfigObject { // ドボン返しはカードの合計ではなく一番上のカードに対して行なう public bool IsAntiDobonTopCard = true; // ドボン返しは誰でもできる public bool IsAntiDobonEveryone = true; // その他のフィールド変数は省略 public void CopyToFile() { IsAntiDobonTopCard = Config.IsAntiDobonTopCard; IsAntiDobonEveryone = Config.IsAntiDobonEveryone; // その他の処理は前回と同じなので省略 } public void CopyFromFile() { Config.IsAntiDobonTopCard = IsAntiDobonTopCard; Config.IsAntiDobonEveryone = IsAntiDobonEveryone; // その他の処理は前回と同じなので省略 } } |
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 |
public partial class ConfigDialog : Form { public ConfigDialog() { InitializeComponent(); buttonOK.DialogResult = DialogResult.OK; buttonOK.Click += ButtonOK_Click; } private void ConfigDialog_Load(object sender, EventArgs e) { if(Config.IsAntiDobonTopCard) cbIsAntiDobonTopCard.Checked = true; else cbIsAntiDobonTopCard.Checked = false; if(Config.IsAntiDobonEveryone) cbIsAntiDobonEveryone.Checked = true; else cbIsAntiDobonEveryone.Checked = false; // その他の処理は前回と同じなので省略 } private void ButtonOK_Click(object sender, EventArgs e) { if(cbIsAntiDobonTopCard.Checked) Config.IsAntiDobonTopCard = true; else Config.IsAntiDobonTopCard = false; if(cbIsAntiDobonEveryone.Checked) Config.IsAntiDobonEveryone = true; else Config.IsAntiDobonEveryone = false; // その他の処理は前回と同じなので省略 } } |
DobonIfCanメソッドとOnDobonメソッドの変更
Config.IsAntiDobonTopCard == trueのときはドボンできるかどうかを判定するメソッドとドボン返しができるかどうかを判定するメソッドを書き換えればなんとかなりそうです。
以下はこれまでのドボン返しができるかどうかを判定するメソッドです。
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 |
public partial class Form1 : Form { bool DobonIfCan(Player player) { int dobonNumber = CenterCard.Number; string reason = ""; foreach(var dobon in Players) { if(dobon.CanDobon(CenterCard, ref reason)) { // 自分が出したカードにはドボンできない if(((CardEx)CenterCard).player == dobon) continue; if(dobon == Players[0]) { DialogResult dr = MessageBox.Show("ドボンできます。ドボンしますか?\n" + reason, "", MessageBoxButtons.YesNo); if(dr == DialogResult.Yes) { // ドボン返しはあるのか? OnDobon(dobonNumber, Players[0], player); return true; } continue; } else { // コンピュータがドボンを辞退する確率は5分の1 int a = random.Next(5); if(a != 0) { dobon.CanDobon(CenterCard, ref reason); MessageBox.Show(dobon.Name + "が ドボンしました\n" + reason); // ドボン返しはあるのか? OnDobon(dobonNumber, dobon, player); return true; } else continue; // ドボンは見送る } } } return false; } } |
以下はこれまでのドボン返しができるかどうかを判定するメソッドです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class Form1 : Form { void OnDobon(int dobonNumber, Player dobon, Player doboned) { if(doboned.Cards.Sum(x => x.Number) == dobonNumber) { doboned.AntiDobon(dobon); MessageBox.Show("ドボン返しで" + doboned.Name + " の勝ち、\n" + dobon.Name + " の負けです"); } else { dobon.Dobon(doboned); MessageBox.Show(dobon.Name + " の勝ち、" + doboned.Name + " の負けです"); } } } |
ドボンをするときにどのカードを一番上にするのか考える必要があります。ユーザーがドボンするときはダイアログをつかって指定できるようにします。
一方、コンピュータがドボンするときは持っている数のなかで一番少ない番号を使おうと考えています。(数が小さいとドボン返しされにくい。ただしカードの和だけでなく差や商の場合、数が小さいからといってドボン返しされる確率が下がるとは言えない)
これはユーザーがドボンするときに一番上におくカードを番号を指定するためのダイアログです。
持っているカードのなかからラジオボタンを使って選択できるようにしています。また持っていないカードはRadioButton.Enabled = false; にして選択できないようにしています。
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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
public partial class DobonTopNumberDialog : Form { public List<int> vs = null; public int TopNumber = 0; public DobonTopNumberDialog() { InitializeComponent(); buttonOK.DialogResult = DialogResult.OK; buttonCancel.DialogResult = DialogResult.Cancel; buttonOK.Click += ButtonOK_Click; } private void DobonTopNumberDialog_Load(object sender, EventArgs e) { if(!vs.Any(x => x == 1)) radioButton1.Enabled = false; if(!vs.Any(x => x == 2)) radioButton2.Enabled = false; if(!vs.Any(x => x == 3)) radioButton3.Enabled = false; if(!vs.Any(x => x == 4)) radioButton4.Enabled = false; if(!vs.Any(x => x == 5)) radioButton5.Enabled = false; if(!vs.Any(x => x == 6)) radioButton6.Enabled = false; if(!vs.Any(x => x == 7)) radioButton7.Enabled = false; if(!vs.Any(x => x == 8)) radioButton8.Enabled = false; if(!vs.Any(x => x == 9)) radioButton9.Enabled = false; if(!vs.Any(x => x == 10)) radioButton10.Enabled = false; if(!vs.Any(x => x == 11)) radioButton11.Enabled = false; if(!vs.Any(x => x == 12)) radioButton12.Enabled = false; if(!vs.Any(x => x == 13)) radioButton13.Enabled = false; } private void ButtonOK_Click(object sender, EventArgs e) { if(radioButton1.Checked) TopNumber = 1; if(radioButton2.Checked) TopNumber = 2; if(radioButton3.Checked) TopNumber = 3; if(radioButton4.Checked) TopNumber = 4; if(radioButton5.Checked) TopNumber = 5; if(radioButton6.Checked) TopNumber = 6; if(radioButton7.Checked) TopNumber = 7; if(radioButton8.Checked) TopNumber = 8; if(radioButton9.Checked) TopNumber = 9; if(radioButton10.Checked) TopNumber = 10; if(radioButton11.Checked) TopNumber = 11; if(radioButton12.Checked) TopNumber = 12; if(radioButton13.Checked) TopNumber = 13; } } |
それではForm1.DobonIfCanメソッドを書き換えます。ここではドボンをするときに一番上に置くカードを選択させるようにしています。
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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
public partial class Form1 : Form { bool DobonIfCan(Player player) { int dobonNumber = CenterCard.Number; string reason = ""; foreach(var dobon in Players) { if(dobon.CanDobon(CenterCard, ref reason)) { // 自分が出したカードにはドボンできない if(((CardEx)CenterCard).player == dobon) continue; if(dobon == Players[0]) { DialogResult dr = MessageBox.Show("ドボンできます。ドボンしますか?\n" + reason, "", MessageBoxButtons.YesNo); if(dr == DialogResult.Yes) { if(Config.IsAntiDobonTopCard) { DobonTopNumberDialog dlg = new DobonTopNumberDialog(); dlg.vs = Players[0].Cards.Select(x => x.Number).Distinct().ToList(); if(dlg.ShowDialog() == DialogResult.OK) { int dobonNumber = dlg.TopNumber; // 選ばれたカードを探して出す CardEx topCard = (CardEx)Players[0].Cards.First(x => x.Number == dobonNumber); topCard.player = Players[0]; // 場に出されているカードを変更する CenterCard = topCard; System.Threading.Thread.Sleep(500); } else continue; } // ドボン返しはあるのか? OnDobon(dobonNumber, Players[0], player); return true; } continue; } else { // コンピュータがドボンを辞退する確率は5分の1 int a = random.Next(5); if(a != 0) { dobon.CanDobon(CenterCard, ref reason); MessageBox.Show(dobon.Name + "が ドボンしました\n" + reason); if(Config.IsAntiDobonTopCard) { dobonNumber = dobon.Cards.Min(x => x.Number); // カードを出す CardEx topCard = (CardEx)dobon.Cards.First(x => x.Number == dobonNumber); topCard.player = dobon; // 場に出されているカードを変更する CenterCard = topCard; System.Threading.Thread.Sleep(500); } // ドボン返しはあるのか? OnDobon(dobonNumber, dobon, player); return true; } else continue; // ドボンは見送る } } } return false; } } |
これでドボン返しはドボンしたプレイヤーが一番上においたカードに対してできるようになりました。
実際にドボン返しがあるかどうかを判定するOnDobonメソッドに変更はありません。
失礼いたします。
Form1のDobonIfCanメソッド内の
int dobonNumber = CenterCard.Number;にて、dobonNumberが既に宣言されているため、
int dobonNumber = dlg.TopNumber;でエラーが発生してしまいます。
>Form1のDobonIfCanメソッド内の
>int dobonNumber = CenterCard.Number;にて、dobonNumberが既に宣言されているため、
>int dobonNumber = dlg.TopNumber;でエラーが発生してしまいます。
元のコードが見当たらないため、ちょっとわかりません。
DobonIfCan(Player player)メソッドは後のページで書き換えています。
返事にならない返事で申し訳ありません。