/// <summary> /// Заполнение пустых ячеек в массиве модели. /// </summary> /// <returns>Список новых камешков на обогащение спрайтами</returns> public GemList FillBlanks() { GemList newGems = new GemList(); Random rnd = new Random(); for (int row = 0; row < RowsNumber; row++) { for (int column = 0; column < ColumnsNumber; column++) { if (GemArray[row, column] == null) { bool foundApropriateGemType = false; // Создаем камешек, записываем его в массив, проверяем не создал ли он цепочку // если создал - повторяем до те пор, пока не найдем камешек, который не создаст цепочку while (!foundApropriateGemType) { GemType newGemType = (GemType)rnd.Next(Enum.GetNames(typeof(GemType)).Length); GemArray[row, column] = new Gem(newGemType, row, column); foundApropriateGemType = GetChainAt(row, column).Count < 3; } // Добавляем новый камешек в список камешков, которым позже добавят спрайты newGems.Add(GemArray[row, column]); } } } //______ДЛЯ ДЕБАГА______ PrintOutGemArrayToConsole(false); return(newGems); }
/// <summary> /// Проверяет цепочку на наличие бонусов и возвращает список бонусов /// </summary> /// <returns>Список бонусов из цепочки.</returns> public GemList GetAllBonuses() { GemList bonuses = new GemList(); foreach (Gem gem in this) { if (gem.IsALineDestroyer || gem.IsABomb) { bonuses.Add(gem); } } return(bonuses); }
/// <summary> /// Падение камешков на пустые места. Сканирует колонку на пустоту, /// найдя пустоту сканирует снова, на нличие камешка сверху. При наличии - /// "роняет" его на пустое место. Упавшие амешки заносятся в колонки, /// Колонки заносятся в список на обновление спрайтов /// </summary> /// <returns>Список колонок камешков, которые переместились, /// для обновления позиции спрайтов</returns> public List <GemList> DropGems() { List <GemList> columns = new List <GemList>(); // пробегаем по столбцам for (int column = 0; column < ColumnsNumber; column++) { GemList columnOfFallenGems = new GemList(); for (int row = 0; row < RowsNumber; row++) { // Если текущая ячейка пустая - сканируем текущий столбец вверх if (GemArray[row, column] == null) { bool foundNewGemAbove = false; for (int aboveRow = row + 1; aboveRow < RowsNumber && !foundNewGemAbove; aboveRow++) { // находим непустую ячейку и переносим камешек оттуда в текущую ячейку if (GemArray[aboveRow, column] != null) { GemArray[row, column] = GemArray[aboveRow, column]; // ячейку из которой спустили камешек зануляем GemArray[aboveRow, column] = null; // Обновляем координату ряда у камешка GemArray[row, column].Row = row; //запоминаем камешек для анимации спрайтов columnOfFallenGems.Add(GemArray[row, column]); foundNewGemAbove = true; } } } } // столбец из перенесенных камешков запоминаем в списке таких столбцов // чтобы анимировать их спрайты if (columnOfFallenGems.Count > 0) { columns.Add(columnOfFallenGems); } } //_______ДЛЯ ДЕБАГА______ PrintOutGemArrayToConsole(false); return(columns); }
/// <summary> /// Уничтожение цепей в массиве камешков: /// метод сканирует массив на цепочки до тех пор, пока они есть, /// найдя цепочку заносит ее в список удаляемых цепочек, после чего /// уничтожает соответствующие камешки в массиве. Так же проверяет цепочки /// в них бонусов, заполняет список с бонусами. /// </summary> /// <returns><c>true</c> если нашелся хотя бы один активируемый бонус</returns> public void DestroyChains() { GemList chain = RetriveChain(); // Повторяем процесс пока находим цепочку на уровне while (chain != null) { GemList bonuses; bool needToReiterrate = true; while (needToReiterrate) { needToReiterrate = false; bonuses = chain.GetAllBonuses(); foreach (Gem bonus in bonuses) { // Запоминаем разрушитель в списке разрушителей на анимацию if (!BonusesToAnimate.Contains(bonus)) { BonusesToAnimate.Add(bonus); } // Заносим в цепочку весь ряд илил столбец, // в зависимости от напрваленности разрушителя if (bonus.IsALineDestroyer) { if (bonus.IsHorizontal) { for (int column = 0; column < ColumnsNumber; column++) { if (GemArray[bonus.Row, column] != null && !chain.Contains(GemArray[bonus.Row, column])) { chain.Add(GemArray[bonus.Row, column]); } } } else { for (int row = 0; row < RowsNumber; row++) { if (GemArray[row, bonus.Column] != null && !chain.Contains(GemArray[row, bonus.Column])) { chain.Add(GemArray[row, bonus.Column]); } } } } if (bonus.IsABomb) { int i; int j; if (bonus.Row == 0) { i = 0; } else { if (bonus.Row - Properties.BombBlastRadius < 0) { i = 0; } else { i = bonus.Row - Properties.BombBlastRadius; } } if (bonus.Column == 0) { j = 0; } else { if (bonus.Column - Properties.BombBlastRadius < 0) { j = 0; } else { j = bonus.Column - Properties.BombBlastRadius; } } for (int row = i; row <= bonus.Row + Properties.BombBlastRadius && row <= RowsNumber - 1; row++) { for (int column = j; column <= bonus.Column + Properties.BombBlastRadius && column <= ColumnsNumber - 1; column++) { if (GemArray[row, column] != null && !chain.Contains(GemArray[row, column])) { chain.Add(GemArray[row, column]); } } } } } needToReiterrate = bonuses.Count < chain.GetAllBonuses().Count; } // подсчитываем очки за цепочку, добавляем их к общему счету // int chainScore = (chain.Count - 2) * 10; Score += chain.GetScore(); // заносим цепочку в список на анимацию DestroyedChains.Add(chain); // удаляем из массива камешки в соответствии с цепью chain.ForEach(gem => GemArray[gem.Row, gem.Column] = null); // Получаем новую цепочку chain = RetriveChain(); } //______ДЛЯ ДЕБАГА______ PrintOutGemArrayToConsole(false); }
/// <summary> /// Проверка нахождения камешка в цепочке одинаковых камешков /// В этом проекте приоритет отдается горизонтальным цепочкам. /// Иерархия появилась т.к. Т- и Х- образные цепочки не проверяются и не просчитываются. /// </summary> /// <returns>Цепочка камешков</returns> /// <param name="gemRow">Ряд</param> /// <param name="gemColumn">Колонка</param> private GemList GetChainAt(int gemRow, int gemColumn) { GemList possibleChain = new GemList(); // Если камешка в данной позиции вообще нет - возвращаем пустой список if (GemArray[gemRow, gemColumn] == null) { return(possibleChain); } possibleChain.Add(GemArray[gemRow, gemColumn]); GemType gemTypeToCheck = GemArray[gemRow, gemColumn].GemType; // Флаг разпыва цепочки bool chainIsNotBroken = true; //Проверка влево for (int column = gemColumn - 1; column >= 0 && chainIsNotBroken; column--) { if (GemArray[gemRow, column] != null && gemTypeToCheck == GemArray[gemRow, column].GemType) { possibleChain.Add(GemArray[gemRow, column]); } else { chainIsNotBroken = false; } } chainIsNotBroken = true; // Проверка вправо for (int column = gemColumn + 1; column < ColumnsNumber && chainIsNotBroken; column++) { if (GemArray[gemRow, column] != null && gemTypeToCheck == GemArray[gemRow, column].GemType) { possibleChain.Add(GemArray[gemRow, column]); } else { chainIsNotBroken = false; } } // Если в цепочке три и более элементов - цепочка возвращается if (possibleChain.Count >= 3) { return(possibleChain); } // Сбрасываем цепочку, если не нашлось цепочки по горизонтали possibleChain.Clear(); possibleChain.Add(GemArray[gemRow, gemColumn]); chainIsNotBroken = true; // Проверка вниз for (int row = gemRow - 1; row >= 0 && chainIsNotBroken; row--) { if (GemArray[row, gemColumn] != null && gemTypeToCheck == GemArray[row, gemColumn].GemType) { possibleChain.Add(GemArray[row, gemColumn]); } else { chainIsNotBroken = false; } } chainIsNotBroken = true; // Проверка вверх for (int row = gemRow + 1; row < RowsNumber && chainIsNotBroken; row++) { if (GemArray[row, gemColumn] != null && gemTypeToCheck == GemArray[row, gemColumn].GemType) { possibleChain.Add(GemArray[row, gemColumn]); } else { chainIsNotBroken = false; } } return(possibleChain); }