3

I'm trying to create a turn-based card game with MVC pattern. I have some doubts about the correct design.

I created a model consisting of these classes:

  • Card (use Suit)
  • Deck (40 cards, extract card method, number of cards remaining)
  • Table
  • Suit (enum)
  • Player(hand cards, name if human, number of cards in hand, collected card i think)
  • GameModel (has references to Deck, Table and takes two players in the constructor)

I will create two Player objects and GameModel (computer and player) when the user press the "New Game" button. Is this the right way to proceed? (i don't need Strategy pattern i guess)

I created a GameController class that has references to GameModel class and the GameFrame (the view) class.

I need to implement some sort of "pause" when the computer is playing or when someone wins the hand and picks the cards on the table, so i guess i need to create a Runnable class with game loop. Correct?

How should these classes interact? (is this correct english? xD)

Player action example:

Click card button --> actionListener --> invokes GameController method that check if the action is possible (is my turn and i can play, computer played) --> if possible the GameController update the GameModel --> the GameLoop notice the GameModel change and calls some UI method that upgrades the view (with some Thread.sleep(...)). Can this work?

But in all this, where i should i put the AI? Thanks for your help :)

Loris
  • 454
  • 7
  • 19

1 Answers1

3

This is not a question that can be answered in only one way. Do you want to make it only singleplayer or multiplayer? For singleplayer you probably won't need any Threads. I would suggest following things for the beginning:

  • Your game-loop should, of course, be placed insided your GameController. Something like while(gameNotFinished()) { player = determineNextPlayer(); player.makeTurn(); }
  • Add another mvc hierachy: PlayerView PlayerController PlayerModel. It will make your code more readable. PlayerController (with makeTurn()) in this case could be an interface, so you can implement it with a HumanPlayerController and an ComputerPlayerController (which has and needs no view).
  • GameController implements ActionListener: So you simply add the controller to every button or whatever you have and it will then handle the user input.
  • Make sure you do not write controlling code into your view. The view only sends user requests to the controller
  • Use the Observer pattern for view and model. See java.util.Observer and java.util.Observable. When the model changes (e.g. card is laid down) it notifies the observers (all views) and the views then get the new card on top.

Is this the right way to proceed?
I don't see why a "New Game" button and the action you described should be a problem. Maybe consider to "reset" everything in this action, so the player can press the button any time he wants to.

sort of "pause" when the computer is playing
Do you want to wait extra time until the computer player finished his turn? I would say let him play as fast as possible. As long as the game only continues when the human player has finished his turn.

Can this work?
I would change it to following:
Click card button --> GameController (is the ActionListener) --> method that check if the action is possible (is my turn and i can play, computer played Card can be laid down. The Controller contacts you when it is your turn! When your turn is possible disable the card button and makeTurn() will enable it again) --> if possible the GameController update the GameModel --> The GameModel notifies all Observers (views) and then they get updated

Where i should i put the AI?
As explained above next to the HumanPlayerController implementing the PlayerController interface.

Thomas
  • 330
  • 2
  • 13
  • For now the game will be very easy, human vs computer without multiplayer. I need "pause" when the computer has already played or the user has already played, and it's necessary to determine who won the hand, otherwise the user will not understand nothing. Anyway thanks for the tips, it can be a good start, but not all the actions of the game can be instantaneous. – Loris May 22 '14 at 11:11
  • You still can add Thread.sleep(timeInMilliSeconds) at desired places to slow down the game. Or do you want some kind of "Continue" button? – Thomas May 22 '14 at 11:14
  • It is safe to use "Thread.sleep(...)" out of a runnable? I don't want to risk freeze the view. However, i noticed that you wrote "GameModel implements ActionListener" above. Maybe you meant "GameController" instead of "GameModel"? Ps: my GameController class is a singleton. – Loris May 22 '14 at 11:19
  • 1
    Of course the **GameController** implements the ActionListener (fixed). And yes you're right, Thread.sleep() could lead to problems. I found this question explaining this issue: http://stackoverflow.com/questions/14074329/using-sleep-for-a-single-thread – Thomas May 22 '14 at 13:31
  • Thanks. Sorry but i need another little explanation. You said that i have to create an interface "PlayerController" with "makeTurn" method. This interface must be implemented by "HumanPlayerController" and "ComputerPlayerController", but human actions are simply clicks on the buttons, there's no logic. So, the "makeTurn" method of the "HumanPlayerController",and the same "HumanPlayerController" what they should do? – Loris May 22 '14 at 13:56
  • 1
    Either makeTurn() enables the buttons in the view of the human player or it just sets a boolean value in GameController which prevents the ActionEvents from the view to actually do something. – Thomas May 22 '14 at 14:01
  • At this point, the buttons in the view should implements HumanPlayerController instead of GameController i guess – Loris May 22 '14 at 17:57
  • 1
    Yes the view only communicates with its "own" controller and this takes place mostly via ActionEvents (can be other event types, too). I found this article about hierarchical MVC very useful: http://www.javaworld.com/article/2076128/design-patterns/hmvc--the-layered-pattern-for-developing-strong-client-tiers.html – Thomas May 22 '14 at 19:10
  • Ehm, i'm sorry but how can find out which button i'm clicking from HumanPlayerController? I can't add get methods in the view, is not correct. UPDATE: i used actionCommand. – Loris May 23 '14 at 16:59