static void waitAndUpdate(Draw draw, GameManager game, int wait, int state, List<bool> isBurst = null, List<Card> cantPutCard = null) { DX.ClearDrawScreen(); if (state >= 0) { draw.DrawGrid(); draw.DrawFieldCard(game); draw.DrawHandCard(game, -1, new Point()); draw.DrawState(game); draw.DrawBurst(game, isBurst); } DX.ScreenFlip(); DX.WaitVSync(wait); }
//プレイヤーの状態描画 public void DrawState(GameManager game) { //山札枚数 //1P uint deckCol = DX.GetColor(255, 255, 255); Point deck_1P = new Point(GridStart.X / 2 - cardScale.Width / 2, screenSize.Height - (int)(grid_len * 2) - cardScale.Height); string decknum_1P = game.deck[0].Count().ToString(); int decknumLen_1P = DX.GetDrawStringWidth(decknum_1P, decknum_1P.Length); DX.DrawBox(deck_1P.X, deck_1P.Y, deck_1P.X + cardScale.Width, deck_1P.Y + cardScale.Height, deckCol, 1); DX.DrawString(deck_1P.X + cardScale.Width / 2 - decknumLen_1P / 2, deck_1P.Y + cardScale.Height / 2- DX.GetFontSize()/2, decknum_1P, DX.GetColor(0, 0, 0)); //2P Point deck_2P = new Point(screenSize.Width/2 + (GridStart.X + (int)(grid_len * fieldSize.Width)) / 2 - cardScale.Width / 2, (int)(grid_len)); string decknum_2P = game.deck[1].Count().ToString(); int decknumLen_2P = DX.GetDrawStringWidth(decknum_2P, decknum_2P.Length); DX.DrawBox(deck_2P.X, deck_2P.Y, deck_2P.X + cardScale.Width, deck_2P.Y + cardScale.Height, deckCol, 1); DX.DrawString(deck_2P.X + cardScale.Width / 2 - decknumLen_2P / 2, deck_2P.Y + cardScale.Height / 2 - DX.GetFontSize() / 2, decknum_2P, DX.GetColor(0, 0, 0)); //現在のプレイヤー表示 string msg = (game.now_Player + 1) + "Pの番です"; int msg_len = DX.GetDrawStringWidth(msg, msg.Length); DX.DrawString(deck_2P.X - msg_len / 2, screenSize.Height / 2, msg, DX.GetColor(0, 255 * (game.is1P ? 1 : 0), 255 * (game.now_Player))); //メッセージ表示 int showMessage = 4; Point msgPt = new Point(GridStart.X + (int)(grid_len * (fieldSize.Width + 1)), deck_2P.Y + cardScale.Height+ DX.GetFontSize()); DX.DrawBox(msgPt.X, msgPt.Y, msgPt.X + DX.GetFontSize() * 8, msgPt.Y + DX.GetFontSize() * showMessage, DX.GetColor(128, 128, 128), 1); foreach(var elem in game.messageList.Reverse<string>().Take(showMessage).Select((v,i) => new { v, i })) { bool is1PDoc = elem.v.Contains("1P:"); DX.DrawString(msgPt.X, msgPt.Y + DX.GetFontSize() * elem.i, elem.v, DX.GetColor(0, 255 * (is1PDoc ? 1 : 0), 255 * (is1PDoc ? 0 : 1))); } //イニシエーション string init_1p = "1Pinit:" + (game.initiation[0] ? "可" : "不可"); string init_2p = "2Pinit:" + (game.initiation[1] ? "可" : "不可"); string skill_1p = "1PSkill:" + game.skillPt_1p.ToString(); string skill_2p = "2PSkill:" + game.skillPt_2p.ToString(); int init_1p_len = DX.GetDrawStringWidth(init_1p, init_1p.Length); int init_2p_len = DX.GetDrawStringWidth(init_2p, init_2p.Length); int skill_1p_len = DX.GetDrawStringWidth(skill_1p, skill_1p.Length); int skill_2p_len = DX.GetDrawStringWidth(skill_2p, skill_2p.Length); DX.DrawString(GridStart.X / 2 - init_1p_len / 2, screenSize.Height / 2-40, init_1p, DX.GetColor(255, 255, 255)); DX.DrawString(GridStart.X / 2 - init_2p_len / 2, screenSize.Height / 2- 20, init_2p, DX.GetColor(255, 255, 255)); DX.DrawString(GridStart.X / 2 - skill_1p_len / 2, screenSize.Height / 2 + 20, skill_1p, DX.GetColor(255, 255, 255)); DX.DrawString(GridStart.X / 2 - skill_2p_len / 2, screenSize.Height / 2 + 40, skill_2p, DX.GetColor(255, 255, 255)); }
//CPUの再帰用コンストラクタ public GameManager(GameManager game, List<Card>[] handCard) { myConstractor(game.cardNum, game.handCardNum, game.fieldSize, game.cardSize); for(int x = 0; x < game.fieldSize.Width; x++) { for (int y = 0; y < game.fieldSize.Height; y++) { field[x, y] = new Field(game.field[x, y]); } } initiation = (bool[])game.initiation.Clone(); now_Player = game.now_Player; for(int i = 0; i < handCard.Count(); i++) { this.handCard[i] = new List<Card>(handCard[i]); } }
//init public Draw(GameManager game) { fieldSize = game.fieldSize; cardSize = game.cardSize; //グリッドの色 LineCol = DX.GetColor(255, 255, 255); //グリッドの1マスのサイズ grid_len = screenSize.Height / (fieldSize.Height + 2); //グリッドの右上座標 GridStart = new Point((int)(screenSize.Width / 2 - grid_len * fieldSize.Width / 2), (int)grid_len); //属性の色 elementColDict = new Dictionary<int, uint>() { {0,DX.GetColor(255,0,0) },{1,DX.GetColor(0,0,255)},{2,DX.GetColor(0,0,0) },{3,DX.GetColor(0,255,0) },{4,DX.GetColor(255,255,0) } }; //カードの大きさ cardScale = new Size((int)(grid_len * cardSize.Width), (int)(grid_len * cardSize.Height)); }
//バースト時のカード枚数取得 public static int getSheetsNumber(GameManager game, int group) { int groupSum = 0; Size fieldSize = game.fieldSize; Size cardSize = game.cardSize; for (int x = 0; x < fieldSize.Width; x++) { for (int y = 0; y < fieldSize.Height; y++) { if (game.field[x, y].group == group) groupSum++; } } int cardProduct = cardSize.Width * cardSize.Height; int groupCardNum = groupSum / cardProduct; return groupCardNum; }
//バーストさせる public static int Burst(GameManager game, Size cardSize, int group) { int groupSum = 0; Size fieldSize = game.fieldSize; for (int x = 0; x < fieldSize.Width; x++) { for (int y = 0; y < fieldSize.Height; y++) { if (game.field[x, y].group == group) { game.field[x, y] = new Field(); groupSum++; } } } int cardProduct = cardSize.Width * cardSize.Height; int groupCardNum = groupSum / cardProduct; return groupCardNum; }
//バーストチェック public static bool isBurst(GameManager game, Size cardSize, int group) { Size fieldSize = game.fieldSize; Card card = new Card(group); for (int x = 0; x < fieldSize.Width; x++) { for (int y = 0; y < fieldSize.Height; y++) { for (int turn = 0; turn < 2; turn++) { Size mycardSize = cardSize; if (turn % 2 == 1) { mycardSize = new Size(cardSize.Height, cardSize.Width); } card.turn = turn; if (canPut(game.field, new Point(x, y), card, mycardSize, group, game.initiation, true)) { card.turn = 0; return false; } } } } return true; }
static void Main(string[] args) { Size fieldSize = new Size(18, 24); Size cardSize = new Size(4, 6); int deckNum = 15; int handCardNum = 3; int wait = 60; bool isCPU = false; GameManager game = new GameManager(deckNum, handCardNum, fieldSize, cardSize); Draw draw = new Draw(game); CPU cpu = new CPU(0); DX.ChangeWindowMode(1); DX.DxLib_Init(); DX.SetGraphMode(1280, 720, 32); DX.SetDrawScreen(DX.DX_SCREEN_BACK); //山札のロード Card.LoadDeck(); //ゲームの状態 int state = -1; //移動中の手札の番号 int moving_hand_cur = -1; //前の人が詰んでいたか bool[] isAlreadyCheckmate = new bool[game.max_Player]; int mouse_state = 0; int wheel; string[] deckIndexes = new string[game.max_Player]; //置ける場所の候補 List<Card> candidates = new List<Card>(); while (DX.ScreenFlip() == 0 && DX.ProcessMessage() == 0 && DX.ClearDrawScreen() == 0) { Point mousePoint; int hand_cur = -1; mouse_state = getMouse(out mousePoint); if(mousePoint==new Point()) { //マウス座標 int mx = 0, my = 0; DX.GetMousePoint(out mx, out my); mousePoint = new Point(mx, my); } if (state >= 0) { //描画 draw.DrawGrid(); draw.DrawFieldCard(game); draw.DrawAssist(game, candidates, moving_hand_cur); hand_cur = draw.DrawHandCard(game, moving_hand_cur, mousePoint); } switch (state) { case -2://設定 wheel = DX.GetMouseWheelRotVol(); draw.DrawSetting(game, mousePoint, wheel, ref deckIndexes); if (clickedLeft(ref mouse_state)) state = -1; break; case -1://タイトル wheel = DX.GetMouseWheelRotVol(); if (wheel != 0) isCPU = !isCPU; draw.DrawTitle(isCPU); if (clickedLeft(ref mouse_state)) state = 0; if (clickedRight(ref mouse_state)) state = -2; break; case 0://初期化 draw = new Draw(game); game = new GameManager(deckNum, handCardNum, fieldSize, cardSize, deckIndexes); if (isCPU) cpu = new CPU(1); //置ける場所の候補取得 candidates = Field.getCandidates(game); state = 1; break; case 1://手札選択 if (isCPU && game.now_Player == cpu.me) { state = 5; } if (clickedLeft(ref mouse_state) && hand_cur != -1 && game.nowHandCard[hand_cur].available) { moving_hand_cur = hand_cur; state = 2; } break; case 2://手札移動 Point fieldPt = draw.DrawMovingCard(game, moving_hand_cur, mousePoint); bool clicked = clickedLeft(ref mouse_state); //回転 wheel = DX.GetMouseWheelRotVol(); if (wheel > 0) game.nowHandCard[moving_hand_cur].turn = (game.nowHandCard[moving_hand_cur].turn + 1) % 4; if (wheel < 0) game.nowHandCard[moving_hand_cur].turn = (game.nowHandCard[moving_hand_cur].turn + 3) % 4; //フィールドに配置 if (clicked && fieldPt != new Point(-1,-1)) { if (!game.handToField(fieldPt, moving_hand_cur)) break; moving_hand_cur = -1; //勝利判定 if (Enumerable.Range(0, game.max_Player).Select(player => game.deck[player].Count() + game.handCard[player].Count()).Count(allCards => allCards == 0) > 0) { state = 4; break; } //手番交代 //waitAndUpdate(draw, game, wait, state); game.next(); state = 3; break; } //移動をやめる if (clicked && hand_cur != -1) { moving_hand_cur = -1; state = 1; } break; case 3://詰み・バーストチェック //バースト bool[] isBurst = new bool[] { false, false }; for (int i = 0; i < game.max_Player; i++) { if (Field.isBurst(game, cardSize, i)) { isBurst[i] = true; } } if (isBurst.Count(t => t) != 0) { waitAndUpdate(draw, game, wait, state, isBurst: isBurst.ToList()); } for (int i = 0; i < 2; i++) { if (isBurst[i]) { game.burst(i); } } if (isBurst.Count(t => t == true) != 0) { //手番を戻す game.next(); game.insertInfo("バースト"); state = 1; } //ドロー game.draw(); //詰み candidates = Field.getCandidates(game); if (candidates.Count() == 0) { if (isAlreadyCheckmate.Count(t => t) >= game.max_Player) { game.insertInfo("両詰み"); waitAndUpdate(draw, game, wait, state, isBurst: Enumerable.Range(0, game.max_Player).Select(t => true).ToList()); isAlreadyCheckmate = new bool[game.max_Player]; game.clearField(); //手番を戻す game.next(); candidates = Field.getCandidates(game); state = 1; } else { game.insertInfo("詰み"); isAlreadyCheckmate[game.now_Player] = true; waitAndUpdate(draw, game, wait, state); //手番を戻す game.next(); state = 3; } } else { isAlreadyCheckmate[game.now_Player] = false; state = 1; } break; case 4://勝利 draw.DrawWinnerMessage((game.now_Player + 1) + "P WIN!!!!"); if (clickedLeft(ref mouse_state)) { state = -1; } break; case 5://CPU選択 var cpu_res = cpu.choice(game); int cardCur = game.nowHandCard.IndexOf(game.nowHandCard.Where(t => t.handCardID == cpu_res.card.handCardID).First()); //CPUの手の回転 game.handCard[game.now_Player][cardCur].turn = cpu_res.card.turn; if (!game.handToField(cpu_res.card.point, cardCur)) throw new Exception("CPU fatal error"); //勝利判定 if (Enumerable.Range(0, game.max_Player).Select(player => game.deck[player].Count() + game.handCard[player].Count()).Count(allCards => allCards == 0) > 0) { state = 4; break; } //手番交代 waitAndUpdate(draw, game, wait, state); game.next(); state = 3; break; } if (state >= 0) draw.DrawState(game); } DX.DxLib_End(); }
//バースト表示 public void DrawBurst(GameManager game, List<bool> isBurst) { if (isBurst == null || isBurst.Count(t => t) == 0) return; List<int> burstNum = Enumerable.Range(0, isBurst.Count()).Where(t => isBurst[t]).ToList(); for (int x = 0; x < fieldSize.Width; x++) { for (int y = 0; y < fieldSize.Height; y++) { Card card = game.field[x, y].card; if (card != null && burstNum.Contains(game.field[x, y].group)) { Size mycardSize = new Size(game.cardSize.Width, game.cardSize.Height); if (card.turn % 2 == 1) mycardSize = new Size(mycardSize.Height, mycardSize.Width); DX.DrawBox(GridStart.X + (int)(grid_len * x), GridStart.Y + (int)(grid_len * y), GridStart.X + (int)(grid_len * (x + mycardSize.Width)), GridStart.Y + (int)(grid_len * (y + mycardSize.Height)), DX.GetColor(255, 0, 0), 1); } } } }
//カード配置 public static bool putCard(GameManager game, Point putAt, Card card, Size cardSize, bool[] initiation) { Field[,] field = game.field; Size fieldSize = game.fieldSize; int turn = card.turn; //カードサイズをターンにあわせる Size mycardSize = cardSize; if (turn % 2 == 1) { mycardSize = new Size(cardSize.Height, cardSize.Width); } //前回のイニシエーション保存 bool[] oldInitiation = new bool[] { initiation[0], initiation[1] }; //設置判定 if (!canPut(field, putAt, card, mycardSize, game.now_Player, initiation)) return false; if (isLowBurst(game, putAt, card, mycardSize)) { //イニシエーションの場合は取り消し int init_group = game.now_Player; if (initiation[init_group] != oldInitiation[init_group]) initiation[init_group] = true; return false; } //カード配置 fillCard(game.field, putAt, card, mycardSize); return true; }
/// <summary> /// 手を選ぶ /// </summary> /// <param name="game"></param> /// <returns></returns> public resultSet choice(GameManager game) { cardSize = game.cardSize; GameManager newGame = new GameManager(game, game.handCard); superGame = game; int step = 1; //if (game.initiation[0] == true && game.initiation[1] == true) step = 4; resultSet[] bestPat = getScore(newGame, step: step); Console.WriteLine(string.Join("/", bestPat.Select(t => t.score.ToString()))); return bestPat[game.now_Player]; }
public void DrawSetting(GameManager game,Point mouse, int wheel, ref string[] deck) { if (DeckIndex == null || DeckIndex.Length != game.max_Player) DeckIndex = new int[game.max_Player]; List<string> deckList = new List<string>() {"ランダム" }; deckList.AddRange(Card.deckList.Keys); int fontSize = 32; int defaultFontSize = DX.GetFontSize(); DX.SetFontSize(fontSize); Point settingStart = new Point(fieldSize.Width / 3, fieldSize.Height / 3); for(int i = 0; i < game.max_Player; i++) { DX.DrawString(settingStart.X, settingStart.Y + fontSize * 2 * i, (i + 1) + "Pデッキ", DX.GetColor(255, 255, 255)); //デッキ情報の開始位置 Point deck_start = new Point(settingStart.X, settingStart.Y + fontSize * (i * 2 + 1)); deck[i] = deckList[DeckIndex[i]]; //デッキ情報のサイズ Size deck_size = new Size(DX.GetDrawStringWidth(deck[i], deck[i].Length), fontSize); //move index if (mouse.X >= deck_start.X && mouse.X < deck_start.X + deck_size.Width && mouse.Y >= deck_start.Y && mouse.Y < deck_start.Y + deck_size.Height) { if (wheel > 0) DeckIndex[i] = (DeckIndex[i] + 1) % deckList.Count(); if (wheel < 0) DeckIndex[i] = (DeckIndex[i] + deckList.Count() - 1) % deckList.Count(); } //デッキ情報描画 DX.DrawString(deck_start.X, deck_start.Y, deck[i], DX.GetColor(255, 0, 255)); if (deck[i] == "ランダム") deck[i] = ""; } DX.SetFontSize(defaultFontSize); }
//フィールド上のカード描画 public void DrawFieldCard(GameManager game) { for (int x = 0; x < fieldSize.Width; x++) { for (int y = 0; y < fieldSize.Height; y++) { if (game.field[x, y].card != null) { DrawCard((int)(GridStart.X + grid_len * x), (int)(GridStart.Y + grid_len * y), game.field[x, y].card); } //デバッグ用描画処理 /* if (game.field[x, y].group != -1) { DX.DrawBox((int)(GridStart.X + grid_len * x), (int)(GridStart.Y + grid_len * y), (int)(GridStart.X + grid_len * (x + 1)), (int)(GridStart.Y + grid_len * (y + 1)), game.field[x, y].group==0?DX.GetColor(0, 0, 0): DX.GetColor(255, 255, 255), 1); } if (game.field[x, y].connector != -1) { DX.DrawBox((int)(GridStart.X + grid_len * x), (int)(GridStart.Y + grid_len * y), (int)(GridStart.X + grid_len * (x + 1)), (int)(GridStart.Y + grid_len * (y + 1)), elementColDict[game.field[x, y].connector], 1); }*/ } } }
//移動中のカード描画 public Point DrawMovingCard(GameManager game, int hand_cur, Point mouse) { bool is1P = game.is1P; Card card = game.nowHandCard[hand_cur]; int x = 0, y = 0, fix_x = 0, fix_y = 0; Point fieldPt = new Point(-1, -1); //カードの中心座標を取得 x = mouse.X - cardScale.Width / 2; y = mouse.Y - cardScale.Height / 2; fix_x = cardSize.Width - 1; fix_y = cardSize.Height - 1; if (card.turn % 2 == 1) { x = mouse.X - cardScale.Height / 2; y = mouse.Y - cardScale.Width / 2; fix_x = cardSize.Height - 1; fix_y = cardSize.Width - 1; } //グリッドにフィットさせる if (x >= GridStart.X && y >= GridStart.Y && x < GridStart.X + grid_len * (fieldSize.Width - fix_x) && y < GridStart.Y + grid_len * (fieldSize.Height - fix_y)) { fieldPt = new Point((int)((x - GridStart.X) / grid_len), (int)((y - GridStart.Y) / grid_len)); x = fieldPt.X * (int)grid_len + GridStart.X; y = fieldPt.Y * (int)grid_len + GridStart.Y; } DrawCard(x, y, card); return fieldPt; }
//手札描画 public int DrawHandCard(GameManager game, int hand_cur, Point mouse) { int cardOnMouseNum = -1; bool is1P = game.is1P; List<Card> card_1p = game.handCard[0]; List<Card> card_2p = game.handCard[1]; int handCard_width = GridStart.X / game.handCardNum; Size handCard_size = new Size(handCard_width, handCard_width / 2 * 3); Point HandCardStart_1P = new Point((int)(GridStart.X + grid_len * fieldSize.Width) + 1, (int)(GridStart.Y + grid_len * fieldSize.Height - handCard_size.Height)); for (int i = 0; i < card_1p.Count(); i++) { int x = HandCardStart_1P.X + handCard_size.Width * i; int y=HandCardStart_1P.Y; if (is1P && mouse.X >= x && mouse.X < x + handCard_size.Width && mouse.Y >= y && mouse.Y < y + handCard_size.Height) cardOnMouseNum = i; if (is1P && i == hand_cur) continue; DrawCard(x, y, card_1p[i], handCard_size); } Point HandCardStart_2P = new Point(0, (int)grid_len); for (int i = 0; i < card_2p.Count(); i++) { int x = HandCardStart_2P.X + handCard_size.Width * i; int y = HandCardStart_2P.Y; if (!is1P && mouse.X >= x && mouse.X < x + handCard_size.Width && mouse.Y >= y && mouse.Y < y + handCard_size.Height) cardOnMouseNum = i; if (!is1P && i == hand_cur) continue; DrawCard(x, y, card_2p[i], handCard_size); } return cardOnMouseNum; }
//低バーストチェック public static bool isLowBurst(GameManager game, Point putAt, Card card, Size cardSize) { //一時的に埋める int tmpConnect = fillCard(game.field, putAt, card, cardSize); bool tmpInit = game.initiation[tmpConnect]; game.initiation[tmpConnect] = false; for (int i = 0; i < game.max_Player; i++) { //バーストチェック if (!isBurst(game, cardSize, i)) { continue; } //バースト枚数取得 int groupCardNum = getSheetsNumber(game, i); if (groupCardNum < 3) { //埋めを解除 unfillCard(game.field, putAt, cardSize); //判定コネクターを戻す connector_group = tmpConnect; game.initiation[tmpConnect] = tmpInit; return true; } } //埋めを解除 unfillCard(game.field, putAt, cardSize); //判定コネクターを戻す connector_group = tmpConnect; game.initiation[tmpConnect] = tmpInit; return false; }
/// <summary> /// 配置可能場所リスト生成 /// </summary> /// <param name="game"></param> /// <returns></returns> public static List<Card> getCandidates(GameManager game) { //候補 List<Card> candidates = new List<Card>(); Size cardSize = game.cardSize; Size fieldSize = game.fieldSize; foreach (var card in game.nowHandCard) { if (card == null) continue; card.available = false; for (int x = 0; x < fieldSize.Width; x++) { for (int y = 0; y < fieldSize.Height; y++) { for (int turn = 0; turn < 4; turn++) { Size mycardSize = cardSize; if (turn % 2 == 1) { mycardSize = new Size(cardSize.Height, cardSize.Width); } card.turn = turn; if (canPut(game.field, new Point(x, y), card, mycardSize, game.now_Player, game.initiation, true)) { //低バーストでもない場合は候補に追加 if (!isLowBurst(game, new Point(x, y), card, mycardSize)) { Card cand = new Card(card); cand.point = new Point(x, y); candidates.Add(cand); card.available = true; } } } } } card.turn = 0; } return candidates; }
/// <summary> /// 再帰で最適解を求める /// </summary> /// <param name="game"></param> /// <param name="nest"></param> /// <param name="isMe"></param> /// <param name="step"></param> /// <returns></returns> resultSet[] getScore(GameManager game, int nest = 0, int step = 1) { //手札がない if (game.handCard[game.now_Player].Count()==0) { return new resultSet[game.max_Player]; } //手の候補取得 List<Card> candidates = Field.getCandidates(game); Field[,] field = game.field; Size fieldSize = game.fieldSize; //候補のスコア List<resultSet[]> scores = new List<resultSet[]>(); foreach (var card_vi in candidates.Select((v,i)=>new { v,i})) { Card card = card_vi.v; if (nest == 0 && game.now_Player == me) { //パーセンテージを表示 Console.Write("{0, 4:f0}%", (double)(card_vi.i + 1) / candidates.Count() * 100); Console.SetCursorPosition(0, Console.CursorTop); } if (card == null) continue; //カードサイズを回転に合わせる Size mycardSize = new Size(cardSize.Width, cardSize.Height); if (card.turn % 2 == 1) mycardSize = new Size(mycardSize.Height, mycardSize.Width); //コネクターグループ設置用 List<bool> tmpInit = new List<bool>(game.initiation); if (!Field.canPut(game.field, card.point, card, mycardSize, game.now_Player, game.initiation)) throw new Exception("checkmate fatal error"); //手札を減らす /* List<Card> innerHandCard = new List<Card>(myHandCard); var rmIndex = innerHandCard.IndexOf(innerHandCard.Where(t => t != null && t.handCardID == card.handCardID).First()); innerHandCard[rmIndex] = null;*/ List<Card>[] innerHandCard = game.handCard.Select(cards => cards.Select(t => t == null ? null : new Card(t)).ToList()).ToArray(); var rmIndex = innerHandCard[game.now_Player].IndexOf(innerHandCard[game.now_Player].Where(t => t != null && t.handCardID == card.handCardID).First()); innerHandCard[game.now_Player][rmIndex] = null; //フィールドに手札を置く GameManager innerGame = new GameManager(game, innerHandCard); int tmpConnect = Field.fillCard(innerGame.field, card.point, card, mycardSize); innerGame.next(); resultSet[] cand = new resultSet[game.max_Player]; for(int i = 0; i < game.max_Player; i++) { cand[i] = new resultSet(); } if (superGame.deck[game.now_Player].Count() == 0 && innerGame.handCard[game.now_Player].Count(t => t != null) == 0) { //勝利の場合 cand[game.now_Player].score += 10000.0 - 1000.0 / (nest / game.max_Player + 1); } else if (Field.isBurst(innerGame, cardSize, tmpConnect)) { //バーストチェック int burstNum = Field.Burst(innerGame, cardSize, tmpConnect); cand[game.now_Player].score += (1000.0 + (burstNum - 3) * 10.0) - 100.0 / (nest / game.max_Player + 1); innerGame.next(); var tmpcand = getScore(innerGame, nest: nest + 1, step: 1); cand[game.now_Player].innerResult = tmpcand; cand[game.now_Player].isBurst = true; } else { //バーストしない場合再帰 int initCount = superGame.initiation.Count(t => t == true); if (initCount == 0 || initCount == 1 && nest <= 1 || nest <= 0) cand = getScore(innerGame, nest: nest + 1, step: 1); } //カード情報を候補に追加 cand[game.now_Player].card = new Card(card); scores.Add(cand); //イニシエーション戻す game.initiation = new bool[game.max_Player]; for (int i = 0; i < game.max_Player; i++) { game.initiation[i] = tmpInit[i]; } } //候補から最善手を予測 var noPlayerRange = Enumerable.Range(0, game.max_Player).Where(player => player != game.now_Player); resultSet[] bestPattern = new resultSet[game.max_Player]; if (scores.Count() > 0) { var scorePair = scores.Select(result => new { v = result, score = (result[game.now_Player].score / noPlayerRange.Select(player => result[player].score).Sum()) }); var filtered = scorePair.Where(t => t.v[game.now_Player].innerResult == null || (!t.v[game.now_Player].innerResult[game.now_Player].isCheckmate && !t.v[game.now_Player].isCheckmate)); //if (filtered.Count() == 0) { bestPattern = scorePair.OrderByDescending(t => t.score).First().v; } /*else { bestPattern = filtered.OrderByDescending(t => t.score).First().v; }*/ } else { for (int i = 0; i < game.max_Player; i++) { bestPattern[i] = new resultSet(); } } //自分の手数を追加 bestPattern[game.now_Player].score += candidates.Count(); //詰みの場合ほかの人がボーナス if (nest != 0 && candidates.Count() == 0) { bestPattern[game.now_Player].isCheckmate = true; for (int i = 0; i < game.max_Player; i++) { if (i == game.now_Player) continue; bestPattern[i].score += 1000.0 - 100.0 / (nest / game.max_Player + 1); } } return bestPattern; }
//バーストチェック public static bool isBurst(GameManager game, Size cardSize, int group, List<int> ignoreGroup = null) { Size fieldSize = game.fieldSize; //最初の呼び出しは再帰に自分を含めない if (ignoreGroup == null) { ignoreGroup = new List<int>(); ignoreGroup.Add(group); } Card card = new Card(group); for (int x = 0; x < fieldSize.Width; x++) { for (int y = 0; y < fieldSize.Height; y++) { for (int turn = 0; turn < 2; turn++) { Size mycardSize = cardSize; if (turn % 2 == 1) { mycardSize = new Size(cardSize.Height, cardSize.Width); } card.turn = turn; if (canPut(game.field, new Point(x, y), card, mycardSize, group, game.initiation, true)) { card.turn = 0; return false; } } } } return true; }
//アシスト表示 public void DrawAssist(GameManager game, List<Card> candidates, int handCardCur) { if (handCardCur < 0) return; foreach (var card in candidates) { if (card.handCardID != game.nowHandCard[handCardCur].handCardID || card.turn != game.nowHandCard[handCardCur].turn) continue; Size mycardSize = new Size(game.cardSize.Width, game.cardSize.Height); if (card.turn % 2 == 1) mycardSize = new Size(mycardSize.Height, mycardSize.Width); DX.DrawBox(GridStart.X + (int)(grid_len * card.point.X), GridStart.Y + (int)(grid_len * card.point.Y), GridStart.X + (int)(grid_len * (card.point.X + mycardSize.Width)), GridStart.Y + (int)(grid_len * (card.point.Y + mycardSize.Height)), DX.GetColor(0, 128, 0), 1); } }