ジョーカーに関するローカルルール
これまではジョーカーは使いませんでした。ジョーカーを使う場合、これもローカルルールがいくつかあります。
出せるカードがない場合、ジョーカーを代用する
(ジョーカーはすべてのカードの代わりになる)
ジョーカーは単独では使用できない
場に出ているカードから1つ違ったカードを持っている場合であれば、ジョーカーと併せて1つ違った数字のカードとの2枚を一緒に出さないといけません。この場合、ジョーカーはいつでも使えるカードではなくなります。
またジョーカーが出された場合、その位置に本来置かれるべきカードを持っているプレイヤーは、そのカードを場に出し、代わりにジョーカーを手札に加えなければならないというルールもあります。
そのときジョーカーは強制的に取らされるというルールと、辞退することができるルールがあります。
ローカルルールがたくさんあるとややこしいです。
今回作成するプログラムのルール
ここではいきなり難しくすると大変(あと間を持たせることができない)なのでジョーカーは単体で出す、ジョーカーのうけとりは「拒否できない」というルールにします。あとでジョーカーは次に出せるカードとセットで出さなければならない、ジョーカーをもらうかどうかは任意というルールでもつくってみることにします。
ジョーカーを表示させる
カードの種類は以下のように定義されています。
| 
					 1 2 3 4 5 6 7 8 9  | 
						public enum CardMark {     none = -1,     joker = 0,     spade = 1,     hart = 2,     dia = 3,     club = 4, }  | 
					
