今回は「グロタンカット」と「ラマヌジャン革命」を実装します。
Contents
「グロタンカット」と「ラマヌジャン革命」
素数大富豪には「グロタンカット」と「ラマヌジャン革命」があります。革命なら普通の大富豪でもありますね。同じ数字のカードを4枚出したらカードの強弱が逆になります。そしてもう一度同じ数字のカードを4枚出したら「革命返し」となり、カードの強弱は元に戻ります。
素数大富豪では1729が出されるとラマヌジャン革命が成立します。この数は数学者シュリニヴァーサ・ラマヌジャンの逸話からタクシー数とも呼ばれています。また素数ではないにもかかわらず確率的素数であると判定される数でもあります。
また素数大富豪では57を単体で出すことができます。57が出ると即座に場が流れ、57を出した者が次の親になります。「グロタンカット」とも呼ばれます。
57は素数ではないのですが、ドイツ出身のユダヤ系フランス人の数学者であるアレクサンドル・グロタンディークが素数に関する一般論について講演をした際に、素数ではない57を誤って選んだという逸話があります。数学者でもこんなミスをするのですね。そのことから57は素数として出すことができ、しかも57が出されると即座に場が流れ、このカードを出した人が親になるという「グロタンカット」というルールができたのです。
グロタンカット
まずグロタンカットの実装から考えます。プレイヤーからカードが素数として出されたときに57であれば正当な手とみなして、同時に場を流す処理をすればよいのです。またコンピュータが次の手を考えるときに2枚出しのときは57も選択肢のひとつにすればよいのです。
グロタンカットはどのタイミングでやればいいのでしょうか? ただでさえ素数にしても合成数にしても人間業では見つけることが困難な手をコンピュータが繰り出してくるので、57が出せるときはランダムで決めます。これ以上強くなってはどうやっても勝つことはできないので、あまり深くは考えないことにします。
プレイヤーによって決定ボタンが押されたときの処理
決定ボタンが押されたときの処理ですが、いくつかのメソッドにわけました。
まず出されたカードの枚数とカードによってつくられる数が正しいかどうかを判定する部分をCheckPlayerCards0メソッドとして分離しました。これはラマヌジャン革命が起きたときに処理を変えなければならないので、いまの段階で分離しておきます。
そのあとグロタンディーク素数である57が出されたのかを確認します。素数として57が出された場合は強制的に場が流されます。カードが「素数」57として出されたのかのチェックと場を流す処理はCheckPlayerGrothendieckメソッドのなかでおこなわれています。
そのあとプレイヤーとコンピュータが持っているカードがなくなっているかどうかも別のメソッドをつくって処理をしています。
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 { async private void ButtonDecision_Click(object sender, EventArgs e) { // コンピュータが素因数場に出したカードは手番が代わると同時に流れる Cards.AddRange(CardsPutByComp2); CardsPutByComp2.Clear(); // カードの枚数と生成される数をチェック if (!CheckPlayerCards0()) return; int cardCount = 0; long minValue = 0; if (TempPrimefactors.Count > 0) { Primefactors.Add(GetNumber(TempPrimefactors)); TempPrimefactors.Clear(); } // 素数として出された数はグロタンディーク素数57か? if (CheckPlayerGrothendieck(ref cardCount, ref minValue)) return; if (Primefactors.Count == 0) CheckPlayerCards1(ref cardCount, ref minValue); // 素数として出された場合のチェック else CheckPlayerCards2(ref cardCount, ref minValue); // 合成数として出された場合のチェック Primefactors.Clear(); TempPrimefactors.Clear(); PlayerText1 = ""; PlayerText2 = ""; LabelPlayer.Text = "あなた:"; CheckBoxPrimeFactor.Checked = false; PlayerCards = PlayerCards.OrderBy(card => card.Number).ToList(); ShowCards(); await Task.Delay(500); // プレイヤーのカードがなくなっていればプレイヤーの勝利 if(CheckPlayerWin()) return; CompPutCards(cardCount, minValue, ref CountCardsPutMust, ref MinValueCards); // コンピュータのカードがなくなっていればコンピュータの勝利 if (CheckCompWin()) return; // 勝負が決着せずゲーム続行の場合はプレイヤーはなにを出すべきかをLabelに表示 ShowNaviLabelText(); } } |
CheckPlayerCards0メソッドでは出されたカードの枚数とカードによってつくられる数が出さなければならない最低の数を上回っているかだけ確認しています。これはラマヌジャン革命時には最大の数を下回っていなければなりません。すぐに書き換えなければならないメソッドです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public partial class Form1 : Form { bool CheckPlayerCards0() { if (CountCardsPutMust != -1) { string str = ""; if (CountCardsPutMust != CardsPutByPlayer1.Count) str += $"場に出せるカードは{CountCardsPutMust}枚限定です。"; if (MinValueCards > GetNumber(CardsPutByPlayer1)) str += $"場に出せるカードは{MinValueCards}以上になるようなカードを出してください"; LabelPlayerErrer.Text = str; if (str != "") return false; } return true; } } |
グロタンディーク素数が出されて場を流す処理
そのあとグロタンディーク素数である57が出されたのかを確認します。素数として57が出された場合は強制的に場が流されます。カードが「素数」57として出されたのかのチェックと場を流す処理はCheckPlayerGrothendieckメソッドのなかでおこなわれています。
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 |
public partial class Form1 : Form { bool CheckPlayerGrothendieck(ref int cardCount, ref long minValue) { if (Primefactors.Count == 0) { long number = GetNumber(CardsPutByPlayer1); if (number == 57) { // 強制的に場を流す Pass(); ShowCards(); LabelPlayerErrer.Text = ""; LabelMessage.Text = "グロタンディーク素数を出したのであなたが親です。"; // 57を出したプレイヤーは次は何を出してもかまわない minValue = -1; cardCount = -1; return true; } } return 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 |
public partial class Form1 : Form { bool CheckPlayerWin() { if (PlayerCards.Count == 0) { LabelMessage.Text = "あなたの勝ちです。"; ButtonGameStart.Enabled = true; return true; } else return false; } bool CheckCompWin() { if (CompCards.Count == 0) { LabelMessage.Text = "コンピュータの勝ちです。"; ButtonGameStart.Enabled = true; return true; } else return false; } } |
勝負が決着せずゲーム続行の場合、プレイヤーになにを出すべきかをLabelに表示させる処理を示します。この部分もラマヌジャン革命がおきると書き換えが必要です。
1 2 3 4 5 6 7 8 9 10 |
public partial class Form1 : Form { void ShowNaviLabelText() { if (CountCardsPutMust != -1) LabelMessage.Text = $"{CountCardsPutMust}枚のカードで{MinValueCards}以上の数を出してください"; else LabelMessage.Text = $"コンピュータはパスをしました。あなたが親です。"; } } |
コンピュータがグロタンディーク素数を出した場合の処理
次にコンピュータがグロタンディーク素数を出した場合の処理を考えます。
現状では57は素数ではないのでコンピュータにとっては選択肢に入っていません。そこでコンピュータが出すカードを探すときに57も選択肢に加えます。
出せるカードの番号を調べる処理はSearchNumberメソッドでおこなっていますが、ちょっと長いので分割しました。ラマヌジャン革命がおきると書き換えないといけないので本体部分は短くしておきたいです。
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 |
public partial class Form1 : Form { ResultCards SearchNumber(bool isPrimeNumber, int cardCount, long minValue) { List<int> compCardNumbers = CompCards.Select(card => card.Number).ToList(); // カードの番号の順列を生成する処理を別メソッドにまとめた(後述) List<ResultCards> resultCardsList = GetCardNumbersPermutation(compCardNumbers, cardCount); List<ResultCards> rets = new List<ResultCards>(); ResultCards NextBest = null; foreach (ResultCards resultCards in resultCardsList) { if(resultCards.Number < minValue) continue; if (resultCards.IsPrimeNumber != isPrimeNumber) continue; // コンピュータの手持ちのカードをすべて消費できるならそのまま出す(後述) if (CheckWinPutCards(compCardNumbers, resultCards)) return resultCards; // 次に出せるカードがあるか調べる処理も別メソッドにした(後述) if (CheckNextPutCards(compCardNumbers, resultCards)) rets.Add(resultCards); // ないなら次善策として保存しておく else if (NextBest == null) NextBest = resultCards; } // 次の一手になりうるものが見つからない場合は次善策として保存していたものを使う if (rets.Count == 0 && NextBest != null) return NextBest; // 本当に次の一手が存在しないならnullを返す if (rets.Count == 0 && NextBest == null) return null; // 偶数のカードをできるだけ残さないように最終的に出すカードを決める(後述) return GetBestResultCards(rets); } } |
別メソッドにまとめたカードの番号の順列を生成する処理をする部分です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class Form1 : Form { List<ResultCards> GetCardNumbersPermutation(List<int> compCardNumbers, int cardCount) { List<ResultCards> resultCardsList = new List<ResultCards>(); if (cardCount == 2 || cardCount == -1) resultCardsList.AddRange(GetCardsCanPut(compCardNumbers.ToArray(), 2)); if (cardCount == 3 || cardCount == -1) resultCardsList.AddRange(GetCardsCanPut(compCardNumbers.ToArray(), 3)); if (cardCount == 4 || cardCount == -1) resultCardsList.AddRange(GetCardsCanPut(compCardNumbers.ToArray(), 4)); if (cardCount == 1 || cardCount == -1) resultCardsList.AddRange(GetCardsCanPut(compCardNumbers.ToArray(), 1)); return resultCardsList; } } |
CheckWinPutCardsメソッドはResultCardsにオブジェクトに格納されている手でカードを全部出すことができるかどうかを判定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class Form1 : Form { bool CheckWinPutCards(List<int> compCardNumbers, ResultCards resultCards) { List<int> copyCompCardNumbers = new List<int>(compCardNumbers); foreach (int card in resultCards.CardNumbers1) copyCompCardNumbers.Remove(card); foreach (int card in resultCards.CardNumbers2) copyCompCardNumbers.Remove(card); if (copyCompCardNumbers.Count == 0) return true; else return false; } } |
次の手で勝利を決めることができないなら、次の手が存在する方法で手を作らなければなりません。CheckNextPutCardsはその候補手を選択した場合、次の手が存在するか調べます。
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 |
public partial class Form1 : Form { bool CheckNextPutCards(List<int> compCardNumbers, ResultCards resultCards) { // 次に出せるカードがあるか調べておく List<int> copyCompCardNumbers = new List<int>(compCardNumbers); foreach (int card in resultCards.CardNumbers1) copyCompCardNumbers.Remove(card); foreach (int card in resultCards.CardNumbers2) copyCompCardNumbers.Remove(card); if(copyCompCardNumbers.Count == 0) return true; else if (GetCardsCanPut(copyCompCardNumbers.ToArray(), 2).Count > 0) return true; else if (GetCardsCanPut(copyCompCardNumbers.ToArray(), 3).Count > 0) return true; else if (GetCardsCanPut(copyCompCardNumbers.ToArray(), 4).Count > 0) return true; else if (GetCardsCanPut(copyCompCardNumbers.ToArray(), 1).Count > 0) return true; else return false; } } |
候補手が複数存在する場合、偶数のカードばかり残るとやりにくいのでコンピュータには偶数のカードを使う手を優先させます。消費する偶数のカードがもっとも大きいものを次の一手としますが、それが複数存在する場合は乱数で決めます。奇数のカードしか使えない場合はそのなかからランダムに選びます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public partial class Form1 : Form { Random Random1 = new Random(); ResultCards GetBestResultCards(List<ResultCards> resultCards) { List<ResultCards> rets = resultCards.Where(x => x.CardNumbers1.Where(card => card % 2 == 0 && card != 2).ToList().Count > 0).ToList(); if (rets.Count > 0) { int max = rets.Max(x => x.CardNumbers1.Count(card => card % 2 == 0 && card != 2)); rets = resultCards.Where(x => x.CardNumbers1.Where(card => card % 2 == 0 && card != 2).ToList().Count == max).ToList(); return rets[Random1.Next(rets.Count)]; } else { return resultCards[Random1.Next(resultCards.Count)]; } } } |
指定された枚数のカードのすべての組み合わせからコンピュータの候補手をすべて取得する処理をするのがGetCardsCanPutメソッドです。ここでは数字の組み合わせが素数になるか、合成数の場合は合成数出しができる組み合わせを探します。この処理はGetPutCompositeNumberメソッドで行なっています。
またグロタンカットとラマヌジャン革命に対応させるために57 と 1729 は素数として扱っています。
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 |
public partial class Form1 : Form { List<ResultCards> GetCardsCanPut(int[] compCardNumbers, int cardCount) { List<ResultCards> ret = new List<ResultCards>(); List<ResultCards> notPrimeNumbers = new List<ResultCards>(); Permutation permutation = new Permutation(); // cardCount枚でつくることができるカードの順列をつくる // ここから生成される数を素数と合成数にわける List<int[]> arrayList1 = permutation.GetPermutations(compCardNumbers, cardCount).ToList(); foreach (int[] array1 in arrayList1) { long num = GetNumber(array1); // 57 と 1729 は素数と見なす if (IsPrimeNumber(num) || num == 57 || num == 1729) ret.Add( new ResultCards() { IsPrimeNumber = true, Number = num, CardNumbers1 = array1.ToList() } ); else notPrimeNumbers.Add(new ResultCards() { IsPrimeNumber = false, Number = num, CardNumbers1 = array1.ToList() }); } // 合成数は「合成数出し」ができるか調べる List<ResultCards> numbersCanPrimeFactors = GetPutCompositeNumber(notPrimeNumbers); ret.AddRange(numbersCanPrimeFactors); return ret; } } |
合成数の場合、GetPutCompositeNumberメソッドで「合成数出し」ができるか調べます。
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 80 |
public partial class Form1 : Form { List<ResultCards> GetPutCompositeNumber(List<ResultCards> notPrimeNumbers) { List<PrimeNumberCards> primeNumbers = new List<PrimeNumberCards>(); // 素因数分解に使うためのコンピュータが持っているカードで作れる素数を取得する // 結果はprimeNumbersに格納される Permutation permutation = new Permutation(); for (int i = 1; i <= 4; i++) { List<int> numbers = new List<int>(CompCards.Select(card => card.Number)); List<int[]> arrayList = permutation.GetPermutations(numbers, i).ToList(); ; foreach (int[] array in arrayList) { long num = GetNumber(array); if (IsPrimeNumber(num)) primeNumbers.Add(new PrimeNumberCards(num, array.ToList())); } } List<ResultCards> ret = new List<ResultCards>(); foreach (ResultCards notPrimeNumber in notPrimeNumbers) { long notPrimeNumber1 = notPrimeNumber.Number; // 合成数出しで1は認められないので却下 if (notPrimeNumber1 == 1) continue; foreach (PrimeNumberCards primeNumberCard in primeNumbers) { if (notPrimeNumber1 % primeNumberCard.PrimeNumber == 0) { notPrimeNumber1 /= primeNumberCard.PrimeNumber; notPrimeNumber.PrimeNumbers.Add(primeNumberCard.PrimeNumber); notPrimeNumber.CardNumbers2.AddRange(primeNumberCard.Cards); if (notPrimeNumber1 == 1) break; } } if (notPrimeNumber1 != 1) continue; bool CanPrimeFactorization = true; List<int> copyCompCardNumbers = new List<int>(CompCards.Select(card => card.Number)); foreach (int num in notPrimeNumber.CardNumbers1) { if (!copyCompCardNumbers.Remove(num)) { CanPrimeFactorization = false; break; } } if (!CanPrimeFactorization) continue; foreach (int num in notPrimeNumber.CardNumbers2) { if (!copyCompCardNumbers.Remove(num)) { CanPrimeFactorization = false; break; } } if (!CanPrimeFactorization) continue; ret.Add(notPrimeNumber); } return ret; } } |
ラマヌジャン革命
ラマヌジャン革命ですが、1729も素数出しの場合は素数として判定することようにアルゴリズムを変えます。またラマヌジャン革命が成立したらカードの強弱を変えるとともに、背景色を赤に変えます。赤は革命の色だからです。
Ramanujanプロパティ
こんなプロパティをつくります。最初はfalseにしておき、ゲーム中にラマヌジャン革命がおきたらtrueにします。もう一度ゲームをするときはfalseに再設定しなければなりません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class Form1 : Form { bool _ramanujan = false; bool Ramanujan { get { return _ramanujan; } set { _ramanujan = value; if (_ramanujan) this.BackColor = Color.Red; else this.BackColor = Color.Green; } } } |
プレイヤーに見せるメッセージの変更
プレイヤーが素数として1729を出したとき、ラマヌジャン革命がおきます。すでにラマヌジャン革命の状態のときは元に戻されます。それから次に出すカードをフィールド変数minValueに代入してそれ以上の数を出すようにしていました。革命のときはminValueよりも小さなカードを出さなければなりません。
変数名をいまさら変えられないので、minValue「以上」ではなく「より大きい」数を出さなければならず、革命時にはminValue「より小さい」数を出さなければならない仕様に変更します。
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 |
public partial class Form1 : Form { void CheckPlayerCards1(ref int cardCount, ref long minValue) { cardCount = CardsPutByPlayer1.Count; long number = GetNumber(CardsPutByPlayer1); string mes = ""; if (IsPrimeNumber(number) || number == 1729) { minValue = number; // カードを移動させる CardsPutByAll.AddRange(CardsPutByPlayer1); CardsPutByPlayer1.Clear(); if (number == 1729) Ramanujan = Ramanujan != true ? true : false; } else { mes = $"{number}は素数ではありません"; // 素数でない場合、カードは返却される PlayerCards.AddRange(CardsPutByPlayer1); CardsPutByPlayer1.Clear(); PlayerCards.OrderBy(card => card.Number).ToList(); ShowCards(); minValue = -1; cardCount = -1; } LabelPlayerErrer.Text = mes; } } |
コンピュータが1729を出してきたときの処理
コンピュータも1729を出してくる可能性があります。
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 partial class Form1 : Form { void CompPutCards(int cardCount, long minValue, ref int newCardCount, ref long newMinValue) { EableButtons(false); ResultCards resultCards = SearchNumber(false, cardCount, minValue); if (resultCards == null) resultCards = SearchNumber(true, cardCount, minValue); ShowResult(resultCards); if (resultCards == null) { newCardCount = -1; newMinValue = -1; Pass(); } else { // 革命になるのは素数として出されたときだけ // ただし現状ではコンピュータが1729を合成数として出すことはありえない if(resultCards.Number == 1729 && resultCards.IsPrimeNumber) Ramanujan = Ramanujan != true ? true : false; newCardCount = resultCards.CardNumbers1.Count; newMinValue = resultCards.Number; } EableButtons(true); } } |
出されたカードに対する評価の変更
革命がおきたら出せるカードを選ぶ方法も変えなければなりません。まずプレイヤー側ですが、CheckPlayerCards0メソッドを書き換えなければなりません。革命勃発時はコンピュータが作った数より小さくなければなりません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public partial class Form1 : Form { bool CheckPlayerCards0() { if (CountCardsPutMust != -1) { string str = ""; if (CountCardsPutMust != CardsPutByPlayer1.Count) str += $"場に出せるカードは{CountCardsPutMust}枚限定です。"; if (!Ramanujan && MinValueCards >= GetNumber(CardsPutByPlayer1)) str += $"場に出すカードでつくる数は{MinValueCards}より大きくなるようにしてください"; if (Ramanujan && MinValueCards <= GetNumber(CardsPutByPlayer1)) str += $"場に出すカードでつくる数は{MinValueCards}より小さくなるようにしてください"; LabelPlayerErrer.Text = str; if (str != "") return false; } return true; } } |
コンピュータがカードを選ぶ処理の変更
次にコンピュータがカードを選ぶときですが、これも同様にRamanujanプロパティがtrueか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 |
public partial class Form1 : Form { ResultCards SearchNumber(bool isPrimeNumber, int cardCount, long minValue) { List<int> compCardNumbers = CompCards.Select(card => card.Number).ToList(); List<ResultCards> resultCardsList = GetCardNumbersPermutation(compCardNumbers, cardCount); List<ResultCards> rets = new List<ResultCards>(); ResultCards NextBest = null; foreach (ResultCards resultCards in resultCardsList) { if(!Ramanujan && resultCards.Number <= minValue) continue; if (Ramanujan && resultCards.Number >= minValue) continue; if (resultCards.IsPrimeNumber != isPrimeNumber) continue; // コンピュータの手持ちのカードをすべて消費できるならそのまま出す if (CheckWinPutCards(compCardNumbers, resultCards)) return resultCards; // 次に出せるカードがあるか調べておく if (CheckNextPutCards(compCardNumbers, resultCards)) rets.Add(resultCards); // ないなら次善策として保存しておく else if (NextBest == null) NextBest = resultCards; } // 次の一手になりうるものが見つからない場合は次善策として保存していたものを使う if (rets.Count == 0 && NextBest != null) return NextBest; // 本当に次の一手が存在しないならnullを返す if (rets.Count == 0 && NextBest == null) return null; return GetBestResultCards(rets); } } |
プレイヤーのターンになったときに表示されるLabelのテキストも変更しなければなりません。これはプレイヤーが出すカードを決定するボタンをクリックしたときに最後に行なわれる処理です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public partial class Form1 : Form { void ShowNaviLabelText() { if (CountCardsPutMust != -1) { if(!Ramanujan) LabelMessage.Text = $"{CountCardsPutMust}枚のカードで{MinValueCards}より大きい数を出してください"; else LabelMessage.Text = $"{CountCardsPutMust}枚のカードで{MinValueCards}より小さい数を出してください"; } else LabelMessage.Text = $"コンピュータはパスをしました。あなたが親です。"; } } |
これはプレイヤーがパスをしたときの処理です。
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 |
public partial class Form1 : Form { async private void ButtonPass_Click(object sender, EventArgs e) { EableButtons(false); CheckBoxPrimeFactor.Checked = false; LabelPlayerErrer.Text = ""; PlayerText1 = ""; PlayerText2 = ""; LabelPlayer.Text = "あなた:"; Primefactors.Clear(); TempPrimefactors.Clear(); PlayerCards.AddRange(CardsPutByPlayer1); PlayerCards.AddRange(CardsPutByPlayer2); Pass(); PlayerCards = PlayerCards.OrderBy(card => card.Number).ToList(); ShowCards(); await Task.Delay(500); CompPutCards(-1, -1, ref CountCardsPutMust, ref MinValueCards); if (CheckCompWin()) return; if (CountCardsPutMust != -1) { if(!Ramanujan) LabelMessage.Text = $"{CountCardsPutMust}枚のカードで{MinValueCards}より大きい数を出してください"; else LabelMessage.Text = $"{CountCardsPutMust}枚のカードで{MinValueCards}より小さい数を出してください"; } else LabelMessage.Text = $"コンピュータもパスをしました。あなたが親です。"; EableButtons(true); } } |