//カードのクローン public Card(Card card) { elems = new List<int>(card.elems); imgPath = card.imgPath; point = new Point(card.point.X, card.point.Y); turn = card.turn; handCardID = card.handCardID; testCard = card.testCard; }
/// <summary> /// コネクターに連結可能か判定 /// card.TestCard==trueの場合はコネクターの属性を無視 /// </summary> /// <param name="field"></param> /// <param name="putAt"></param> /// <param name="card"></param> /// <param name="mycardSize">回転に合わせたカードサイズ</param> /// <returns></returns> static bool canConnect(Field[,] field, Point putAt, Card card, Size mycardSize) { Size fieldSize = new Size(field.GetLength(0), field.GetLength(1)); List<int> elems = card.elems; int turn = card.turn; for (int i = 0; i < 4; i++) { if (elems[i] == -1 && card.testCard == -1) continue; int sx, sy; switch ((i + turn) % 4) { case 0: sx = putAt.X + mycardSize.Width / 2 - 1; sy = putAt.Y - 1; if (sy < 0) continue; connector_group = field[sx, sy].group; if (card.testCard == -1 && field[sx, sy].connector == elems[i] && field[sx + 1, sy].connector == elems[i] || card.testCard != -1 && field[sx, sy].group == card.testCard &&//テストカード field[sx + 1, sy].group == card.testCard && field[sx, sy].connector != -1 && field[sx + 1, sy].connector != -1) return true; break; case 1: sx = putAt.X + mycardSize.Width; sy = putAt.Y + mycardSize.Height / 2; if (sx >= fieldSize.Width) continue; connector_group = field[sx, sy].group; if (card.testCard == -1 && field[sx, sy].connector == elems[i] && field[sx, sy - 1].connector == elems[i] || card.testCard != -1 && field[sx, sy].group == card.testCard &&//テストカード field[sx, sy - 1].group == card.testCard && field[sx, sy].connector != -1 && field[sx, sy - 1].connector != -1) return true; break; case 2: sx = putAt.X + mycardSize.Width / 2 - 1; sy = putAt.Y + mycardSize.Height; if (sy >= fieldSize.Height) continue; connector_group = field[sx, sy].group; if (card.testCard == -1 && field[sx, sy].connector == elems[i] && field[sx + 1, sy].connector == elems[i] || card.testCard != -1 && field[sx, sy].group == card.testCard &&//テストカード field[sx + 1, sy].group == card.testCard && field[sx, sy].connector != -1 && field[sx + 1, sy].connector != -1) return true; break; case 3: sx = putAt.X - 1; sy = putAt.Y + mycardSize.Height / 2 - 1; if (sx < 0) continue; connector_group = field[sx, sy].group; if (card.testCard == -1 && field[sx, sy].connector == elems[i] && field[sx, sy + 1].connector == elems[i] || card.testCard != -1 && field[sx, sy].group == card.testCard &&//テストカード field[sx, sy + 1].group == card.testCard && field[sx, sy].connector != -1 && field[sx, sy + 1].connector != -1) return true; break; } } return false; }
//カード配置 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 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; }
//低バーストチェック 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="field"></param> /// <param name="putAt"></param> /// <param name="card"></param> /// <param name="mycardSize"></param> /// <returns></returns> public static int fillCard(Field[,] field, Point putAt, Card card, Size mycardSize) { if (connector_group == -1) throw new Exception("connector group is -1"); List<int> elems = card.elems; int turn = card.turn; //コネクター配置 for (int i = 0; i < elems.Count(); i++) { if (elems[i] == -1) continue; int sx, sy; switch ((i + turn) % 4) { case 0: sx = putAt.X + mycardSize.Width / 2 - 1; sy = putAt.Y; field[sx, sy].connector = elems[i]; field[sx + 1, sy].connector = elems[i]; break; case 1: sx = putAt.X + mycardSize.Width - 1; sy = putAt.Y + mycardSize.Height / 2; field[sx, sy].connector = elems[i]; field[sx, sy - 1].connector = elems[i]; break; case 2: sx = putAt.X + mycardSize.Width / 2 - 1; sy = putAt.Y + mycardSize.Height; field[sx, sy - 1].connector = elems[i]; field[sx + 1, sy - 1].connector = elems[i]; break; case 3: sx = putAt.X; sy = putAt.Y + mycardSize.Height / 2 - 1; field[sx, sy].connector = elems[i]; field[sx, sy + 1].connector = elems[i]; break; } } //グループ化 for (int x = 0; x < mycardSize.Width; x++) { for (int y = 0; y < mycardSize.Height; y++) { field[putAt.X + x, putAt.Y + y].group = connector_group; } } //カード配置 field[putAt.X, putAt.Y].card = card; int tmpConnector = connector_group; connector_group = -1; return tmpConnector; }
public Field(Field field) { card = field.card; connector = field.connector; group = field.group; }
//バーストチェック 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; }
//配置可能判定 public static bool canPut(Field[,] field, Point putAt, Card card, Size mycardSize, int now_Player, bool[] initiation, bool isJudge = false) { Size fieldSize = new Size(field.GetLength(0), field.GetLength(1)); //衝突判定 if (collision(field, putAt, mycardSize)) return false; //イニシエーション可能 if (initiation[now_Player] && (now_Player % 2 == 0 && putAt.Y == fieldSize.Height - mycardSize.Height || now_Player % 2 == 1 && putAt.Y == 0)) { if (!isJudge) initiation[now_Player] = false; connector_group = now_Player; return true; } //属性連結可能 if (canConnect(field, putAt, card, mycardSize)) return true; return false; }
//バーストチェック 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 resultSet() { score = 1.0; card = new Card(); }
//カード描画 public void DrawCard(int x, int y, Card card, Size cardScale = new Size()) { List<int> elems = card.elems; int turn = card.turn; if (cardScale == new Size()) cardScale = new Size(this.cardScale.Width + 1, this.cardScale.Height + 1); Size cardScaleOrg = new Size((Point)cardScale); if (turn % 2 == 1) cardScale = new Size(cardScale.Height, cardScale.Width); uint col = DX.GetColor(128, 128, 128); if (card.imgPath == "") DX.DrawBox(x, y, x + cardScale.Width, y + cardScale.Height, col, 1); else { int myx = x; int myy = y; if (turn >= 2 && turn <= 3) myy += cardScale.Height; if (turn >= 1 && turn <= 2) myx += cardScale.Width; int h, w; DX.GetGraphSize(Card.CardGraphDic[card.imgPath], out w, out h); DX.DrawRotaGraph3(myx, myy, 0, 0, (double)cardScaleOrg.Width / w, (double)cardScaleOrg.Height / h, turn * Math.PI / 2.0, Card.CardGraphDic[card.imgPath], 0); } DX.DrawBox(x, y, x + cardScale.Width, y + cardScale.Height, DX.GetColor(256, 256, 256), 0); int defaultFontSize = DX.GetFontSize(); int myFontSize = (int)Math.Sqrt(cardScale.Width * cardScale.Height / 32); DX.SetFontSize(myFontSize); for (int i = 0; i < elems.Count(); i++) { if (elems[i] == -1) continue; int sx = 0, sy = 0; int strwidth = DX.GetDrawStringWidth(elementDict[elems[i]], elementDict[elems[i]].Length); switch ((i + turn) % 4) { case 0: sx = x + cardScale.Width / 2 - strwidth / 2; sy = y; break; case 1: sx = x + cardScale.Width - strwidth; sy = y + cardScale.Height / 2 - strwidth / 2; break; case 2: sx = x + cardScale.Width / 2 - strwidth / 2; sy = y + cardScale.Height - strwidth; break; case 3: sx = x; sy = y + cardScale.Height / 2 - strwidth / 2; break; } int fontSize = DX.GetFontSize(); DX.DrawBox(sx, sy, sx + fontSize + 1, sy + fontSize + 1, DX.GetColor(255, 255, 255) - elementColDict[elems[i]], 0); DX.DrawBox(sx, sy, sx + fontSize, sy + fontSize, elementColDict[elems[i]], 1); DX.DrawString(sx + 1, sy + 1, elementDict[elems[i]], DX.GetColor(0, 0, 0)); DX.DrawString(sx, sy, elementDict[elems[i]], DX.GetColor(255, 255, 255)); } DX.SetFontSize(defaultFontSize); if (!card.available) { DX.DrawQuadrangle(x, y, x + (int)grid_len, y, x + cardScale.Width, y + cardScale.Height, x + cardScale.Width - (int)grid_len, y + cardScale.Height, DX.GetColor(255, 0, 0), 1); DX.DrawQuadrangle(x + cardScale.Width - (int)grid_len, y, x + cardScale.Width, y, x + (int)grid_len, y + cardScale.Height, x, y + cardScale.Height, DX.GetColor(255, 0, 0), 1); } }