/// <summary> /// Метод проверяет наличие "матчей" после свапа для блоков, которые были свапнуты. Если есть, удаляем "матчи" и затем производим "осыпание" доски. /// </summary> /// <param name="prevBlock">Блок, на который кликнули ранее.</param> /// <param name="currentBlock">Блок, на который кликнули сейчас</param> /// <returns>Метод возвращает были "матчи" после свапа или нет</returns> public bool CheckMatchesForSwappedBlocks(BlockStruct prevBlock, BlockStruct currentBlock) { List <BlockStruct> matchingBlocks = new List <BlockStruct>(); matchingBlocks.AddRange(CheckVerticalMatches(prevBlock.X, prevBlock.Y)); matchingBlocks.AddRange(CheckHorizontalMatches(prevBlock.X, prevBlock.Y)); if (matchingBlocks.Count > 0) { matchingBlocks.Add(prevBlock); } List <BlockStruct> verticalMatchingBlocks = new List <BlockStruct>(); verticalMatchingBlocks.AddRange(CheckVerticalMatches(currentBlock.X, currentBlock.Y)); verticalMatchingBlocks.AddRange(CheckHorizontalMatches(currentBlock.X, currentBlock.Y)); if (verticalMatchingBlocks.Count > 0) { matchingBlocks.Add(currentBlock); matchingBlocks.AddRange(verticalMatchingBlocks); } if (matchingBlocks.Count > 0) { ClearMatches(matchingBlocks); FindNullBlocks(); return(true); } else { return(false); } }
public void SwapColor(BlockStruct otherBlock) { Color tempColor = otherBlock.Color; otherBlock.Color = this.Color; this.Color = tempColor; }
void Awake() { boardGeneration = GetComponent <BoardGeneration>(); GameBoard = new BlockStruct[xSize, ySize]; boardGeneration.GenerateGameBoard(ref GameBoard, this); boardGeneration.VisualizeBlocks(GameBoard); prevSelected = null; }
/// <summary> /// См. описание метода для поиска по вертикали. Аналогично только по горизонтали /// </summary> /// <param name="block">Блок для которого ищем возможные ходы</param> /// <returns>Возвращает true, если есть возможные ходы, иначе false</returns> private bool CheckHorizontalPossible(BlockStruct block) { if (block.X < xSize - 1 && GameBoard[block.X + 1, block.Y].Color == block.Color) { if (block.X > 0) { if (block.Y > 0 && GameBoard[block.X - 1, block.Y - 1].Color == block.Color) { return(true); } if (block.Y < ySize - 1 && GameBoard[block.X - 1, block.Y + 1].Color == block.Color) { return(true); } if (block.X > 1 && GameBoard[block.X - 2, block.Y].Color == block.Color) { return(true); } } if (block.X < xSize - 2) { if (block.Y > 0 && GameBoard[block.X + 2, block.Y - 1].Color == block.Color) { return(true); } if (block.Y < ySize - 1 && GameBoard[block.X + 2, block.Y + 1].Color == block.Color) { return(true); } if (block.X < xSize - 3 && GameBoard[block.X + 3, block.Y].Color == block.Color) { return(true); } } } if (block.X < xSize - 2 && GameBoard[block.X + 2, block.Y].Color == block.Color) { if (block.Y > 0 && GameBoard[block.X + 1, block.Y - 1].Color == block.Color) { return(true); } if (block.Y < ySize - 1 && GameBoard[block.X + 1, block.Y + 1].Color == block.Color) { return(true); } } return(false); }
/// <summary> /// По вертикали возможны следующие ситуации: /// 1) Два блока подряд одного цвета, следующий блок другого цвета, а рядом с этим блоком другого цвета (сверху, справа или слева) есть блок с нужным цветом /// 2) Два блока подряд одного цвета, под ними блок другого цвета, а рядом с этим блоком другого цвета (снизу, справа или слева) есть блок с нужным цветом /// 3) Два блока одного цвета, а между ними блок другого цвета, и слева или справа от блока другого цвета есть блок с нужным цветом /// </summary> /// <param name="block">Блок для которого ищем возможные ходы</param> /// <returns>Возвращает true, если есть возможные ходы, иначе false</returns> private bool CheckVerticalPossible(BlockStruct block) { if (block.Y < ySize - 1 && GameBoard[block.X, block.Y + 1].Color == block.Color) { if (block.Y > 0) { if (block.X > 0 && GameBoard[block.X - 1, block.Y - 1].Color == block.Color) { return(true); } if (block.X < xSize - 1 && GameBoard[block.X + 1, block.Y - 1].Color == block.Color) { return(true); } if (block.Y > 1 && GameBoard[block.X, block.Y - 2].Color == block.Color) { return(true); } } if (block.Y < ySize - 2) { if (block.X > 0 && GameBoard[block.X - 1, block.Y + 2].Color == block.Color) { return(true); } if (block.X < xSize - 1 && GameBoard[block.X + 1, block.Y + 2].Color == block.Color) { return(true); } if (block.Y < ySize - 3 && GameBoard[block.X, block.Y + 3].Color == block.Color) { return(true); } } } if (block.Y < ySize - 2 && GameBoard[block.X, block.Y + 2].Color == block.Color) { if (block.X > 0 && GameBoard[block.X - 1, block.Y + 1].Color == block.Color) { return(true); } if (block.X < xSize - 1 && GameBoard[block.X + 1, block.Y + 1].Color == block.Color) { return(true); } } return(false); }
public void SwapForShift(BlockStruct otherBlock) { Color tempCol = otherBlock.Color; bool tempCleared = otherBlock.cleared; bool tempDel = otherBlock.deleted; otherBlock.Color = this.Color; this.Color = tempCol; otherBlock.deleted = this.deleted; this.deleted = tempDel; otherBlock.cleared = this.cleared; this.cleared = tempCleared; }
/// <summary> /// Метод подбирает цвет для блока. Цвет не должен создать ситуацию "готовых матчей". Но также мы не должны выйти за границы массива. /// </summary> /// <param name="block">Блок, для которого подбираем цвет</param> /// <returns></returns> private List <Color> GetPossibleColors(BlockStruct block) { List <Color> possibleColors = new List <Color>(); possibleColors.AddRange(boardGeneration.BlockColors); if (block.X > 1 && GameBoard[block.X - 2, block.Y].Color == GameBoard[block.X - 1, block.Y].Color) { possibleColors.Remove(GameBoard[block.X - 1, block.Y].Color); } if (block.X < xSize - 2 && GameBoard[block.X + 1, block.Y].Color == GameBoard[block.X + 2, block.Y].Color && !GameBoard[block.X + 1, block.Y].cleared && !GameBoard[block.X + 2, block.Y].cleared) { possibleColors.Remove(GameBoard[block.X + 1, block.Y].Color); } if (block.X > 0 && block.X < xSize - 1 && GameBoard[block.X + 1, block.Y].Color == GameBoard[block.X - 1, block.Y].Color && !GameBoard[block.X + 1, block.Y].cleared) { possibleColors.Remove(GameBoard[block.X + 1, block.Y].Color); } if (block.Y > 1 && GameBoard[block.X, block.Y - 1].Color == GameBoard[block.X, block.Y - 2].Color) { possibleColors.Remove(GameBoard[block.X, block.Y - 1].Color); } if (block.Y > 0 && block.Y < ySize - 1 && GameBoard[block.X, block.Y + 1].Color == GameBoard[block.X, block.Y - 1].Color && !GameBoard[block.X, block.Y + 1].cleared) { possibleColors.Remove(GameBoard[block.X, block.Y - 1].Color); } if (block.Y < ySize - 2 && GameBoard[block.X, block.Y + 1].Color == GameBoard[block.X, block.Y + 2].Color && !GameBoard[block.X, block.Y + 1].cleared && !GameBoard[block.X, block.Y + 2].cleared) { possibleColors.Remove(GameBoard[block.X, block.Y + 1].Color); } if (possibleColors.Count > 0) { return(possibleColors); } else { //такой ситуации быть с 6 цветами не может, но на всякий случай я её добавлю return(new List <Color> { Color.white }); } }
public void SaveGameToJsonFile() { GameSave gameSave = new GameSave(); // get player data and set to serializable structs PlayerStruct playerStruct = PlayerManager.instance.player.ToPlayerStruct(); gameSave.SetPlayer(playerStruct); // get block data and set to serializable structs foreach (Block b in BlockManager.instance.GetBlocksAsList()) { BlockStruct blockStruct = b.ToBlockStruct(); gameSave.AddBlock(blockStruct); } // commit the save data string json = JsonUtility.ToJson(gameSave); // print("save game to file..."); // print("json to save: " + json); // print("path to save: " + GetSavePath()); File.WriteAllText(GetSavePath(), json, Encoding.UTF8); }
public void GenerateGameBoard(ref BlockStruct[,] GameBoard, BoardManager boardManager) { for (int x = 0; x < GameBoard.GetLength(0); x++) { for (int y = 0; y < GameBoard.GetLength(1); y++) { GameBoard[x, y] = new BlockStruct(); #region "Без стартовых 'Матчей'"; List <Color> possibleColors = new List <Color>(); possibleColors.AddRange(BlockColors); if (x > 1 && GameBoard[x - 2, y].Color == GameBoard[x - 1, y].Color) { possibleColors.Remove(GameBoard[x - 1, y].Color); } if (y > 1 && GameBoard[x, y - 1].Color == GameBoard[x, y - 2].Color) { possibleColors.Remove(GameBoard[x, y - 1].Color); } Color blockColor = possibleColors[Random.Range(0, possibleColors.Count)]; #endregion ; GameBoard[x, y].SetStartData(x, y, blockColor); } } int counter = 0; while (!boardManager.CheckPossibleMatches() || counter >= tryCount) { GameBoard = RegenerateBoard(GameBoard); counter++; } if (counter >= tryCount) { boardManager.EndGame(); Debug.Log("Cant start the game 100 times!"); } }
private void OnMouseDown() { if (!render.enabled) { return; } BlockStruct block = boardManager.GameBoard[_x, _y]; if (block.selected) { boardManager.Deselect(_x, _y); } else { if (boardManager.prevSelected == null) { boardManager.Select(_x, _y); } else { if (boardManager.IsBlockNeighbour(_x, _y)) { boardManager.SwapBlocks(boardManager.GameBoard[_x, _y], boardManager.prevSelected); if (!boardManager.CheckMatchesForSwappedBlocks(boardManager.prevSelected, boardManager.GameBoard[_x, _y])) { boardManager.SwapBlocks(boardManager.GameBoard[_x, _y], boardManager.prevSelected); } boardManager.Deselect(boardManager.prevSelected.X, boardManager.prevSelected.Y); } else { boardManager.Deselect(boardManager.prevSelected.X, boardManager.prevSelected.Y); boardManager.Select(_x, _y); } } } }
public static BlockArray CreateTestArray() { var blockArray = new BlockArray(); blockArray.Values = new BlockStruct[100 * 100]; var index = 0; for (var x = 0; x < 100; x++) { for (var y = 0; y < 100; y++) { var blockStruct = new BlockStruct { Type = (short)Random.Range(0, 5), GroupId = 0, Position = new int2(x, y), FrameCountLastUpdated = 0, }; blockArray.Values[index++] = blockStruct; } } return(blockArray); }
private static void ProcessAbuseLog() { var currentTimestamp = Utilities.GetCurrentTimestamp(); var expireTimestamp = currentTimestamp - GlobalVars.Config.AbuseExpirationTime; var blockCounter = 0; var itemsToRemove = new List <string>(); foreach (var(key, value) in AbuseDictionary) { if (GlobalVars.Data.BlockHashSet.Contains(value.IpAddress)) { itemsToRemove.Add(key); continue; } while (true) { if (value.Timestamps.TryPeek(out var timestamp)) { if (timestamp < expireTimestamp) { value.Timestamps.Dequeue(); } else { break; } } else { break; } } // remove expired timestamps if (value.Timestamps.Count == 0) { itemsToRemove.Add(key); continue; } // count & block abusing ips var abusesToBlock = _underAttack ? GlobalVars.Config.AbusesToBlockUnderAttack : GlobalVars.Config.AbusesToBlock; if (value.Timestamps.Count >= abusesToBlock) { var blockStruct = new BlockStruct(value.IpAddress, currentTimestamp + GlobalVars.Config.BlockExpirationTime) { BlockId = CloudflareUtilities.Block(value.IpAddress) }; Console.WriteLine($"Blocked abusing IP: {blockStruct.IpAddress} (Id = {blockStruct.BlockId})"); GlobalVars.Data.BlockQueue.Enqueue(blockStruct); GlobalVars.Data.BlockHashSet.Add(value.IpAddress); blockCounter++; itemsToRemove.Add(key); _dataChanged = true; } } foreach (var key in itemsToRemove) { AbuseDictionary.Remove(key); } if (!_underAttack && blockCounter >= GlobalVars.Config.BlocksToUnderAttack) { _underAttack = true; Console.WriteLine($"UAM is now enabled (blocked {blockCounter} IPs in one tick)"); if (GlobalVars.Config.CloudflareUnderAttackMode) { foreach (var id in GlobalVars.Config.CloudflareManageZones) { CloudflareUtilities.SecurityLevel(id, "under_attack"); Console.WriteLine($"SecurityLevel({id}) = under_attack"); } } } if (_underAttack) { if (blockCounter > 0) { _underAttackExpirationTicks = GlobalVars.Config.UnderAttackExpirationTicks; } else { _underAttackExpirationTicks--; if (_underAttackExpirationTicks <= 0) { _underAttack = false; Console.WriteLine("UAM is now disabled, no more abuses detected"); if (GlobalVars.Config.CloudflareUnderAttackMode) { foreach (var id in GlobalVars.Config.CloudflareManageZones) { CloudflareUtilities.SecurityLevel(id, GlobalVars.Config.CloudflareModeDefault); Console.WriteLine($"SecurityLevel({id}) = {GlobalVars.Config.CloudflareModeDefault}"); } } } } } }
public void SwapBlocks(BlockStruct firstBlock, BlockStruct secondBlock) { firstBlock.SwapColor(secondBlock); secondBlock.VisualChangeColor?.Invoke(secondBlock.Color); firstBlock.VisualChangeColor?.Invoke(firstBlock.Color); }
public void Select(int x, int y) { GameBoard[x, y].selected = true; prevSelected = GameBoard[x, y]; GameBoard[x, y].VisualSelect?.Invoke(); }
public void Deselect(int x, int y) { GameBoard[x, y].selected = false; GameBoard[x, y].VisualDeselect?.Invoke(); prevSelected = null; }
public void AddBlock(BlockStruct block) { this.blocks.Add(block); }