Home > Software design >  C# how to properly code reusable classes?
C# how to properly code reusable classes?

Time:10-19

I want to be able to call methods from a GameState object, like this:

public void some_method (GameState s)
{
  GameState s_copy = s.duplicate()
  s_copy.make_move()
  //s_copy now has made a move, but s remains untouched.
}

So the class GameState should have:

-The make_move method.

-The duplicate method. Duplicate is used to create a deepcopy of the object, so that I can make moves in a GameState without altering the original one.

Which makes me believe I need to create an interface, because I can have multiple games. Here is where I am confused. I'm currently trying:

public interface IGameState
{
  void make_move();
  GameState duplicate();
}
public class GameState : IGameState
{
  public virtual void make_move(){}
  public virtual GameState duplicate(){}
}
public class Game1 : GameState
{
  public override void make_move(){ /*whatever a move is in game 1*/}
  public GameState override duplicate() { /*deepcopy of the class variables*/ }
}
public class Game2 : GameState
{
  public void make_move(){ /*whatever a move is in game 2*/}
  GameState duplicate() { /*deepcopy of the class variables*/ }
}

So, when I call "some_method", I expect to be able to pass any of the game objects:

g1 = new Game1();
g2 = new Game2();
some_method((GameState)g1);
some_method((GameState)g2);

But I seem to be unable to access the methods, and the duplicate() GameState typing is creating a mess when the newly created GameState is used. I've read about generic types, static, abstract classes and interfaces, but cannot wrap my head around how this is supposed to be done, and feels wrong so far.

Edit: Game1 and Game2 are completely different games: othello and tictactoe let's say

CodePudding user response:

You don't want to alter the GameState objects between games. So create one GameState object for each game, provided each game share the same definition of what would be a state for the game.

public class GameState
{
  public string State {get;set;} = ""
}

public class Game {
  private readonly GameState state;
  public Game(GameState state) {
    this.state = state;
  }

  public void Play() {
     state = "Game is Starting";
  }

}

var g1 = new Game(new GameState() { State = "Game1State" });
var g2 = new Game(new GameState() { State = "Game2State" });
g1.Play();

CodePudding user response:

I think you can overcome your issues by applying some minor changes:

public interface IGameState
{
  // Just Naming Conventions here
  void MakeMove();
  IGameState Duplicate();
}

// Get rid of GameState class

public class Game1 : IGameState // implement the interface
{
  public void MakeMove(){ /*whatever a move is in game 1*/}
  public IGameState Duplicate() { /*deepcopy of the class variables*/ }
}

// Game2 accordingly

// then `SomeMethod` should work like this:
public void SomeMethod (IGameState s)
{
  IGameState s_copy = s.Duplicate();
  s_copy.MakeMove();
  //s_copy now has made a move, but s remains untouched.
}

In order to keep the changes, you might want to return the mutated state:

public IGameState SomeMethod (IGameState s)
{
  IGameState s_copy = s.Duplicate();
  s_copy.MakeMove();
  return s_copy;
}
  • Related