Qは2枚以上同時に出せる
ドボンではQを2枚以上持っていたら同時にだすことができます。もちろん1枚だけでも出せます。この場合は上に置いたカードが台札となります。
では上に置くカードはどれになるのでしょうか?
たとえば「ダイアのQ」と「ハートのQ」をもっていたとします。台札は「ダイアの7」としましょう。この場合、2枚同時に出すのであれば、「ダイアのQ」を下、「ハートのQ」を上に重ねて場に出します。台札に置くことができるQを下にするというわけです。
Qを複数枚もっているときは「同時にだすことができる」のですが、これは強制ではありません。1枚ずつ出してもかまいません。
ではどのように考えればいいでしょうか。
PlayerクラスのPutCardメソッドを一部修正
PlayerクラスのPutCardメソッドのなかで、カードを出し、そのカードがQだった場合、ほかにQが持ち札にあるかどうか調べてそれも一緒に出すのか判定しています。
GetPutQueensメソッドはもっているQueenのなかでいっしょに出すカードのリストを返します。まず1枚目のQueenが出されたときにこのメソッドは呼ばれます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class Player { public List<Card> GetPutQueens() { var queens = Cards.Where(x => x.Number == 12).ToList(); List<Card> putCards = new List<Card>(); for(int i = 0; i< queens.Count; i++) { int r = Random.Next(8); if(r < 6) putCards.Add(queens[i]); } return putCards; } } |
PutCardメソッドですが、複数のQueenを出した場合、どれを上にするか考える必要があります。PutCardメソッドが長くなるので書き直しました。
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 |
public class Player { public Card PutCard(Card card, List<Card> shuffledCards) { // 出せるカードを求める List<Card> canPutCards = GetAblePutCards(card); // 実際に出されたカード Card putCard = null; if(canPutCards.Count > 0) { putCard = OnFindCanPutCard(canPutCards); } else { // 出せるカードがない場合 // 出せるカードがない場合は積み札からとり続けなければならない putCard = OnFindCanPutNoCard(shuffledCards, card); } // Qを出したあと一緒に出すかどうか if(putCard.Number == 12) { Card ret = OnAfterPutQueen(); if(ret != null) putCard = ret; } return putCard; } } |
OnFindCanPutCardメソッドは出せるカードが手札のなかにあるときのメソッドです。
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 |
public class Player { Card OnFindCanPutCard(List<Card> canPutCards) { // 実際に出されたカード Card putCard = null; if(canPutCards.Count == 1) { // ひとつだけみつかった場合 Cards.Remove(canPutCards[0]); putCard = canPutCards[0]; System.Threading.Thread.Sleep(500); PlayerPanel.Invalidate(); } else if(canPutCards.Count > 1) { // 複数ある場合 int index = Random.Next(canPutCards.Count); Card card = canPutCards[index]; Cards.Remove(card); putCard = card; System.Threading.Thread.Sleep(500); PlayerPanel.Invalidate(); } return putCard; } } |
OnFindCanPutNoCardは出せるカードが手札のなかにはないので、出せるカードを引くまで積み札からカードを取り続けるメソッドです。
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 |
public class Player { Card OnFindCanPutNoCard(List<Card> shuffledCards, Card card) { // 実際に出されたカード Card putCard; while(true) { // 積み札がなくなったらすでに出されているカードを使う。 if(shuffledCards.Count == 0) _form1.ShuffleCard(card); Card addCard = shuffledCards[0]; shuffledCards.RemoveAt(0); Cards.Add(addCard); PlayerPanel.Invalidate(); System.Threading.Thread.Sleep(500); // 出せるカードがあったらこれを出してループから抜ける if(IsAblePutCards(addCard, card)) { Cards.Remove(addCard); PlayerPanel.Invalidate(); putCard = addCard; System.Threading.Thread.Sleep(500); break; } } return putCard; } } |
OnAfterPutQueenメソッドはQueenを出すときにいっしょに他のQueenも出すメソッドです。戻り値は一番上に置かれるカードです。
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 |
public class Player { Card OnAfterPutQueen() { // 一番上に置かれるカード Card mostTop = null; List<Card> queens = GetPutQueens(); if(queens.Count != 0) { // 一番上にするカードを決める int index = Random.Next(queens.Count); mostTop = queens[index]; queens.RemoveAt(index); queens.Add(mostTop); foreach(var cardQ in queens) { Cards.Remove(cardQ); System.Threading.Thread.Sleep(100); PlayerPanel.Invalidate(); } return mostTop; } return null; } } |
自分の手番のときQueenが複数あったら・・・
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 |
public partial class Form1 : Form { private void panelSouth_MouseDown(object sender, MouseEventArgs e) { Card card = GetClickedCard(e); if(CheckUnjustClick(card)) return; Players[0].Cards.Remove(card); CenterCard = card; // Queenは複数枚まとめて出せるため // カードを出したあとQueenしか残っていないならあがりの処理をする if(Players[0].Cards.All(x => x.Number == 12)) { Players[0].Cards.Clear(); } // Qを出したとき複数枚数できる場合はダイアログを表示する if(CenterCard.Number == 12) { Card QueenCard = OnMyPutCardQueen(); if(QueenCard != null) { ((CardEx)QueenCard).player = Players[0]; CenterCard = QueenCard; } } if(CenterCard.Number == 1) isLastCardA = true; if(CenterCard.Number == 2) drawTwoCount = 1; if(CenterCard.Number == 11) { if(!isFromBack) isFromBack = true; else isFromBack = false; System.Threading.Thread.Sleep(500); } panelSouth.Invalidate(); // あがったと思ったらドボンされる可能性があるのでチェックする if(Players[0].Cards.Count == 0) { OnMyFinish(); return; } RivalsTurnAsync(); } } |
自分の手番の場合、Queenが複数あった場合、どうするのか選択できるようにしないといけません。これに対応できるようにダイアログを出すことにします。
OnMyPutCardQueenメソッドはQを出したとき、他にもQがある場合はいっしょに出せることを示すダイアログボックスを表示します。
そして同時にだすQueenと一番上に置くカードをユーザーに選択させます。選択が終わったらカードを出します。
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 |
public partial class Form1 : Form { Card OnMyPutCardQueen() { Card ret = null; // 一番上に出すカード // ユーザーがQueenを出したら・・・ if(CenterCard.Number == 12) { // ほかにも手札にQueenがないか調べる if(Players[0].Cards.Count(x => x.Number == 12) > 0) { // 表示するダイアログの設定 // 存在しないカードは選択できないようにする FormQueen formQueen = new FormQueen(); if(!Players[0].Cards.Any(x => x.Number == 12 && x.Suit == Suit.Spade)) { formQueen.checkBoxSpade.Enabled = false; formQueen.radioButtonSpade.Enabled = false; } if(!Players[0].Cards.Any(x => x.Number == 12 && x.Suit == Suit.Hart)) { formQueen.checkBoxHart.Enabled = false; formQueen.radioButtonHart.Enabled = false; } if(!Players[0].Cards.Any(x => x.Number == 12 && x.Suit == Suit.Dia)) { formQueen.checkBoxDia.Enabled = false; formQueen.radioButtonDia.Enabled = false; } if(!Players[0].Cards.Any(x => x.Number == 12 && x.Suit == Suit.Club)) { formQueen.checkBoxClub.Enabled = false; formQueen.radioButtonClub.Enabled = false; } // ダイアログを表示させる formQueen.ShowDialog(); // どのような選択がされたのか調べる List<Card> removeCards = new List<Card>(); if(formQueen.checkBoxSpade.Checked) removeCards.Add(Players[0].Cards.First(x => x.Number == 12 && x.Suit == Suit.Spade)); if(formQueen.checkBoxHart.Checked) removeCards.Add(Players[0].Cards.First(x => x.Number == 12 && x.Suit == Suit.Hart)); if(formQueen.checkBoxDia.Checked) removeCards.Add(Players[0].Cards.First(x => x.Number == 12 && x.Suit == Suit.Dia)); if(formQueen.checkBoxClub.Checked) removeCards.Add(Players[0].Cards.First(x => x.Number == 12 && x.Suit == Suit.Club)); // 一番上になるように指定したカードが一番上にくるようにする if(formQueen.radioButtonSpade.Checked) ret = Cards.First(x => x.Number == 12 && x.Suit == Suit.Spade); if(formQueen.radioButtonHart.Checked) ret = Cards.First(x => x.Number == 12 && x.Suit == Suit.Hart); if(formQueen.radioButtonDia.Checked) ret = Cards.First(x => x.Number == 12 && x.Suit == Suit.Dia); if(formQueen.radioButtonClub.Checked) ret = Cards.First(x => x.Number == 12 && x.Suit == Suit.Club); foreach(var card in removeCards) Players[0].Cards.Remove(card); } } return ret; } } |
これはQueenを同時に複数出すかどうか選択するためのダイアログです。
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 FormQueen : Form { bool isOk = false; public FormQueen() { InitializeComponent(); } private void FormQueen_Load(object sender, EventArgs e) { buttonOK.DialogResult = DialogResult.OK; buttonCancel.DialogResult = DialogResult.Cancel; buttonOK.Click += ButtonOK_Click; buttonCancel.Click += ButtonCancel_Click; } private void ButtonCancel_Click(object sender, EventArgs e) { isOk = false; } private void ButtonOK_Click(object sender, EventArgs e) { isOk = true; } private void FormQueen_FormClosing(object sender, FormClosingEventArgs e) { // 不正な選択がされていないかチェックする if( !radioButtonClub.Checked && !radioButtonDia.Checked && !radioButtonHart.Checked && !radioButtonSpade.Checked ) { MessageBox.Show("一番上にするカードを選択してください"); e.Cancel = true; return; } if( radioButtonClub.Checked && !checkBoxClub.Checked || radioButtonDia.Checked && !checkBoxDia.Checked || radioButtonHart.Checked && !checkBoxHart.Checked || radioButtonSpade.Checked && !checkBoxSpade.Checked ) { MessageBox.Show("出すカードでないと「一番上にするカード」として選択できません"); e.Cancel = true; } } } |