private List <LinkedList <CheckerModel> > GetPossiblePaths(CheckerModel playerPosition) { var paths = new List <LinkedList <CheckerModel> >(); if (playerPosition.Type == PieceType.Checker) { SetPossibleMovementsRecursive(playerPosition, new LinkedList <CheckerModel>(), new List <CheckerModel>(), playerPosition.Side, paths); } else { if (playerPosition.Neighbors.All(x => x.Side == Side.Empty)) { foreach (var neighbor in playerPosition.Neighbors) { paths.Add(new LinkedList <CheckerModel>(new List <CheckerModel>() { neighbor })); } } else { SetPossibleMovementsForQueenRecursive(playerPosition, new LinkedList <CheckerModel>(), new List <CheckerModel>(), playerPosition.Side, paths); } } return(paths); }
private List <CheckerModel> GetNeighborsForChecker(CheckerModel сheckerModel) { var neighbors = new List <CheckerModel>(); if (сheckerModel.Column - 1 >= 0) { if (сheckerModel.Row - 1 >= 0) { var element = _dataProvider.GetElementAtPosition(сheckerModel.Column - 1, сheckerModel.Row - 1); neighbors.Add(element); } if (сheckerModel.Row + 1 < 8) { var element = _dataProvider.GetElementAtPosition(сheckerModel.Column - 1, сheckerModel.Row + 1); neighbors.Add(element); } } if (сheckerModel.Column + 1 < 8) { if (сheckerModel.Row - 1 >= 0) { var element = _dataProvider.GetElementAtPosition(сheckerModel.Column + 1, сheckerModel.Row - 1); neighbors.Add(element); } if (сheckerModel.Row + 1 < 8) { var element = _dataProvider.GetElementAtPosition(сheckerModel.Column + 1, сheckerModel.Row + 1); neighbors.Add(element); } } return(neighbors); }
public List <CheckerModel> GetNextElementsInDiagonal(CheckerModel playerChecker, CheckerModel otherSideNeighbor, CheckerModel rootElementViewModel = null) { Diagonal diagonal; if (playerChecker.Column - otherSideNeighbor.Column > 0) { diagonal = playerChecker.Row - otherSideNeighbor.Row > 0 ? Diagonal.LeftDown : Diagonal.LeftUp; } else { diagonal = playerChecker.Row - otherSideNeighbor.Row > 0 ? Diagonal.RightDown : Diagonal.RightUp; } Queue <CheckerModel> allElementsInDiagonalFromCurrent = GetAllElementsInDiagonalFromCurrent(otherSideNeighbor, diagonal); if (allElementsInDiagonalFromCurrent.Count == 0) { return(new List <CheckerModel>()); } var emptyElementsAfterOtherChecker = new List <CheckerModel>(); while (allElementsInDiagonalFromCurrent.Count > 0) { var value = allElementsInDiagonalFromCurrent.Dequeue(); if (value.Side != Side.Empty && value != rootElementViewModel) { break; } emptyElementsAfterOtherChecker.Add(value); } return(emptyElementsAfterOtherChecker); }
public void MoveCheckerToNewPosition(CheckerModel checkerToMove, int newPositionColumn, int newPositionRow) { int fromColumn = checkerToMove.Column; int fromRow = checkerToMove.Row; CheckerModel oldPositionedItem = _data[newPositionColumn, newPositionRow]; if (checkerToMove == oldPositionedItem) { return; } if (fromColumn == newPositionColumn && fromRow == newPositionRow) { _data[newPositionColumn, newPositionRow] = checkerToMove; _added.Add(checkerToMove); _deleted.Add(oldPositionedItem); return; } _data[newPositionColumn, newPositionRow] = checkerToMove; checkerToMove.SetNewPosition(newPositionColumn, newPositionRow); _data[fromColumn, fromRow] = oldPositionedItem; oldPositionedItem.SetNewPosition(fromColumn, fromRow); _modified.Add(oldPositionedItem); _modified.Add(checkerToMove); }
public void MoveChecker(CheckerModel fromPlace, CheckerModel toPlace, bool addToHistory = true) { CheckerModel foundChecker = NextMovePlayer.PlayerPositions.SingleOrDefault(x => x.Column == fromPlace.Column && x.Row == fromPlace.Row); CheckerModel toPosition = EmptyCellsAsPlayer.PlayerPositions.SingleOrDefault(x => x.Column == toPlace.Column && x.Row == toPlace.Row); if (toPlace.Side == fromPlace.Side) { toPosition = NextMovePlayer.PlayerPositions.SingleOrDefault(x => x.Column == toPlace.Column && x.Row == toPlace.Row); } int currentCol = foundChecker.Column; int currentRow = foundChecker.Row; int nextCol = toPosition.Column; int nextRow = toPosition.Row; HistoryMove historyMove = NextMovePlayer.MoveCheckerToNewPlace(currentCol, currentRow, nextCol, nextRow); ReCalculateNeighborsAndPaths(); bool isGameEnded = GetIsGameEnded(); if (!isGameEnded) { ChangeTurn(); } if (addToHistory) { _actionsHistory.Push(historyMove); } }
public void AddNewChecker(CheckerModel checkerToAdd, int currentEmptyColumn, int currentEmptyRow) { CheckerModel emptyCheckerToDelete = _data[currentEmptyColumn, currentEmptyRow]; _data[currentEmptyColumn, currentEmptyRow] = checkerToAdd; _added.Add(checkerToAdd); _deleted.Add(emptyCheckerToDelete); }
public void AddNewChecker(CheckerModel resurrectedChecker , int currentEmptyColumn , int currentEmptyRow) { _dataProvider.StartTrackChanges(); _dataProvider.AddNewChecker(resurrectedChecker, currentEmptyColumn, currentEmptyRow); _dataProvider.StopTrackChanges(); }
private List <CheckerModel> GetSimpleEmptyMoves(CheckerModel initialChecker) { List <CheckerModel> moves = initialChecker.Neighbors.Where(x => x.Side == Side.Empty).ToList(); if (_isMainPlayer) { return(moves.Where(x => x.Row > initialChecker.Row).ToList()); } return(moves.Where(x => x.Row < initialChecker.Row).ToList()); }
private void RevertMove(CheckerModel from, CheckerModel to, bool historyMoveIsConvertedToQueen) { KeyValuePair <Player, CheckerModel> fromPlacePair = FindChecker(from); KeyValuePair <Player, CheckerModel> toPlace = FindChecker(to); int currentCol = fromPlacePair.Value.Column; int currentRow = fromPlacePair.Value.Row; int nextCol = toPlace.Value.Column; int nextRow = toPlace.Value.Row; fromPlacePair.Key.MoveCheckerToNewPlace(currentCol, currentRow, nextCol, nextRow, historyMoveIsConvertedToQueen); }
public Dictionary <CheckerModel, List <CheckerModel> > CalculateNeighbors() { var dictionary = new Dictionary <CheckerModel, List <CheckerModel> >(); foreach (CheckerModel playerChecker in _playerPositions) { CheckerModel checkerModel = _dataProvider.GetElementAtPosition(playerChecker.Column, playerChecker.Row); List <CheckerModel> neighbors = checkerModel.Type == PieceType.Checker ? GetNeighborsForChecker(checkerModel) : GetNeighborsForQueen(checkerModel).Select(x => x.Value).ToList(); dictionary.Add(playerChecker, neighbors); } return(dictionary); }
public DataProvider Clone() { var clonedCheckers = new CheckerModel[8, 8]; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { clonedCheckers[j, i] = _data[j, i] == null? null: _data[j, i].Clone(); } } return(new DataProvider(clonedCheckers)); }
private Queue <CheckerModel> GetAllElementsInLeftDownDiagonal(CheckerModel checker) { int checkerRowDown = checker.Row; var elements = new Queue <CheckerModel>(); for (int col = checker.Column - 1; col >= 0; col--) { if (checkerRowDown - 1 >= 0) { var element = _dataProvider.GetElementAtPosition(col, checkerRowDown - 1); elements.Enqueue(element); checkerRowDown--; } } return(elements); }
private Queue <CheckerModel> GetAllElementsInRightUpDiagonal(CheckerModel checker) { var checkerRowUp = checker.Row; var elements = new Queue <CheckerModel>(); for (int col = checker.Column + 1; col < 8; col++) { if (checkerRowUp + 1 < 8) { var element = _dataProvider.GetElementAtPosition(col, checkerRowUp + 1); elements.Enqueue(element); checkerRowUp++; } } return(elements); }
private void RevertMove(HistoryMove historyMove) { RevertMove(historyMove.MovedFromTo.Value, historyMove.MovedFromTo.Key, historyMove.IsConvertedToQueen); foreach (KeyValuePair <CheckerModel, CheckerModel> deletedInfoPair in historyMove.DeletedList) { CheckerModel resurrectedChecker = deletedInfoPair.Key; Player playerToAddChecker = GetPlayerByCheckerSide(resurrectedChecker.Side); playerToAddChecker.AddNewChecker(resurrectedChecker, deletedInfoPair.Key.Column, deletedInfoPair.Key.Row); } ReCalculateNeighborsAndPaths(); bool isFinished = GetIsGameEnded(); if (!isFinished) { ChangeTurn(); } }
public HistoryMove MoveCheckerToNewPlace(int currentCol , int currentRow , int nextCol , int nextRow , bool convertBackToChecker = false) { CheckerModel checker = PlayerPositions.Single(x => x.Column == currentCol && x.Row == currentRow); IEnumerable <LinkedList <CheckerModel> > availablePaths = CalculateAvailablePaths(); LinkedList <CheckerModel> path = availablePaths.Where(x => x.Last.Value.Column == nextCol && x.Last.Value.Row == nextRow).OrderByDescending(x => x.Count).FirstOrDefault(); bool isConvertedToQueen = false; if (ShouldConvertToQueenByPathDuringTaking(path)) { checker.BecomeAQueen(); isConvertedToQueen = true; } CheckerModel newPosition = _dataProvider.GetElementAtPosition(nextCol, nextRow); CheckerModel oldPositionedChecker = _dataProvider.GetElementAtPosition(currentCol, currentRow); if (convertBackToChecker) { oldPositionedChecker.DowngradeToChecker(); } if (_pathCalculator.IsMoveToucheBoard(newPosition)) { oldPositionedChecker.BecomeAQueen(); isConvertedToQueen = true; } _dataProvider.StartTrackChanges(); List <CheckerModel> itemsToTake = GetToTakeCheckers(availablePaths, nextCol, nextRow, checker); var historyMove = new HistoryMove(isConvertedToQueen); foreach (CheckerModel checkerElement in itemsToTake) { var element = new CheckerModel(checkerElement.Column, checkerElement.Row, PieceType.Checker, Side.Empty); historyMove.DeletedList.Add(new KeyValuePair <CheckerModel, CheckerModel>(checkerElement.Clone(), element.Clone())); _dataProvider.MoveCheckerToNewPosition(element, checkerElement.Column, checkerElement.Row); } historyMove.MovedFromTo = new KeyValuePair <CheckerModel, CheckerModel>(oldPositionedChecker.Clone(), newPosition.Clone()); _dataProvider.MoveCheckerToNewPosition(oldPositionedChecker, nextCol, nextRow); _dataProvider.StopTrackChanges(); return(historyMove); }
public Queue <CheckerModel> GetAllElementsInDiagonalFromCurrent(CheckerModel checker, Diagonal diagonal) { switch (diagonal) { case Diagonal.LeftDown: return(GetAllElementsInLeftDownDiagonal(checker)); case Diagonal.LeftUp: return(GetAllElementsInLeftUpDiagonal(checker)); case Diagonal.RightUp: return(GetAllElementsInRightUpDiagonal(checker)); case Diagonal.RightDown: return(GetAllElementsInRightDownDiagonal(checker)); default: throw new ArgumentOutOfRangeException(nameof(diagonal), diagonal, null); } }
private CheckerModel[,] GetCurrentGamePositions(IEnumerable <CheckerModel> mainPlayerElements, IEnumerable <CheckerModel> secondPlayElements, IEnumerable <CheckerModel> emptyElementsList) { var data = new CheckerModel[8, 8]; foreach (CheckerModel position in mainPlayerElements) { data[position.Column, position.Row] = position; } foreach (CheckerModel position in secondPlayElements) { data[position.Column, position.Row] = position; } foreach (CheckerModel position in emptyElementsList) { data[position.Column, position.Row] = position; } return(data); }
private CheckerModel GetNextElementInDiagonal(CheckerModel playerChecker, CheckerModel otherSideNeighbor) { if (playerChecker.Column - otherSideNeighbor.Column > 0) { if (playerChecker.Row - otherSideNeighbor.Row > 0) { return(otherSideNeighbor.Neighbors.SingleOrDefault(x => x.Column == playerChecker.Column - 2 && x.Row == playerChecker.Row - 2)); } else { return(otherSideNeighbor.Neighbors.SingleOrDefault(x => x.Column == playerChecker.Column - 2 && x.Row == playerChecker.Row + 2)); } } if (playerChecker.Row - otherSideNeighbor.Row > 0) { return(otherSideNeighbor.Neighbors.SingleOrDefault(x => x.Column == playerChecker.Column + 2 && x.Row == playerChecker.Row - 2)); } else { return(otherSideNeighbor.Neighbors.SingleOrDefault(x => x.Column == playerChecker.Column + 2 && x.Row == playerChecker.Row + 2)); } }
private void NotificationFromDataAdapter(List <CheckerModel> added, List <CheckerModel> deleted, List <CheckerModel> modified) { var addedForPlayer = new List <CheckerModel>(); foreach (var addedModel in added.Where(x => x.Side == Side)) { PlayerPositions.Add(addedModel); addedForPlayer.Add(addedModel); } var deletedFromForPlayer = new List <CheckerModel>(); foreach (var deletedModel in deleted.Where(x => x.Side == Side)) { CheckerModel toRemove = PlayerPositions.Single(x => x.Column == deletedModel.Column && x.Row == deletedModel.Row); PlayerPositions.Remove(toRemove); deletedFromForPlayer.Add(toRemove); } modified = modified.Where(x => x.Side == Side).ToList(); NotificationAction?.Invoke(addedForPlayer, deletedFromForPlayer, modified); }
private KeyValuePair <Player, CheckerModel> FindChecker(CheckerModel fromPlace) { int column = fromPlace.Column; int row = fromPlace.Row; var findChecker = MainPlayer.PlayerPositions.SingleOrDefault(x => x.Column == column && x.Row == row); if (findChecker != null) { return(new KeyValuePair <Player, CheckerModel>(MainPlayer, findChecker)); } findChecker = RobotPlayer.PlayerPositions.SingleOrDefault(x => x.Column == column && x.Row == row); if (findChecker != null) { return(new KeyValuePair <Player, CheckerModel>(RobotPlayer, findChecker)); } findChecker = EmptyCellsAsPlayer.PlayerPositions.SingleOrDefault(x => x.Column == column && x.Row == row); if (findChecker == null) { throw new Exception($"Can't find checker at position ({column},{row}) in game view model: "); } return(new KeyValuePair <Player, CheckerModel>(EmptyCellsAsPlayer, findChecker)); }
public List <KeyValuePair <Diagonal, CheckerModel> > GetNeighborsForQueen(CheckerModel checkerAsQueen) { var neighbors = new List <KeyValuePair <Diagonal, CheckerModel> >(); int checkerRowUp = checkerAsQueen.Row; int checkerRowDown = checkerAsQueen.Row; bool skipUpDiagonal = false; bool skipDownDiagonal = false; for (int col = checkerAsQueen.Column - 1; col >= 0; col--) { if (checkerRowUp + 1 < 8 && !skipUpDiagonal) { var element = _dataProvider.GetElementAtPosition(col, checkerRowUp + 1); if (element.Side != Side.Empty) { skipUpDiagonal = true; } neighbors.Add(new KeyValuePair <Diagonal, CheckerModel>(Diagonal.LeftUp, element)); checkerRowUp++; } if (checkerRowDown - 1 >= 0 && !skipDownDiagonal) { var element = _dataProvider.GetElementAtPosition(col, checkerRowDown - 1); if (element.Side != Side.Empty) { skipDownDiagonal = true; } neighbors.Add(new KeyValuePair <Diagonal, CheckerModel>(Diagonal.LeftDown, element)); checkerRowDown--; } } checkerRowUp = checkerAsQueen.Row; checkerRowDown = checkerAsQueen.Row; skipUpDiagonal = false; skipDownDiagonal = false; for (int col = checkerAsQueen.Column + 1; col < 8; col++) { if (checkerRowUp + 1 < 8 && !skipUpDiagonal) { var element = _dataProvider.GetElementAtPosition(col, checkerRowUp + 1); if (element.Side != Side.Empty) { skipUpDiagonal = true; } neighbors.Add(new KeyValuePair <Diagonal, CheckerModel>(Diagonal.RightUp, element)); checkerRowUp++; } if (checkerRowDown - 1 >= 0 && !skipDownDiagonal) { var element = _dataProvider.GetElementAtPosition(col, checkerRowDown - 1); if (element.Side != Side.Empty) { skipDownDiagonal = true; } neighbors.Add(new KeyValuePair <Diagonal, CheckerModel>(Diagonal.RightDown, element)); checkerRowDown--; } } return(neighbors); }
private IEnumerable <CheckerModel> GetSimpleEmptyMovesForQueen(CheckerModel queen) { return(queen.Neighbors.Where(x => x.Side == Side.Empty)); }
private List <CheckerModel> GetToTakeCheckers(IEnumerable <LinkedList <CheckerModel> > availablePaths, int column, int row, CheckerModel checker) { if (!availablePaths.Any()) { return(new List <CheckerModel>()); } LinkedList <CheckerModel> neededPath = availablePaths.Where(x => x.Last.Value.Column == column && x.Last.Value.Row == row).OrderByDescending(x => x.Count).FirstOrDefault(); if (neededPath == null) { return(new List <CheckerModel>()); } var itemsToRemove = new List <CheckerModel>(neededPath.Where(x => x.Side != Side.Empty && x.Side != checker.Side)); return(itemsToRemove); }
private void SetPossibleMovementsForQueenRecursive(CheckerModel currentChecker , LinkedList <CheckerModel> path , List <CheckerModel> visited , Side checkerSide , List <LinkedList <CheckerModel> > paths, Diagonal fromDiagonal = Diagonal.Initial) { path.AddLast(currentChecker); paths.Add(new LinkedList <CheckerModel>(path)); visited.Add(currentChecker); List <KeyValuePair <Diagonal, CheckerModel> > neighborsForQueen = _neighborsCalculator.GetNeighborsForQueen(currentChecker); neighborsForQueen = FilterNeighborsOnOppositeDirection(neighborsForQueen, fromDiagonal); var otherSideNeighbors = neighborsForQueen.Where(x => x.Value.Side != Side.Empty && x.Value.Side != checkerSide); foreach (KeyValuePair <Diagonal, CheckerModel> otherSideNeighborPair in otherSideNeighbors) { if (path.Contains(otherSideNeighborPair.Value)) { continue; } Diagonal diagonal = otherSideNeighborPair.Key; CheckerModel otherSideNeighbor = otherSideNeighborPair.Value; List <CheckerModel> elementsAfterOpponent = GetNextElementsInDiagonal(currentChecker, otherSideNeighbor, path.First.Value); foreach (CheckerModel positionAfterNextChecker in elementsAfterOpponent) { if (positionAfterNextChecker == null || (positionAfterNextChecker.Side != Side.Empty && !path.Contains(positionAfterNextChecker))) { continue; } var cycle = new LinkedList <CheckerModel>(); if (path.Contains(positionAfterNextChecker)) // Cycle here { int indexOfChecker = 0; int index = 0; foreach (var checkerElement in path) { cycle.AddLast(checkerElement); if (checkerElement == positionAfterNextChecker) { indexOfChecker = index; } index++; } int len = index - indexOfChecker; if (len > 3) { List <KeyValuePair <Diagonal, CheckerModel> > neighborsForCycleRoot = _neighborsCalculator.GetNeighborsForQueen(positionAfterNextChecker); foreach (var checkerElement in neighborsForCycleRoot.Where(x => x.Value.Side != Side.Empty)) { List <CheckerModel> toVisitAgain = GetNextElementsInDiagonal(positionAfterNextChecker, checkerElement.Value); foreach (CheckerModel previouslyVisitedToWalkAgain in toVisitAgain) { CheckerModel firstToNotDelete = path.Last.Value; CheckerModel secondToNotDelete = path.Find(positionAfterNextChecker).Next.Value; if (previouslyVisitedToWalkAgain != null && (previouslyVisitedToWalkAgain.Side == Side.Empty) && previouslyVisitedToWalkAgain != firstToNotDelete && previouslyVisitedToWalkAgain != secondToNotDelete) { visited.Remove(previouslyVisitedToWalkAgain); } } } path.AddLast(otherSideNeighbor); SetPossibleMovementsForQueenRecursive(positionAfterNextChecker, path, visited, checkerSide, paths, diagonal); path.RemoveLast(); } } bool notContainsInCycle = !cycle.Contains(positionAfterNextChecker); if (notContainsInCycle) { path.AddLast(otherSideNeighbor); SetPossibleMovementsForQueenRecursive(positionAfterNextChecker, path, visited, checkerSide, paths, diagonal); path.RemoveLast(); } } } path.RemoveLast(); }
private void SetPossibleMovementsRecursive(CheckerModel currentChecker , LinkedList <CheckerModel> path , List <CheckerModel> visited , Side checkerSide , List <LinkedList <CheckerModel> > paths , LinkedList <CheckerModel> outerCycle = null) { path.AddLast(currentChecker); paths.Add(new LinkedList <CheckerModel>(path)); visited.Add(currentChecker); var otherSideNeighbors = currentChecker.Neighbors.Where(x => x.Side != Side.Empty && x.Side != checkerSide); foreach (CheckerModel otherSideNeighbor in otherSideNeighbors) { CheckerModel positionAfterNextChecker = GetNextElementInDiagonal(currentChecker, otherSideNeighbor); if (positionAfterNextChecker != null && (positionAfterNextChecker.Side == Side.Empty || path.Contains(positionAfterNextChecker))) { if (outerCycle != null && outerCycle.Contains(positionAfterNextChecker)) { continue; } var cycle = new LinkedList <CheckerModel>(); if (path.Contains(positionAfterNextChecker)) // Cycle here { int indexOfChecker = 0; int index = 0; foreach (var checkerElement in path) { cycle.AddLast(checkerElement); if (checkerElement == positionAfterNextChecker) { indexOfChecker = index; } index++; } int len = index - indexOfChecker; if (len > 3) { foreach (CheckerModel checkerElement in positionAfterNextChecker.Neighbors.Where(x => x.Side != Side.Empty)) { CheckerModel tempToDelete = GetNextElementInDiagonal(positionAfterNextChecker, checkerElement); CheckerModel firstToNotDelete = path.Last.Value; CheckerModel secondToNotDelete = path.Find(positionAfterNextChecker).Next.Value; if (tempToDelete != null && (tempToDelete.Side == Side.Empty) && tempToDelete != firstToNotDelete && tempToDelete != secondToNotDelete) { visited.Remove(tempToDelete); } } path.AddLast(otherSideNeighbor); if (IsMoveToucheBoard(positionAfterNextChecker)) { SetPossibleMovementsForQueenRecursive(positionAfterNextChecker, path, visited, checkerSide, paths); } else { SetPossibleMovementsRecursive(positionAfterNextChecker, path, visited, checkerSide, paths, cycle); } path.RemoveLast(); } } bool notContainsInCycle = !cycle.Contains(positionAfterNextChecker); if (notContainsInCycle) { path.AddLast(otherSideNeighbor); if (IsMoveToucheBoard(positionAfterNextChecker)) { SetPossibleMovementsForQueenRecursive(positionAfterNextChecker, path, visited, checkerSide, paths); } else { SetPossibleMovementsRecursive(positionAfterNextChecker, path, visited, checkerSide, paths, cycle); } path.RemoveLast(); } } } path.RemoveLast(); }
public bool IsMoveToucheBoard(CheckerModel positionAfterNextChecker) { return((_isMainPlayer && positionAfterNextChecker.Row == 7) || (!_isMainPlayer && positionAfterNextChecker.Row == 0)); }