まずはカードを配るときにジョーカーをいれる必要があります。それからカードを生成するときにジョーカーもつくる必要があります。
以下はカードを生成するためのクラスです。カードの絵柄を取得するメソッドを少し変更しています。
これでジョーカーをつくることができます。またスペードのAは他のカードと違う絵柄もあったので、これを使うことにします。
| 
					 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  | 
						class Card {     Bitmap _bitmap = null;     // カードの絵柄はクラス外からも取得できるようにした     public Bitmap Bitmap     {         get         {             if(_bitmap == null)                 _bitmap = GetBitmap();             return _bitmap;         }     }     Bitmap GetBitmap()     {         Rectangle rect = new Rectangle(Point, Size);         Bitmap bitmap = new Bitmap(Size.Width, Size.Height);         var image = Properties.Resources.cardimage;         int x, y = 0;         x = 0;         if(Mark == CardMark.spade)         {             y = 1800;             x = 382 * (Number - 1);         }         if(Mark == CardMark.hart)         {             y = 1200;             x = 382 * (Number - 1);         }         if(Mark == CardMark.dia)         {             y = 600;             x = 382 * (Number - 1);         }         if(Mark == CardMark.club)         {             y = 0;             x = 382 * (Number - 1);         }         // 追加部分 ジョーカー         if(Mark == CardMark.joker)         {             y = 2400;             x = 0;         }         // 追加部分 裏         if(Mark == CardMark.none)         {             y = 2400;             x = 382 * 2;         }         // 追加部分 スペードのエース         if(Mark == CardMark.spade && Number == 1)         {             y = 2400;             x = 382 * 1;         }         Rectangle srcRect = new Rectangle(new Point(x, y), new Size(354, 490));         Graphics graphics = Graphics.FromImage(bitmap);         graphics.DrawImage(image, new Rectangle(0, 0, Size.Width, Size.Height), srcRect, GraphicsUnit.Pixel);         graphics.Dispose();         return bitmap;     } }  | 
					
これはジョーカーを使うためのメソッドです。引数はどのカードの代わりに使うかです。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  | 
						class Card {     public void UseJoker(CardMark mark, int number)     {         Colum = number - 1;         if(mark == CardMark.spade)             Row = 0;         if(mark == CardMark.hart)             Row = 1;         if(mark == CardMark.dia)             Row = 2;         if(mark == CardMark.club)             Row = 3;         int x = (size.Width + 10) * Colum + 20;         int y = (size.Height + 10) * Row + 30;         Point = new Point(x, y);     } }  | 
					
カードを生成するときにジョーカーも生成します。他のマークには番号がありますが、ジョーカーには番号はありません。とりあえず1を設定しています。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16  | 
						public partial class Form1 : Form {     void Init()     {         for(int i = 1; i <= 13; i++)             cards.Add(new Card(CardMark.spade, i));         for(int i = 1; i <= 13; i++)             cards.Add(new Card(CardMark.hart, i));         for(int i = 1; i <= 13; i++)             cards.Add(new Card(CardMark.dia, i));         for(int i = 1; i <= 13; i++)             cards.Add(new Card(CardMark.club, i));         cards.Add(new Card(CardMark.joker, 1));     } }  | 
					
ライバルの動作に関するメソッド
もし相手が出せるカードはないけどジョーカーを持っているのであれば、それを使います。
ジョーカーが使用する場合、どのカードの代わりに使うのかを考える必要があります。乱数で適当に決めています。
それからジョーカーしか持っていないのであれば、そのプレイヤーは負けです。
| 
					 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  | 
						public partial class Form1 : Form {     void RivalTurn(int rivalID)     {         var rivalCards = playersCards[rivalID];         List<Card> canCards = rivalCards.Intersect(GetCanTakeout()).ToList();         if(canCards.Count != 0)         {             // 持っているカードを普通に出す             // 省略         }         else         {             // ジョーカーしかもっていないのであれば失格             if(rivalCards.Count == 1 && rivalCards[0].Mark == CardMark.joker)             {                 string str = String.Format("ジョーカーしかもっていない {0} は失格です", rivalID);                 MessageBox.Show(str, "報告", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);                 // 失格の表示をさせるための処理                 passCounts[rivalID] = PASS_MAX + 1;                 ShowPlayerInfo(rivalID);                 return;             }             // ジョーカーをもっているのであれば出す             if(rivalCards.Any(x => x.Mark == CardMark.joker))             {                 Card jokerCard = rivalCards.First(x => x.Mark == CardMark.joker);                 rivalCards.Remove(jokerCard);                 // どのカードの代わりに出すか?                 int next = random.Next(0, GetCanTakeout().Count);                 Card nextCard = GetCanTakeout()[next];                 jokerCard.UseJoker(nextCard.Mark, nextCard.Number);                 jokerCard.isExists = true;                 Rectangle rectInvalidate = new Rectangle(jokerCard.Point, Card.Size);                 Invalidate(rectInvalidate);                 OnUseJoker(jokerCard, nextCard);             }             else                 RivalPass(rivalID);         }         ShowPlayerInfo(rivalID);     } }  | 
					
ジョーカーの表示と移動
またジョーカーは出されたらそのときのための処理をする必要があります。
ジョーカーはどのカードの代わりに出されたのかを調べてその位置に表示されます。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  | 
						class Card {     public void UseJoker(CardMark mark, int number)     {         Colum = number - 1;         if(mark == CardMark.spade)             Row = 0;         if(mark == CardMark.hart)             Row = 1;         if(mark == CardMark.dia)             Row = 2;         if(mark == CardMark.club)             Row = 3;         int x = (size.Width + 10) * Colum + 20;         int y = (size.Height + 10) * Row + 30;         Point = new Point(x, y);     } }  | 
					
ジョーカーが使用された場合、ジョーカーのかわりに出されているカードを持っているプレイヤーはそれを出さなければなりません。OnUseJokerはカードの持ち主を探してカードをださせてジョーカーを受け取らせます。
| 
					 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 partial class Form1 : Form {     void OnUseJoker(Card jokerCard, Card card)     {         MessageBox.Show("ジョーカーが使用されました");         // カードの持ち主を探す         List<Card> player1 = null;         foreach(var player in playersCards)         {             if(player.Any(x => x == card))             {                 player1 = player;                 break;             }         }         if(player1 != null)         {             player1.Remove(card);             player1.Add(jokerCard);             card.isExists = true;             jokerCard.isExists = false;             Rectangle rectInvalidate = new Rectangle(card.Point, Card.Size);             Invalidate(rectInvalidate);         }     } }  | 
					
次回は自分の動作に関するメソッドを考えます。
