// перемещение поворотом private bool MoveRotate() { lock (Tank) { // проверка TetrisFigure Figure = (TetrisFigure)CurrentFigure.Clone(); Figure.MoveRotate(); if (!TryCurrentFigure(Figure)) { return(false); } // перемещение HideCurrentFigure(); CurrentFigure.MoveRotate(); ShowCurrentFigure(); return(true); } }
// добавление фигуры в стакан private bool CreateCurrentFigure() { CurrentFigure = NextFigure ?? Figures.GetFigure(FigureColors.GetColor()); CurrentFigure.OffsetX = (Width - CurrentFigure.Width) / 2; CurrentFigure.OffsetY = 0; lock (Tank) { // проверяем место для фигуры if (!TryCurrentFigure(CurrentFigure)) { return(false); } // добавляем фигуру в стакан ShowCurrentFigure(); // добавляем следующую фигуру CreateNextFigure(); } return(true); }
// получить случайную фигуру заданного цвета из набора public TetrisFigure GetFigure(Color color) { TetrisFigure Figure = GetFigure(); Figure.Color = color; return(Figure); }
// конструктор для клонирования protected TetrisFigure(TetrisFigure another) : this((TetrisBlock[])another.Blocks.Clone()) { for (int i = 0; i < Blocks.Length; i++) { Blocks[i] = (TetrisBlock)Blocks[i].Clone(); } OffsetX = another.OffsetX; OffsetY = another.OffsetY; }
// получить случайную фигуру из набора public TetrisFigure GetFigure() { if (Figures.Count() == 0) { throw new Exception("The set contains no figures"); } TetrisFigure Figure = (TetrisFigure)Figures[Random.Next(Figures.Count())].Clone(); return(Figure); }
private bool TryDown() { lock (Tank) { TetrisFigure Figure = (TetrisFigure)CurrentFigure.Clone(); Figure.MoveDown(); return(TryCurrentFigure(Figure)); } }
// проверка подобия фигур public bool IsSimilar(TetrisFigure other) { if (Blocks.Count() != other.Blocks.Count()) { return(false); } TetrisFigure Figure = (TetrisFigure)other.Clone(); bool CompareBlocks() { return(Blocks.Count() == Figure.Blocks.Count() && Blocks.All(p1 => Figure.Blocks.Any(p2 => p1.X == p2.X && p1.Y == p2.Y))); } // совпадение if (CompareBlocks()) { return(true); } // совпадение после поворота на 90 Figure.MoveRotate(); if (CompareBlocks()) { return(true); } // совпадение после поворота на 180 Figure.MoveRotate(); if (CompareBlocks()) { return(true); } // совпадение после поворота на 270 Figure.MoveRotate(); if (CompareBlocks()) { return(true); } // не совпало return(false); }
public void Stop() { switch (State) { case TetrisState.Started: case TetrisState.Paused: CurrentFigure = null; NextFigure = null; State = TetrisState.Stopped; StopTimerDown(); lock (Commands) Commands.Clear(); break; } }
public void Start() { switch (State) { case TetrisState.Paused: lock (Commands) Commands.Clear(); State = TetrisState.Started; StartTimerDown(); break; case TetrisState.Stopped: lock (Tank) { Array.Clear(Tank, 0, Tank.GetLength(0) * Tank.GetLength(1)); OnPropertyChanged("Tank"); } CurrentFigure = null; NextFigure = null; lock (Commands) Commands.Clear(); Level = 1; Lines = 0; Score = 0; if (CreateCurrentFigure()) { State = TetrisState.Started; StartTimerDown(); } else { State = TetrisState.Stopped; } break; } }
// проверка возможности перемещения фигуры на заданную позицию private bool TryCurrentFigure(TetrisFigure Figure) { foreach (TetrisBlock Block in Figure.Blocks) { int X = Block.X + Figure.OffsetX; int Y = Block.Y + Figure.OffsetY; // проверяем попадание в стакан if (X < 0 || X > Width - 1 || Y < 0 || Y > Height - 1) { return(false); } // проверяем наложение на другие элементы (кроме текущей фигуры) if (Tank[X, Y] != null && CurrentFigure.Blocks.SingleOrDefault(p => p == Tank[X, Y]) == null) { return(false); } } return(true); }
private Random Random = new Random((int)DateTime.Now.Ticks); // генератор случайных чисел // добавить фигуру в набор public void AddFigure(TetrisFigure Figure) { Figures.Add(Figure); }
public TetrisFiguresRandom(int Size, bool CheckConnected = true, int MinBlocks = 0, int MaxBlocks = 0) { int Variants = (int)Math.Pow(2, Size * Size); // количество вариантов для анализа for (int Variant = 1; Variant < Variants; Variant++) { bool[] Bits = Convert.ToString(Variant, 2).PadLeft(Size * Size, '0').Select(c => c == '1').ToArray(); // проверяем количество точек int BlockCount = Bits.Count(b => b); if ((MinBlocks != 0 && BlockCount < MinBlocks) || (MaxBlocks != 0 && BlockCount > MaxBlocks)) { continue; } // заполняем точки фигуры, проверяем положение в левом верхнем углу TetrisBlock[] Blocks = new TetrisBlock[BlockCount]; bool FirstRow = false; bool FirstColumn = false; int BlockNumber = 0; for (int X = 0; X < Size; X++) { for (int Y = 0; Y < Size; Y++) { if (Bits[X * Size + Y]) { Blocks[BlockNumber] = new TetrisBlock(X, Y); BlockNumber++; if (Y == 0) { FirstRow = true; } if (X == 0) { FirstColumn = true; } } } } if (!FirstRow || !FirstColumn) { continue; } // проверяем связность фигуры if (CheckConnected) { // http://algolist.manual.ru/maths/graphs/linked.php // начальное значение - точки не связаны foreach (TetrisBlock Block in Blocks) { Block.Mark = 1; } // начинаем проверку связности с этой точки Blocks[0].Mark = 2; TetrisBlock StartBlock; while ((StartBlock = Blocks.FirstOrDefault(p => p.Mark == 2)) != null) { // точка обработана StartBlock.Mark = 3; // связанные точки ставим в очередь на обработку foreach (TetrisBlock Block in Blocks.Where(p => p.Mark == 1 && Math.Abs(StartBlock.X - p.X) + Math.Abs(StartBlock.Y - p.Y) == 1)) { Block.Mark = 2; } } // остались не связанные точки if (Blocks.Any(p => p.Mark == 1)) { continue; } } // проверяем совпадение фигур и добавляем фигуру TetrisFigure Figure = new TetrisFigure(Blocks); if (!Figures.Any(f => f.IsSimilar(Figure))) { AddFigure(Figure); } } }