using System.Collections.Generic;
using System.Text.RegularExpressions;
public static void Main(string[] args)
Board boardAndPlay = new Board(Read());
public static List<string> Read()
return new List<string>()
public class InputBoardReader
public List<Tuple<char, int, int>> Animals { get; private set; }
public int Rows { get; private set; }
public int Columns { get; private set; }
public bool InputChecker { get; private set; }
public InputBoardReader(List<string> board)
if (ReadAndCheckTheBoard(board))
private bool ReadAndCheckTheBoard(List<string> board)
Columns = board[0].Length;
if (CheckIfBoardIsRectangle(board))
private bool CheckIfBoardIsRectangle(List<string> board)
foreach (string s in board)
private void ReadAnimals(List<string> board)
Animals = new List<Tuple<char, int, int>>();
Regex regex = new Regex(@"^[a-zA-Z]*$");
for (int r = 0; r < Rows; r++)
for (int c = 0; c < Columns; c++)
if (regex.IsMatch(board[r][c].ToString()))
char letter = board[r][c];
Tuple<char, int, int> animalInfo = new Tuple<char, int, int>(letter, r, c);
public class Board : IBoard
private Dictionary<char, Type> possibleAnimalsByChar = new Dictionary<char, Type>()
{'a', typeof(Antelope) },
{'s', typeof(Elephant) },
{'k', typeof(Crocodile) }
public List<Animal> Animals { get; private set; }
public FieldOnBoard[,] Fields { get; private set; }
public int NumberOfRows { get; private set; }
public int NumberOfColumns { get; private set; }
public Board(List<string> boardAsString)
InputBoardReader input = new InputBoardReader(boardAsString);
NumberOfRows = input.Rows;
NumberOfColumns = input.Columns;
CreateCleanBoard(NumberOfRows, NumberOfColumns);
PopulateTheBoard(input.Animals);
Console.WriteLine("Wrong input!");
public bool CheckIfFieldIsOnBoard(int rowIndex, int columnIndex)
if (rowIndex >= 0 && rowIndex < NumberOfRows && columnIndex >= 0 && columnIndex < NumberOfColumns)
private void CreateCleanBoard(int rows, int columns)
Fields = new FieldOnBoard[rows, columns];
for (int counter = 0; counter < rows * columns; counter++)
for (int r = 0; r < rows; r++)
for (int c = 0; c < columns; c++)
FieldOnBoard field = new FieldOnBoard();
private void DisplayBoard()
for (int i = 0; i < NumberOfRows; i++)
for (int j = 0; j < NumberOfColumns; j++)
if (Fields[i, j].AnimalAtField != null)
Console.Write(string.Format("{0}", Fields[i, j].AnimalAtField.Symbol));
Console.Write(Environment.NewLine);
Console.Write(Environment.NewLine);
private void UpdateListOfAnimals()
Animals = new List<Animal>();
foreach (FieldOnBoard f in Fields)
if (f.AnimalAtField != null)
Animals.Add(f.AnimalAtField);
private void MovementPhase()
for (int i = 0; i < Animals.Count; i++)
foreach (Animal a in Animals)
if (!a.MovedThisTurn && a.PossibleMoves.Any())
a.Move(this, a.PossibleMoves[0]);
private void CleaningAfterMovePhases()
foreach (Animal a in Animals)
private void UpdateAnimalsPossibleMovementList()
foreach (Animal a in Animals)
a.RemoveFirstElementOfPossibleMovesList();
for (int phase = 1; phase <= 4; phase++)
UpdateAnimalsPossibleMovementList();
CleaningAfterMovePhases();
private void PopulateTheBoard(List<Tuple<char, int, int>> readedAnimals)
foreach (var tuple in readedAnimals)
if (possibleAnimalsByChar.ContainsKey(Char.ToLower(tuple.Item1)))
if (possibleAnimalsByChar[Char.ToLower(tuple.Item1)] == typeof(Antelope))
Fields[tuple.Item2, tuple.Item3].AnimalAtField = new Antelope(tuple.Item2, tuple.Item3, tuple.Item1, this);
if (possibleAnimalsByChar[Char.ToLower(tuple.Item1)] == typeof(Elephant))
Fields[tuple.Item2, tuple.Item3].AnimalAtField = new Elephant(tuple.Item2, tuple.Item3, tuple.Item1, this);
if (possibleAnimalsByChar[Char.ToLower(tuple.Item1)] == typeof(Lion))
Fields[tuple.Item2, tuple.Item3].AnimalAtField = new Lion(tuple.Item2, tuple.Item3, tuple.Item1, this);
if (possibleAnimalsByChar[Char.ToLower(tuple.Item1)] == typeof(Crocodile))
Fields[tuple.Item2, tuple.Item3].AnimalAtField = new Crocodile(tuple.Item2, tuple.Item3, tuple.Item1, this);
for (int i = 9; i > 0; i--)
foreach (Animal a in Animals)
foreach (Animal a in Animals)
public class FieldOnBoard
public Animal AnimalAtField { get; set; }
public abstract class Animal : IAnimal
public char Symbol { get; private set; }
private int CurrentPositionRowIndex { get; set; }
private int CurrentPositionColumnIndex { get; set; }
private Dictionary<string, int[]> AdjacentFields { get; set; }
private Type Type { get; set; }
private Type LikesToEat { get; set; } = null;
public bool MovedThisTurn { get; protected set; }
private List<string> OrderOfMovement { get; set; }
public List<string> PossibleMoves { get; private set; }
protected Animal(int positionRow, int positionColumn, char symbol, Board board)
CurrentPositionRowIndex = positionRow;
CurrentPositionColumnIndex = positionColumn;
SetStartingPositionOnBoard(board);
DetectNeighborhood(board);
private char DrawGender(char symbol)
Randomizer rand = new Randomizer(2);
int femaleOrMale = rand.PickNumber(0);
return Char.ToLower(symbol);
return Char.ToUpper(symbol);
private void SetStartingPositionOnBoard(Board board)
board.Fields[CurrentPositionRowIndex, CurrentPositionColumnIndex].AnimalAtField = this;
private void DetectNeighborhood(Board board)
AdjacentFields = new Dictionary<string, int[]>();
if (board.CheckIfFieldIsOnBoard(CurrentPositionRowIndex - 1, CurrentPositionColumnIndex))
AdjacentFields.Add("up", new int[] { CurrentPositionRowIndex - 1, CurrentPositionColumnIndex });
if (board.CheckIfFieldIsOnBoard(CurrentPositionRowIndex, CurrentPositionColumnIndex + 1))
AdjacentFields.Add("right", new int[] { CurrentPositionRowIndex, CurrentPositionColumnIndex + 1 });
if (board.CheckIfFieldIsOnBoard(CurrentPositionRowIndex + 1, CurrentPositionColumnIndex))
AdjacentFields.Add("down", new int[] { CurrentPositionRowIndex + 1, CurrentPositionColumnIndex });
if (board.CheckIfFieldIsOnBoard(CurrentPositionRowIndex, CurrentPositionColumnIndex - 1))
AdjacentFields.Add("left", new int[] { CurrentPositionRowIndex, CurrentPositionColumnIndex - 1 });
public bool Move(Board board, string direction)
DetectNeighborhood(board);
if (AdjacentFields.ContainsKey(direction))
move = AdjacentFields[direction];
if (board.Fields[move[0], move[1]].AnimalAtField == null)
board.Fields[CurrentPositionRowIndex, CurrentPositionColumnIndex].AnimalAtField = null;
CurrentPositionRowIndex = move[0]; CurrentPositionColumnIndex = move[1];
board.Fields[CurrentPositionRowIndex, CurrentPositionColumnIndex].AnimalAtField = this;
public void FinishMoving()
RenewPossibleMovesList();
public void RemoveFirstElementOfPossibleMovesList()
PossibleMoves.RemoveAt(0);
public void EatNeighbors(Board board)
foreach (var entry in AdjacentFields)
if (board.Fields[entry.Value[0], entry.Value[1]].AnimalAtField != null)
if (board.Fields[entry.Value[0], entry.Value[1]].AnimalAtField.Type == LikesToEat)
board.Fields[entry.Value[0], entry.Value[1]].AnimalAtField = null;
protected void SetFood(Type type)
protected void SetMovementLists(List<string> orders)
OrderOfMovement = orders;
RenewPossibleMovesList();
private void RenewPossibleMovesList()
PossibleMoves = new List<string>();
OrderOfMovement.ForEach((item) =>
private void CreateNewAnimal(int positionRow, int positionColumn, Board board)
char randomizedGender = DrawGender(Symbol);
if (Type == typeof(Antelope))
board.Fields[positionRow, positionColumn].AnimalAtField = new Antelope(positionRow, positionColumn, randomizedGender, board);
if (Type == typeof(Elephant))
board.Fields[positionRow, positionColumn].AnimalAtField = new Elephant(positionRow, positionColumn, randomizedGender, board);
if (Type == typeof(Crocodile))
board.Fields[positionRow, positionColumn].AnimalAtField = new Crocodile(positionRow, positionColumn, randomizedGender, board);
if (Type == typeof(Lion))
board.Fields[positionRow, positionColumn].AnimalAtField = new Lion(positionRow, positionColumn, randomizedGender, board);
public void Breeding(Board board)
if (Char.IsLower(Symbol))
char male = Char.ToUpper(Symbol);
DetectNeighborhood(board);
foreach (var entry in AdjacentFields)
if (board.Fields[entry.Value[0], entry.Value[1]].AnimalAtField is Animal)
if (board.Fields[entry.Value[0], entry.Value[1]].AnimalAtField.Symbol == male)
Dictionary<string, int[]> localCopyOfAdjacentFields = AdjacentFields;
localCopyOfAdjacentFields.Remove(entry.Key);
Randomizer rand = new Randomizer(localCopyOfAdjacentFields.Count);
localCopyOfAdjacentFields = localCopyOfAdjacentFields.OrderBy(x => rand.PickNumber(0)).ToDictionary(item => item.Key, item => item.Value);
foreach (var leftFields in localCopyOfAdjacentFields)
if (board.Fields[leftFields.Value[0], leftFields.Value[1]].AnimalAtField == null)
CreateNewAnimal(leftFields.Value[0], leftFields.Value[1], board);
public override string ToString()
return String.Format("My symbol is: {0}, currently I`m at ({1},{2})", Symbol, CurrentPositionRowIndex, CurrentPositionColumnIndex);
public class Antelope : Animal
List<string> movements = new List<string> { "right" };
public Antelope(int positionRow, int positionColumn, char symbol, Board board) : base(positionRow, positionColumn, symbol, board)
SetMovementLists(movements);
public class Elephant : Animal
List<string> movements = new List<string> { "up", "right", "down", "left" };
public Elephant(int positionRow, int positionColumn, char symbol, Board board) : base(positionRow, positionColumn, symbol, board)
SetMovementLists(movements);
public class Crocodile : Animal
readonly Type food = typeof(Antelope);
List<string> movements = new List<string> { "up", "down" };
public Crocodile(int positionRow, int positionColumn, char symbol, Board board) : base(positionRow, positionColumn, symbol, board)
SetMovementLists(movements);
public class Lion : Animal
readonly Type food = typeof(Antelope);
List<string> movements = new List<string> { "right", "left" };
public Lion(int positionRow, int positionColumn, char symbol, Board board) : base(positionRow, positionColumn, symbol, board)
SetMovementLists(movements);
private int LimitTo { get; set; }
public Randomizer(int limitTo)
public int PickNumber(int limitFrom)
Random rand = new Random();
int number = rand.Next(limitFrom, LimitTo);
bool MovedThisTurn { get; }
List<string> PossibleMoves { get; }
bool Move(Board board, string direction);
void EatNeighbors(Board board);
void Breeding(Board board);
List<Animal> Animals { get; }
FieldOnBoard[,] Fields { get; }
int NumberOfRows { get; }
int NumberOfColumns { get; }
bool CheckIfFieldIsOnBoard(int rowIndex, int columnIndex);