//=======================// //Разрабатываемые функции// //=======================// private void Standardize(ref MTable.SBone domino) { if (domino.First > domino.Second) { domino.Exchange(); } }
public List <MTable.SBone> ListWithout(List <MTable.SBone> list, MTable.SBone b) { List <MTable.SBone> tmp = new List <MTable.SBone>(); tmp.AddRange(list); tmp.Remove(b); return(tmp); }
private void RemoveTile(MTable.SBone tile) // Удаляет переданную кость из руки { for (int i = 0; i < lHand.Count; i++) { if (lHand[i].First == tile.First && lHand[i].Second == tile.Second) { lHand.Remove(lHand[i]); return; } } }
public void GenerateDomino(List <MTable.SBone> NullDomino) { List <MTable.SBone> AllDomino = new List <MTable.SBone>(); for (ushort i = 1; i <= 6; i++) { for (ushort j = 1; j <= 6; j++) { MTable.SBone Domino = new MTable.SBone(); Domino.First = i; Domino.Second = j; AllDomino.Add(Domino); } } }
private void SaveTable(ref MTable.SBone domino, bool end, int iEnemyBoneCount, ushort number) { if (end) { _pRight = domino; if (number != _pRight.First) { _pRight.Exchange(); } } else { _pLeft = domino; if (number != _pLeft.Second) { _pLeft.Exchange(); } } _pEnemyBoneCount = iEnemyBoneCount; }
public bool DecideSide(MTable.SBone sb, int leftest, int rightest, int[] probs) { if (sb.First == leftest && sb.Second == rightest) // Если можно и так, и так { return(probs[sb.First] >= probs[sb.Second]); // Чтобы у наружней был больше шанс не оказаться в руке соперника } else if (sb.First == rightest && sb.Second == leftest) // то же, но наоборот { return(probs[sb.First] <= probs[sb.Second]); } else if (sb.First == sb.Second) // Если они равны { return(sb.First == rightest); } else if (sb.First == leftest || sb.First == rightest) // если только первую { return(sb.First == rightest); } else // if (sb.Second == leftest || sb.Second == rightest) // Если только вторую { return(sb.Second == rightest); } }
public STiles(MTable.SBone tile, int[] vals, int leftest, int rightest) { this.tile = tile; int sc1 = vals[tile.First], sc2 = vals[tile.Second]; if (tile.First == leftest && tile.First == rightest) // Если левая подходит в оба { wEnemyHasnt = sc2; } else if (tile.Second == leftest && tile.Second == rightest) // Если правая подходит в оба { wEnemyHasnt = sc1; } else if (tile.First == leftest && tile.Second == rightest || tile.Second == leftest && tile.Second == rightest) // Если подходят обе { wEnemyHasnt = Math.Max(sc1, sc2); } else if (tile.Second == leftest || tile.Second == rightest) // Если подходит только вторая { wEnemyHasnt = sc1; } else if (tile.First == leftest || tile.First == rightest) // Если подходит только первая { wEnemyHasnt = sc2; } wSpots = tile.First + tile.Second; if (wSpots == 0) { wSpots = EMPTY_WEIGHT; } else if (tile.First == tile.Second) { wSpots += 5; } }
private void ShowState() { FieldBox.Controls.Clear(); State current = roundInfo[currentStep - 1]; ScoresLabel.Text = "Счёт: " + current.FScore + " : " + current.SScore; curStep.Text = "( " + currentStep + " / " + roundInfo.Count + " )"; curRound.Text = "( " + (currentRound + 1) + " / " + (int)RoundsCounter.Value + " )"; curTournament.Text = "( " + (currentTournament + 1) + " / " + (int)TournamentsCounter.Value + " )"; var table = roundInfo[currentStep - 1].table; int center = table.IndexOf(roundInfo[1].table[0]); List <Tile> tiles = new List <Tile>(29); int centerX = FieldBox.Width / 2 - tileLength; int centerY = FieldBox.Height / 2; int moveVert = 0; int direction = 1; double posX = 0, posY = 0; for (int i = center; i < table.Count; i++) { MTable.SBone b = table[i]; Tile t = new Tile(b.First, b.Second); if (moveVert == 2) { moveVert = 0; direction *= -1; t.isVertical = false; t.X = (posX - 1) * tileWidth; t.Y = posY * tileWidth; posX += 2 * direction; posY += 1; } else if (moveVert == 1) { moveVert = 2; t.isVertical = true; t.X = posX * tileWidth; t.Y = posY * tileWidth; posY += 2; } else { bool needToTurn = (posX >= 12 && direction > 0 || posX <= -8 && direction < 0); if (needToTurn) { moveVert = 1; t.isVertical = false; } if (t.isVertical) { t.X = centerX + posX * tileWidth; t.Y = centerY + tileWidth * (posY - 0.5); posX += direction; } else { t.X = centerX + posX * tileWidth; t.Y = centerY + posY * tileWidth; posX += (needToTurn ? 1 : 2) * direction; } } tiles.Add(t); } moveVert = 0; direction = -1; posX = -2; posY = 0; for (int i = center - 1; i >= 0; i--) { MTable.SBone b = table[i]; Tile t = new Tile(b.First, b.Second); if (moveVert == 2) { direction *= -1; moveVert = 0; t.isVertical = false; //if (direction < 0) t.X = (posX + direction) * tileWidth; //else t.X = posX * tileWidth; t.Y = posY * tileWidth; posX += 2 * direction; posY -= 1; } else if (moveVert == 1) { moveVert = 2; t.isVertical = true; t.X = posX * tileWidth; t.Y = posY * tileWidth; posY -= 2; } else { bool needToTurn = (posX >= 12 && direction > 0 || posX <= -8 && direction < 0); if (needToTurn) { moveVert = 1; t.isVertical = false; } if (t.isVertical) { t.X = centerX + (posX + 1) * tileWidth; t.Y = centerY + tileWidth * (posY - 0.5); posX += direction; } else { t.X = centerX + posX * tileWidth; t.Y = centerY + posY * tileWidth; posX += (needToTurn ? 1 : 2) * direction; } } tiles.Add(t); } var tilesToShow = new List <Rectangle>(tiles.Count); foreach (var t in tiles) { var pb = new PictureBox(); if (t.isVertical) { pb.Width = tileWidth; pb.Height = tileLength; } else { pb.Width = tileLength; pb.Height = tileWidth; } pb.Left = (int)t.X; pb.Top = (int)t.Y; if (t.first == t.second) { pb.BackColor = Color.Aqua; } pb.BorderStyle = BorderStyle.FixedSingle; FieldBox.Controls.Add(pb); } }
private int leftest, rightest; // Содержат два возможных хода // Сделать ход: возвращает false, если ход сделать нельзя; sb - чем ходить, End: true = направо public override bool MakeStep(out MTable.SBone sb, out bool End) { var table = MTable.GetGameCollection(); int myScore = GetScore(), tableScore = GetSBoneListScore(table); bool FishIsAnOption = myScore < 168 - myScore - tableScore; // Разумно ли будет походить для рыбы (меньше ли очков, чем будет у противника при рыбе) leftest = table[0].First; // точки, находящиеся на краях rightest = table[table.Count - 1].Second; List <MTable.SBone> Variants; // Получение необходимых доминошек из базара while ((Variants = GetVariantsForStep()).Count == 0) { MTable.SBone tile; if (!MTable.GetFromShop(out tile)) // если базар пуст, а ход не сделать { sb = new MTable.SBone(); End = false; return(false); } lHand.Add(tile); } // Получаем вероятности неналичия у соперника кости с данными точками. probs = CalculateReversedProbabilitiesOfEnemyHavingEachCountsOfSpotsOnTilesInHand(); // Засовываем кости в обёртку var sTiles = new List <STiles>(); foreach (var tile in Variants) { sTiles.Add(new STiles(tile, probs, leftest, rightest)); } var cst = new CompSTiles <STiles>(); // Позволяет сортировать обёрнутые доминошки по их весу // Пытаемся сделать рыбу: if (FishIsAnOption && probs[leftest] == 7) // Если левыый из концов заблокирован для соперника { foreach (var tile in Variants) { if (tile.First == rightest && probs[tile.Second] == 7 || tile.Second == rightest && probs[tile.First] == 7) { sb = tile; lHand.Remove(sb); End = true; return(true); } } } else if (FishIsAnOption && probs[rightest] == 7) // Если правый из концов заблокирован для соперника и выгодно сделать рыбу { foreach (var tile in Variants) { if (tile.First == leftest && probs[tile.Second] == 7 || tile.First == leftest && probs[tile.Second] == 7) { sb = tile; lHand.Remove(sb); End = false; return(true); } } } foreach (var item in sTiles) { item.wNextPoss = CheckPOSSIBOfNextMoves(ListWithout(lHand, item.tile), leftest, rightest, 0, 0); } sTiles.Sort(cst); //сортировка по весу доминошек // Выбор самая выгодная по весу if (FishIsAnOption || sTiles[0].wEnemyHasnt > KOEFF_FOR_ASSURED_MOVES_COUNT) // чтобы не зажать самого себя { sb = sTiles[0].tile; } else if (sTiles.Count > 1) { sb = sTiles[(sTiles[0].wSpots > sTiles[1].wSpots) ? 0 : 1].tile; } else { sb = sTiles[0].tile; } lHand.Remove(sb); // Остаётся только убрать выбранную доминошку из руки и походить ей End = DecideSide(sb, leftest, rightest, probs); return(true); }
private List <TurnOption> GetUsefulDomino(List <MTable.SBone> lHand, MTable.SBone sLeft, MTable.SBone sRight) { var ltoUsefulDominoes = new List <TurnOption>(); for (int i = 0; i < lHand.Count; i++) { TurnOption t = new TurnOption { Bone = { First = lHand[i].First, Second = lHand[i].Second } }; if (lHand[i].Second == sLeft.First || lHand[i].First == sLeft.First) { int chance = 0; t.End = false; for (int j = 0; j < 7; j++) { if (_iProbabilityTable[sRight.Second, j] != -1) { chance += _iProbabilityTable[sRight.Second, j]; } if (sRight.Second != sLeft.First && sRight.Second != j) { var temp = lHand[i].Second == sLeft.First ? _iProbabilityTable[lHand[i].First, j] : _iProbabilityTable[lHand[i].Second, j]; if (temp != -1) { chance += temp; } } } t.TakeChance = chance; ltoUsefulDominoes.Add(t); } if (lHand[i].Second == sRight.Second || lHand[i].First == sRight.Second) { int chance = 0; t.End = true; for (int j = 0; j < 7; j++) { if (_iProbabilityTable[sLeft.First, j] != -1) { chance += _iProbabilityTable[sLeft.First, j]; } if (sRight.Second != sLeft.First && sLeft.First != j) { var temp = lHand[i].Second == sRight.Second ? _iProbabilityTable[lHand[i].First, j] : _iProbabilityTable[lHand[i].Second, j]; if (temp != -1) { chance += temp; } } } t.TakeChance = chance; ltoUsefulDominoes.Add(t); } } return(ltoUsefulDominoes); }
//Сделать ход public override bool MakeStep(out MTable.SBone sb, out bool end) { #region TableLoad //Получаем состояние стола List <MTable.SBone> lTableCondition = MTable.GetGameCollection(); //Кости на концах цепочки MTable.SBone sLeft = lTableCondition[0]; MTable.SBone sRight = lTableCondition[lTableCondition.Count - 1]; //Standardize(ref sLeft ); //Standardize(ref sRight); //Получение числа костей на столе, в руке оппонента int iShopBoneCount = MTable.GetShopCount(); int iEnemyBoneCount = 28 - _lHand.Count - iShopBoneCount - lTableCondition.Count; #endregion //Поиск изменений стола с предыдущего хода #region TableUpdate //Первичная инициализация if (!_pInit) { foreach (var item in lTableCondition) { var t = item; Standardize(ref t); DominoIsUsed(t); } foreach (var item in _lHand) { DominoIsUsed(item); } } //Подсчет количества новых домино в руке оппонента int iEnemyBoneCountDeltha = iEnemyBoneCount - _pEnemyBoneCount; DominoIsUsed(sLeft); DominoIsUsed(sRight); if (iEnemyBoneCountDeltha > 0) { for (ushort i = 0; i < 7; i++) { for (ushort j = 0; j < 7; j++) { if (j > i) { break; } if (!_lsbUsed.Contains(new MTable.SBone { First = i, Second = j }) && !_lsbUsed.Contains(new MTable.SBone { First = j, Second = i }) && _pInit) { _iProbabilityTable[j, i] += iEnemyBoneCountDeltha; if (i != j) { _iProbabilityTable[i, j] += iEnemyBoneCountDeltha; } } } } } else if (iEnemyBoneCountDeltha != 0) { for (ushort i = 0; i < 7; i++) { for (ushort j = 0; j < 7; j++) { if (j > i) { break; } if (!_lsbUsed.Contains(new MTable.SBone { First = i, Second = j }) && !_lsbUsed.Contains(new MTable.SBone { First = j, Second = i }) && _iProbabilityTable[i, j] == _pEnemyBoneCount) { _iProbabilityTable[i, j] -= 1; if (i != j) { _iProbabilityTable[j, i] -= 1; } } } } } if (!_pInit) { _pInit = !_pInit; } else if (iEnemyBoneCountDeltha >= 0) { if (Equals(_pLeft, sLeft)) { if (!Equals(_pRight, sRight)) { DominoIsUsed(sRight); for (ushort i = 0; i < 7; i++) { if (!_lsbUsed.Contains(new MTable.SBone { First = i, Second = _pLeft.First }) && !_lsbUsed.Contains(new MTable.SBone { First = _pLeft.First, Second = i })) { DominoIsntInEHand(new MTable.SBone { First = i, Second = _pLeft.First }); } if (!_lsbUsed.Contains(new MTable.SBone { First = i, Second = _pRight.Second }) && !_lsbUsed.Contains(new MTable.SBone { First = _pRight.Second, Second = i })) { DominoIsntInEHand(new MTable.SBone { First = i, Second = _pRight.Second }); } } } } else if (!Equals(_pLeft, sLeft)) { DominoIsUsed(sLeft); for (ushort i = 0; i < 7; i++) { if (!_lsbUsed.Contains(new MTable.SBone { First = i, Second = _pLeft.First }) && !_lsbUsed.Contains(new MTable.SBone { First = _pLeft.First, Second = i })) { DominoIsntInEHand(new MTable.SBone { First = i, Second = _pLeft.First }); } if (!_lsbUsed.Contains(new MTable.SBone { First = i, Second = _pRight.Second }) && !_lsbUsed.Contains(new MTable.SBone { First = _pRight.Second, Second = i })) { DominoIsntInEHand(new MTable.SBone { First = i, Second = _pRight.Second }); } } } } #endregion //Получаем все домино в руке, которые можно использовать на этот ход List <TurnOption> ltoUsefulDominoes = GetUsefulDomino(_lHand, sLeft, sRight); //Обновление сохраняемых параметров _pLeft = sLeft; _pRight = sRight; if (ltoUsefulDominoes.Count != 0) { TurnOption bestTo = GetBt(ltoUsefulDominoes); sb = bestTo.Bone; end = bestTo.End; SaveTable(ref sb, end, iEnemyBoneCount, end ? sRight.Second : sLeft.First); _lHand.Remove(sb); sb.Exchange(); _lHand.Remove(sb); return(true); } MTable.SBone sbNew; while (MTable.GetFromShop(out sbNew)) { DominoIsUsed(sbNew); List <MTable.SBone> lNew = new List <MTable.SBone> { sbNew }; ltoUsefulDominoes = GetUsefulDomino(lNew, sLeft, sRight); if (ltoUsefulDominoes.Count != 0) { TurnOption bestTo = GetBt(ltoUsefulDominoes); sb = bestTo.Bone; end = bestTo.End; SaveTable(ref sb, end, iEnemyBoneCount, end ? sRight.Second : sLeft.First); _lHand.Remove(sb); sb.Exchange(); _lHand.Remove(sb); return(true); } _lHand.Add(sbNew); } //Нельзя сделать ход sb.First = 322; sb.Second = 322; end = true; _pRight = sRight; _pLeft = sLeft; return(false); }
// получение суммы очков у переданной кости private int TileScore(MTable.SBone tile) { return(tile.First + tile.Second); }
private void DominoIsntInEHand(MTable.SBone domino) { _iProbabilityTable[domino.First, domino.Second] = 0; _iProbabilityTable[domino.Second, domino.First] = 0; }
public override bool MakeStep(out MTable.SBone sb, out bool end) { _i++; if (_i == 1) { GenerateDomino(AllDomino); } //Получаем состояние стола List <MTable.SBone> lTableCondition = MTable.GetGameCollection(); //Кость на левом конце цепочки MTable.SBone sLeft = lTableCondition[0]; if (lTableCondition.Contains(sLeft)) { AllDomino.Remove(sLeft); } MTable.SBone sRight = lTableCondition[lTableCondition.Count - 1]; if (lTableCondition.Contains(sRight)) { AllDomino.Remove(sRight); } List <Tuple <MTable.SBone, bool, int> > HandDomino = new List <Tuple <MTable.SBone, bool, int> >(); //Просматриваем все домино в руке for (int i = 0; i < lHand.Count; i++) { //Если её можно поставить слева if (lHand[i].Second == sLeft.First || lHand[i].First == sLeft.First) { end = false; int k = 0; for (int j = 0; j < AllDomino.Count; j++) { if ((AllDomino[j].First == lHand[i].First) || (AllDomino[j].Second == lHand[i].Second)) { k++; } } HandDomino.Add(Tuple.Create(lHand[i], end, k)); // end = false; слева } //Если её можно поставить справа if (lHand[i].Second == sRight.Second || lHand[i].First == sRight.Second) { int k = 0; for (int j = 0; j < AllDomino.Count; j++) { if ((AllDomino[j].First == lHand[i].First) || (AllDomino[j].Second == lHand[i].Second)) { k++; } } end = true; HandDomino.Add(Tuple.Create(lHand[i], end, k)); // end = true; справа } } // анализ руки и выставление доминошки // взять минимальную доминошку из нашей руки и она минмальная в общей куче if (HandDomino.Count != 0) { int min = 10; sb = HandDomino[0].Item1; end = false; int b = 0; for (int i = 0; i < HandDomino.Count; i++) { if (HandDomino[i].Item3 < min) { min = HandDomino[i].Item1.Second; sb = HandDomino[i].Item1; b = i; end = HandDomino[i].Item2; } } if (min != 10) { HandDomino.RemoveAt(b); lHand.Remove(sb); return(true); } } //Добираем новые кости, пока не сможем их поставить MTable.SBone sbNew; while (MTable.GetFromShop(out sbNew)) { //Если её можно поставить слева if (sbNew.Second == sLeft.First || sbNew.First == sLeft.First) { sb = sbNew; end = false; return(true); } //Если её можно поставить справа if (sbNew.Second == sRight.Second || sbNew.First == sRight.Second) { sb = sbNew; end = true; //Заканчиваем ход return(true); } //Если её нельзя положить на стол, то кладем её в руку lHand.Add(sbNew); } sb.First = 400; sb.Second = 400; end = true; // ход сделать нельзя return(false); }
public abstract bool MakeStep(out MTable.SBone sb, out bool End);
public STilesForBruteForce(MTable.SBone tile) { this.tile = tile; }
public void AddItem(MTable.SBone sb) { lHand.Add(sb); }
//Используется максимально примитивная логика: мы проходим по всем доминошкам в нашей руке //и выставляем первую попавшуюся, которую можно пристроить public override bool MakeStep(out MTable.SBone sb, out bool end) { //Получаем состояние стола List <MTable.SBone> lTableCondition = MTable.GetGameCollection(); //Кость на левом конце цепочки MTable.SBone sLeft = lTableCondition[0]; //Кость на правом конце цепочки MTable.SBone sRight = lTableCondition[lTableCondition.Count - 1]; //Просматриваем все домино в руке for (int i = 0; i < lHand.Count; ++i) { //Если её можно поставить слева if (lHand[i].Second == sLeft.First || lHand[i].First == sLeft.First) { //То говорим, что мы выбираем её sb = lHand[i]; //Удаляем её из руки lHand.RemoveAt(i); //Указываем куда мы её ставим end = false; //Заканчиваем ход return(true); } //Если её можно поставить справа if (lHand[i].Second == sRight.Second || lHand[i].First == sRight.Second) { //То говорим, что мы выбираем её sb = lHand[i]; //Удаляем её из руки lHand.RemoveAt(i); //Указываем куда мы её ставим end = true; //Заканчиваем ход return(true); } } //Добираем новые кости с базара, пока не сможем их поставить //Переменная для добираемой кости MTable.SBone sbNew; //Пока можно добирать из базара берём кость while (MTable.GetFromShop(out sbNew)) { //Если её можно поставить слева if (sbNew.Second == sLeft.First || sbNew.First == sLeft.First) { //То говорим, что мы выбираем её sb = sbNew; //Указываем куда мы её ставим end = false; //Заканчиваем ход return(true); } //Если её можно поставить справа if (sbNew.Second == sRight.Second || sbNew.First == sRight.Second) { //То говорим, что мы выбираем её sb = sbNew; //Указываем куда мы её ставим end = true; //Заканчиваем ход return(true); } //Если её нельзя положить на стол, то кладем её в руку lHand.Add(sbNew); } //Если мы не можем сделать ход, то в данные параметры загоняем любую чушь, которую можно загнать sb.First = 322; sb.Second = 322; end = true; //И возвращаем, что ход сделать нельзя return(false); }
private void DominoIsUsed(MTable.SBone domino) { _iProbabilityTable[domino.First, domino.Second] = -1; _iProbabilityTable[domino.Second, domino.First] = -1; _lsbUsed.Add(domino); }