private static int CalculateHeight(GameState State) { GameMechanics.RemoveShape(State); int[] MaxHeights = new int[] { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 }; for (int rows = 0; rows < 20; rows++) { for (int columns = 0; columns < 10; columns++) { if (State.GameMap[rows][columns] != 0 && MaxHeights[columns] == 20) { MaxHeights[columns] = rows; } } } GameMechanics.DrawShape(State); return(20 - MaxHeights.Min()); }
static void Main(string[] args) { Random Randomizer = new Random(); Stopwatch watch = new Stopwatch(); Console.WriteLine("Welcome to Tetris. Press Enter to Load Optimal Genome. Press Backspace to start learning from scratch. Press Escape to quit."); GameState State = new GameState(); Console.CursorVisible = false; if (Console.ReadKey().Key == ConsoleKey.Enter) { Console.Clear(); AI.LoadOptimalPopulation(State); while (true) { GameMechanics.GameEngine(State); Console.SetCursorPosition(0, 0); DrawGraphics(State); DrawNextFigure(State); DrawInfo(State); Thread.Sleep(50); } } else if (Console.ReadKey().Key == ConsoleKey.Backspace) { Console.Clear(); AI.CreateFirstPopulation(State); while (true) { GameMechanics.GameEngine(State); Console.SetCursorPosition(0, 0); DrawGraphics(State); DrawNextFigure(State); DrawInfo(State); Thread.Sleep(50); } } }
//Функция создает список всех возможных ходов public static List <Moves> GetAllPossibleMoves(GameState State) { //Перед выполнением всех процедур нужно сохранить игровое состояние. Далее все действия будем выполнять с ним GameState SavedState = new GameState(); SavedState.SaveGameState(State); //Создаем списки движений и соответствующих им рейтингов List <Moves> ListOfPossibleMoves = new List <Moves>(); List <double> PossibleMoveRatings = new List <double>(); //Для каждого возможного количества вращений... for (int Rotations = 0; Rotations < 4; Rotations++) { List <int> OldX = new List <int>(); for (int x = -5; x <= 5; x++) { //Загружаем сохраненное состояние State.LoadGameState(SavedState); //Вращаем for (int j = 0; j < Rotations; j++) { GameMechanics.RotateShape(State); } //Двигаем влево if (x < 0) { for (int l = 0; l < Math.Abs(x); l++) { GameMechanics.MoveLeft(State); } } //Или вправо else if (x > 0) { for (int r = 0; r < x; r++) { GameMechanics.MoveRight(State); } } //Если фигура двигалась, то надо еще подвинуть, пока перестанет двигаться (встанет на свое место) if (!OldX.Contains(State.CurrentFigure.X)) { MovementResults MoveResult = new MovementResults(); MoveResult = GameMechanics.MoveDown(State); while (MoveResult.MoveMade) { MoveResult = GameMechanics.MoveDown(State); } // Создаем новый экземпляр класса Move - наш новый ход Moves Move = new Moves(); //Заполняем его значения Move.NumberOfRowsCleared = MoveResult.RowsCleared; Move.WeightedHeight = Math.Pow(CalculateHeight(State), 1.5); Move.CumulativeHeight = CalculateCumulativeHeight(State); Move.RelativeHeight = CalculateRelativeHeight(State); Move.NumberOfMissingBlocks = CountMissingBlocks(State); Move.Roughness = CalculateRoughness(State); //Производим оценку Move.Rating += Move.NumberOfRowsCleared * State.ListOfGenomes[State.CurrentGenome].NumberOfRowsCleared; Move.Rating -= Move.WeightedHeight * State.ListOfGenomes[State.CurrentGenome].WeightedHeight; Move.Rating -= Move.CumulativeHeight * State.ListOfGenomes[State.CurrentGenome].CumulativeHeight; Move.Rating -= Move.RelativeHeight * State.ListOfGenomes[State.CurrentGenome].RelativeHeight; Move.Rating -= Move.NumberOfMissingBlocks * State.ListOfGenomes[State.CurrentGenome].NumberOfMissingBlocks; Move.Rating -= Move.Roughness * State.ListOfGenomes[State.CurrentGenome].Roughness; //Если шаг проиграл игру, то он очень плохой. Уменьшаем его рейтинг. if (MoveResult.Defeat) { Move.Rating -= 500; } Move.NumberOfRotations = Rotations; Move.Shift = x; ListOfPossibleMoves.Add(Move); OldX.Add(State.CurrentFigure.X); } } } //Загружаем сохраненное состояние и возвращаем список шагов State.LoadGameState(SavedState); return(ListOfPossibleMoves); }