I was asked to give a high level design of Pacman. Please review the OOP design, this is not a full implementation. only the design is important here.
Please comment if the design is missing anything. or can be improved? The main problem I think is to keep Single responsibility, I am having a hard time here not have all the parts of the game knowing each other.
namespace PacmacOopDesign
{
class Program
{
static void Main(string[] args)
{
//we need to init the maze in the board
Board board = new Board();
BaseFigure Pacman = new Pacman(board.GetEmptyPosition());
BaseFigure RedGhost = new Ghost(board.GetEmptyPosition(), System.Drawing.Color.FromName("Red"));
//the logic for the entire game is here is kind of a loop which check many things in each turn.
List<BaseFigure> figures = new List<BaseFigure>();
figures.Add(Pacman);
figures.Add(RedGhost);
Game game = new Game(figures,board);
}
}
}
My first issue is about how do I init the whole game play? do I create all the figures, and the maze and then let the game place them? or do I need to have it pre-defined?
BaseFigure.cs
public abstract class BaseFigure
{
protected Position _position;
protected System.Drawing.Color _color;
//init the base position of the figure
public BaseFigure(Position position, Color color)
{
_position = position;
_color = color;
}
public abstract void DrawShape();
//if the ghost is moving toward the same position the player is moving game is ended
// if pacman collected all the dots and fruits game is ended
}
Board.cs
public class Board
{
public int Level { get; set; }
public int Width { get; set; }
public int Height { get; set; }
//the number of dots to eat in order of winning this specific Board
public int NumOfDotsToEat { get; set; }
//this is a 2d maze
// 0 means wall
// 1 - empty spot for player/computer figures
// 2 means a dot will be placed
// 2-10 fruits/ special
public Position[] Maze { get; set; }
public Position GetEmptyPosition()
{
//get a random/ valid predefined position for a new figure on the board
return new Position(0, 0);
}
public Board()
{
}
}
Game.cs
public class Game
{
private bool _isWinCondition;
private List<BaseFigure> _figures;
private Board _board;
public Game(List<BaseFigure> figures, Board board)
{
_isWinCondition = false;
_figures = figures;
_board = board;
}
public void GameStart()
{
while (!_isWinCondition)
{
foreach (var figure in _figures)
{
GetNewLocation(figure);
figure.DrawShape();
}
}
}
private void GetNewLocation(BaseFigure figure)
{
//if figure is pacman check that user input is valid.
//remove the dot if it has dot, and remove from total in Boards.
//check if isWinCondition
//if next frame has fruit in it, change to killing ghosts ability and speed up move.
//if figure is Ghost check how close to pacman you are is less then minimal of the ghost
//change the strategy of the ghost of chasing pacman, if more continue with old strategy.
//if new location next to pacman when he ate fruit remove ghost from board
//if new location next to pacman the game is ended.
}
}
Game class is the main problem I have, should it really handle all the logic and not each class/Figure handle her own strategy of moving?
Ghost.cs
public class Ghost : BaseFigure
{
private int _minimalDistance;
public Ghost(Position position, Color color) : base(position, color)
{
_minimalDistance = 5;
}
public override void DrawShape()
{
}
public void LockOnFigure()
{
//if in minimal distance from other figure start to chase it
}
}
for example the ghost can have it's own strategy once it reaches a cetrain threshold to go after pacman, the problem is that it needs to be aware how does the board look and where Pacman is...
so the other option is for the Game to handle the strategy and tell the ghost where to go and which strategy to use.
What do you think?
Pacman.cs
public class Pacman : BaseFigure
{
public Pacman(Position position)
: base(position, System.Drawing.Color.FromName("yellow"))
{
_position.Value = 2;
}
public override void DrawShape()
{
// draw the pacman shape
}
}
Position.cs
public class Position
{
public int X { get; set; }
public int Y { get; set; }
public int Value { get; set; }
public Position(int x, int y)
{
X = x;
Y = y;
}
}