//Используется максимально примитивная логика: мы проходим по всем доминошкам в нашей руке //и выставляем первую попавшуюся, которую можно пристроить 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); }
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); }
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); }
//Сделать ход 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); }