//Метод, инициализирующий игровую сессию public static void GameEngine(GameState State) { if (State.AiMode) { MovementResults MoveResult = new MovementResults(); MoveResult = MoveDown(State); if (!MoveResult.MoveMade) { //Если мы проиграли либо вышли за лимит шагов на геном надо обновить геном if (MoveResult.Defeat || State.MovesTaken > State.MovesLimit) { State.ListOfGenomes[State.CurrentGenome].GenomeRating = State.GameScore; //Мы сейчас начнем играть заново новым геномом, поэтому тут необходимо занулить рейтинг State.GameScore = 0; AI.EvaluateNextGenome(State); } //Если же мы не проиграли, то можно делать следующий шаг else { AI.MakeNextMove(State); } } } }
//Метод, сдвигающий фигуру вниз. Одновременно происходит проверка на проигрыш static public MovementResults MoveDown(GameState State) { MovementResults MoveResults = new MovementResults(); RemoveShape(State); State.CurrentFigure.Y++; if (Collision(State)) { State.CurrentFigure.Y--; DrawShape(State); State.GenerateNextFigure(); ClearRows(State); if (Collision(State)) { MoveResults.Defeat = true; if (State.AiMode) { State.ResetGameState(); MoveResults.Defeat = true; } else { State.ResetGameState(); } } MoveResults.MoveMade = false; } DrawShape(State); State.GameScore++; return(MoveResults); }
//Функция создает список всех возможных ходов 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); }