tags:

views:

61

answers:

3

I am working on a generic game engine for simple board games and such. I am defining interfaces that I will require each game to implement I have classes like IGame, IGameState, IBoardEvaluator, and IMove.

I have methods like IGame.PerformMove(IMove move), that I would like to restrict. If I am playing tic-tac-toe I would like to enforce that I can only use the concrete classes TTTGame, TTTState, TTTMove, etc...

I can think of several ways to do this, but none of them sound fun. Maybe all classes could have a single generic parameter, and I could make sure it matches.

so IGame<T> has method PerformMove(IMove<T> move)

If that works out, I wouldn't know what class to use for T. Maybe it doesn't matter.

My other idea is put a bunch of generic parameters on IGame and give it all of the classes I need. So I would create class TTTGame<TTTMove,TTTState,TTTMove....>

That isn't pretty either. Is there a common pattern to do this?

+1  A: 

The whole point of interfaces is to not care about the concrete implementation of the class. Hence I don't see a need to directly enforce only a certain class, in that case an argument could be made to just pass the class itself.

Such as

TTTGame : IGame 
{
    PerformMove(TTTMove move);
}

Perhaps this is what you are talking about.

public interface IGame<T> where T:IMove
    {
        void PerformMove(T move);
    }

public class TTTGame : IGame<TTTMove>
    {

        public void PerformMove(TTTMove move)
        {
            //perform move
        }

    }

Now your IGame is forced to take an IMove, but like you said..with more classes like (IState..etc) this will get messy quick.

Stan R.
Well the point is if the IGame interface specifies PerformMove takes an IMove, then I can give it any type of move. Your version is not a valid implementation of IGame.
CaptnCraig
updated my answer.
Stan R.
+2  A: 

I dont see what advantage you get from specifying that your TTTGame class can only take TTTMoves.

I think you might be over engineering here.

The only thing you are protecting yourself from by doing that is some rogue MonopolyMove class becoming self-aware and putting itself in your code.

I say stick with the interface definitions and avoid the generics unless you have a really valid case. I dont see one based on what you have mentioned.

santosc
Well the idea is that if I have a TTTGame, I would like to be able to PerformMove() with a TTTMove, and assume it is a TTTMove, and not a monopolyMove. I would rather not have to cast and check in every method.
CaptnCraig
You wouldn't have to check that it is a TTTMove. Ideally, TTTMove inherits from IMove. The code for how to move I expected to be declared as IMove::Move(), and defined (with an overridden method) in TTTMove::Move().I wouldn't try to write code just in case someone calls PerformMove() with a MonopolyMove because why would any of the code use a MonopolyMove in a TicTacToe game?
santosc
Maybe you're right. I'm trying to make it as robust as possible. I am going to have to cast it to a TTTMove, and if that fails I will get a NullReference pretty dang fast. Serves me right for throwing monopoly in there.
CaptnCraig
If you really, really want that, just create a new interface ITTTMove (that inherits from IMove) for tic tac toe moves. Then your PerformMove method for tic tac toe should take in ITTTMove. (Although, that may be a different method than whats defined in your original IGame interface).
santosc
General rule of thumb is to solve the easy case first (just TicTacToe game) and then think about how you could change it to be more generic and share code.
santosc
@CaptnCraig, i think you are missing the point of interfaces and are trying to over engineer this a little bit. Personally I don't see a need to only allow certain concrete classes to be passed in. In that case why have an interface?
Stan R.
+1  A: 

I'd say that the fact that you're feeling a need to restrict the implementation of your interfaces to certain classes is an indication of the interfaces not being specific enough.

Is IGame really a good idea in the first place? The name indicates that it could be equally valid for tic-tac-toe and Quake. Sure, there are some similarities between different board games (such as performing moves), but will you really benefit from creating an abstraction at that high level?

Anders Fjeldstad
Well the idea is that I can create game agnostic vies, presenters, and ai agents that can play any game that conforms to the interface. The goal is to examine certain ai strategies in multiplayer turn based games.
CaptnCraig