I'm having a small design issue with a Checkers game to be done in Java--

I'm not really worried about coding it, I can do that.

The problem is listing out the dependencies between classes.


For example, what should be responsible for what?

IF I code the program with the checkers pieces being capable of moving on the board, they need to know where they are on the board.

The problem with this? Should pieces really be responsible for knowing where they are on the board, or should they simply be 'used' as pieces?

The problem is broken down into two cases (and could be broken down into more, but for now let's say two cases).

The first case--

Piece base class, BlackPiece and RedPiece derived classes.

CheckersEngine emulates where the pieces can move within the board (adds movement restrictions, etc).

With this method, a piece (since it's really just "a piece") is only responsible for knowing if it has been attacked and killed. It does NOT hold responsibility for moving, since the piece is just "a piece."

The problem with this? I'm no forcing the board to determine when a piece moves and where.


I thought the design for that would be sloppy, and tedious. Sure it is the Engine's responsibility to make the game run, but I just felt that this design could be improved.


The second method results in pieces being more than pieces - they are now CheckersPieces. CheckersPieces know their direction of movement within a given CheckersBoard (so they must have a reference to the Engine).

I don't mind this pattern, because now within the actual Engine, upon loading I can simply call upon "move" for a piece and the piece will move with its given direction.

For some reason I feel a bit stuck. It feels as if the pieces now have too much responsibility?

Really, I just want to know if my approach is correct (and, just as a reminded, my approach is the second method).

-Alex

"The problem with this? I'm now forcing the board to determine when a piece moves and where."

"Really, I just want to know if my approach is correct (and, just as a reminder, my approach is the second method)."

Just correcting some misspelled words from the initial post.

I'm not sure that there is a "correct" answer to this. You have a GUI, which includes a board and all the pieces. I would probably have a Piece class that know its coordinate on the 8 x 8 board and knew its color. You could have a class called CheckersPiece that extended the Piece class, but I wouldn't have the Piece class know the rules of Checkers (what if you wanted to use it in a different game) and hence it wouldn't know how it could move. But it might make sense to have a CheckersPiece class that had a function that could tell you the legal moves using that CheckersPiece. Depending on the particular rules of Checkers though, especially the rule that if a jump is possible, it MUST be taken, a CheckersPiece would probably not have enough information to know whether it can move (i.e. it has the ability to make a move without jumping since there is a space that it can move to, but it is not allowed to because some OTHER CheckersPiece somewhere else on the board has a jump.

You also didn't mention, regarding "responsibility" of making the move, is there any artificial intelligence going on here or is it a human player versus human player game? If it has an artificial intelligence angle, a CheckersPiece would not have enough information probably to decide to make the move. You need to be looking at the whole board for that. So I think the ultimate "responsibility" should lie with a Game or Board class, something that has a birds-eye view and which has a Collection of CheckersPieces. Make the CheckersPieces relatively "dumb". They know what color they are, they know their coordinates, they know whether they are a king or not, and if you pass the Board to them, they can return a list of "possible" legal moves that are available to them. Don't have them actually make the move though. Leave it to a higher level class that can see everything and knows all the rules of checkers to decide (if using artificial intelligence) which move to make and to make the actual move (i.e. change the CheckersPiece coordinates, make it a king, delete it, etc.).

That's my two cents. You are probably going to have some MouseListener attached to the Board, which will be a JPanel or part of a JPanel, and when clicked, will have to know which CheckersPiece was clicked. Call a function within the CheckersPiece class to return whether/which moves are available. That's as responsible/intelligent as I would make the CheckersPiece class. But yes, I think a piece should know where it is and know what directions it can move, so I'd be more inclined to go with something closer to your second idea than your first.

Comments
Thanks for taking the time to help again! =)

I'm terribly sorry for not mentioning responsibility.

We're going to make this a Client/Server application for users to log in and play checkers. Of course the Server will only host for 2 clients. There wont be any real AI other than the rules implemented in the Engine itself, and the pieces knowing their legal moves.

I already know a few ways of getting the user to interact with the board using a mouse listener, and doing a flip-view of the board (basically the board will appear upside down for the second client so that they can make moves in a more comfortable angle).

I really like the idea of pieces not being capable of moving but knowing their legal moves. I do want to make a move method for pieces that take a mouse x and y coordinate and will return false if the piece isn't a legal move on the board. Of course the pieces will only be responsible for moving within their given direction. I can make the board force limitations on their movement.

Before a piece can move, I will have it selected, and (most likely) make some kind of faint marker of the possible moves for the pieces once it is selected. The user can then click on one of the valid locations, but if they right-click or a click registered on the focused pane is NOT the location, the piece will be deselected.

I can post what I have now from NetBeans. Really it's just a shell since I got stuck with the above problem before you got here.

P.S. I'll mail the code to you so you can see what I have so far.

> I really like the idea of pieces not being capable of moving but knowing their legal moves.

I am yet to see a game where the pieces don't move. Each and every piece is capable of moving though the set of legal moves differ from game to game. IMO, the pieces should be capable of moving be always passed a valid position so that they can dumbly and safely move to the position mentioned. Maybe a common interface like Moveable should do the trick here. Also consider abstracting the 'position' concept in your game inside a class which will provide you the flexibility of switching between 1D, 2D and 3D.

Since you are into a client server architecture, you might as well have a Game class whose instance will be a game in progress having attributes like total game time, the game name, the reference to the board in use and the players involved in the game.

There are many other finer points which come to mind but I think the above mentioned ones should get you going.

Comments
Totally approved =)

You can have a class that just controls the movements. It can check the piece and move it. The board class will have the information about the pieces that are on it. If the region is free, then the piece can move also it'll check the rules defined for that piece. After the piece is moved, you can save the information about the location and all in the piece and have the region on the board 'locked'.

Maybe a common interface like Moveable should do the trick here.

i was going to suggest interfaces too, i think moveable is a good idea. i was going to suggest GamePiece as an interface with a method such as isValidMove(x,y), and maybe isAlive() and some others.

i was going to suggest interfaces too, i think moveable is a good idea. i was going to suggest GamePiece as an interface with a method such as isValidMove(x,y), and maybe isAlive() and some others.

I didn't bother with the isAlive method, but i definitely made an isValidMove in the actual GameEngine.

I went with s.o.s.'s advice to make pieces dumbly move because they really are just pieces being used on the board.

So far everything is good, and now the pieces don't even need to know they are being used by the board!

The purpose of the class (im enrolled int) is not to simply make a functional program, but to practice good OOD concepts. The project I'm working on will be graded on the rule of-

"is it a good design?"

"does it make sense?"

"does it work?"

-and a lot more.

At the moment I'm having a small problem determining if I should have an auto-jump feature for when a user encounters multiple challengers on the board that he must clear in the standard rules of English draughts (checkers). If I don't do this then creating the game will be easy, but the finished product wont be as user-friendly. If I DO implement it, I have to stop the auto-jump when there is a fork (a point where the user has to make a split-decision between which path he/she will take).

I'm nearly done with implementing the rules. I got rid of a lot of unnecessary interfaces and simply let the Engine handle it, whereas the only public methods the Engine has are--

selectPiece(int x, int y);
moveSelected(int x, int y);
displayBoard();
displayChallengers() // for debugging at the moment, but i may just keep it for the board itself

-- and I feel as if the first three methods could inherit from an interface called GameBoard which will make the design look as if it was created from the concept of "a game."

This thread is as good as solved, I just need to know what I should do about the jump-forking? Shouldn't be too hard to implement an auto-jump, I just don't want users getting pissed off if they can't take the path they want.

Design choices you make have to direct impact on your thought process. Had not the pieces implemented the Moveable interface, would the flow have remained the same? Does the ' Moveable ' interface logically make sense? And now do you really think that 'GameBoard' sounds like an Interface name or more so like a name of a Class? Would it make any difference if it were not an interface? Does making it an Interface solve any immediate problem you face?

I still see that you aren't using the abstraction called ' Position ' to hide the gory 2D details of your game. Instead of implementing the additional 'user friendly' features, concentrate on such finer points and you might end up getting more grades than those you focus on the immediate solution at hand. Also does displayBoard() really do all the rendering activity? If yes, then you need to rethink the design since it's really not the responsibility of the Engine to render the board. An alternate design here might be to have a RenderAble interface which is implemented by all the rendering classes like PieceRenderer , BoardRenderer and have methods like draw() , refresh() etc. The way you use these classes would be to have a constructor which takes a reference to Piece and Board respectively which would be with the Game. There are almost infinite possibilities out there when coming up with the design though the best would be the one which doesn't need any explaining to even a layman. All I am doing here is opening up them for you so you can decide what's best given the constraints you are developing the game in.

Though I don't like / play checkers, it's almost a known fact that the initial approximation you end up making for finishing your code turns out to be incorrect and the coding activity takes up more time than planned. My advice would be to forget about the additional feature 'auto-jump' and go ahead and complete your game. Client-Server architecture games aren't that easy to create especially when you are doing them for the first time.

Happy Coding!

I got rid of the displayBoard() method because you're right - an Engine shouldn't be responsible for rendering, it's there to "set the rules." It was there for debugging really.

I think I'm not yet experienced enough to understand the Position abstraction. Do I need to code around the concept of a board (potentially) being in a particular dimension if it is a particular game?

Wait... if what you mean is controlling the movement of pieces based on the dimensional environment I've only implemented it for 2D... I didn't think that people would play checkers in 3D but I see you have a point.

If I understand this correctly, the position abstraction will allow me to implement positions for objects in a 1D. 2D or 3D environment easily by simply extending from Position and redefining methods with their necessary behavior?

"Also consider abstracting the 'position' concept in your game inside a class which will provide you the flexibility of switching between 1D, 2D and 3D."

I have private methods called "isValidMove(int x, int y)," "jumpMove(CheckersPiece, int oldX, int oldY, int x, int y)," "validLocation(CheckersPiece, int oldX, int oldY, int x, int y),"
and other pieces that control where a piece can move. Am I even close to the right track there, or do you mean implementing a "Point" class, encapsulating it, and making each piece have aggregate control on these said Points?

For example, in the Piece constructor, I simply give an array of Positions the piece will be governed by, and code around the possible positions the piece can move from/to ?

I've done something similiar by initially assigning the pieces with a set of points. This can easily be changed by adding a 3rd dimension to the points and simply coding around it.

Again I could be way off. Could you please be more elaborate if I am?

> For example, in the Piece constructor, I simply give an array of Positions the piece will be
> governed by, and code around the possible positions the piece can move from/to ?

Huh? I thought it was pretty clear that Piece should *not* have inking as to what it has to do. It goes something along these lines. A 'Player' makes a 'Move'. The 'CheckerEngine', validates the move, does the necessary operations and updates the 'Board'.

> This can easily be changed by adding a 3rd dimension to the points and simply coding
> around it.

It's just a thought, I am not asking you to add a third dimension but abstract away the dimensional aspect of your game by encapsulating it in a class so that the contract of the methods which use them doesn't change, only the implementation does. Something roughly along the lines of:

public class Position {
  private int x;
  private int y;
  // and many other things
}

// With the position abstraction for 2D
public void renderPiece(Position pos) {
  // Draw something at (x, y)   
}

// With position abstraction for 3D
public void renderPiece(Position pos) {
  // Draw something at (x, y, z)   
}

// Without position abstraction for 2D
public void renderPiece(int x, int y) {
  // Draw something at (x, y)   
}

// Without position abstraction for 3D
public void renderPiece(int x, int y, int z) {
  // Draw something at (x, y, z)   
}

Though the idea is pretty vague, I hope you get the point.

I think I am starting to understand the Position concept. For some reason it's not clicking immediately, maybe it's because I'm not looking at the big picture like I really should be.

By the way, here's the current debugging that I'm using to test the functionality of the board using the temporary displayBoard() method I mentioned earlier.

init:
deps-jar:
Compiling 1 source file to F:\RemakesAndNEwProjects\Java_Folder\Checkers_Project\build\classes
compile-single:
run-single:
Starting with Red's turn...
[ ][B][ ][B][ ][B][ ][B]
[B][ ][B][ ][B][ ][B][ ]
[ ][B][ ][B][ ][B][ ][B]
[ ][ ][ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ][ ]
[R][ ][R][ ][R][ ][R][ ]
[ ][R][ ][R][ ][R][ ][R]
[R][ ][R][ ][R][ ][R][ ]

Red Challengers: 0

Black Challengers: 0

Red -Attempting to move from: (0, 5)
 to (1, 4)
1
SingleMove: Red is no longer a challenger.
Black's turn.
true
[ ][B][ ][B][ ][B][ ][B]
[B][ ][B][ ][B][ ][B][ ]
[ ][B][ ][B][ ][B][ ][B]
[ ][ ][ ][ ][ ][ ][ ][ ]
[ ][R][ ][ ][ ][ ][ ][ ]
[ ][ ][R][ ][R][ ][R][ ]
[ ][R][ ][R][ ][R][ ][R]
[R][ ][R][ ][R][ ][R][ ]

Red Challengers: 0

Black Challengers: 0

Black -Attempting to move from: (3, 2)
 to (2, 3)
-1
SingleMove: Black is no longer a challenger.
Red's turn.
true
[ ][B][ ][B][ ][B][ ][B]
[B][ ][B][ ][B][ ][B][ ]
[ ][B][ ][ ][ ][B][ ][B]
[ ][ ][B][ ][ ][ ][ ][ ]
[ ][R][ ][ ][ ][ ][ ][ ]
[ ][ ][R][ ][R][ ][R][ ]
[ ][R][ ][R][ ][R][ ][R]
[R][ ][R][ ][R][ ][R][ ]

Red Challengers: 0

Black Challengers: 0

[ ][B][ ][B][ ][B][ ][B]
[B][ ][B][ ][B][ ][B][ ]
[ ][B][ ][ ][ ][B][ ][B]
[ ][ ][B][ ][ ][ ][ ][ ]
[ ][R][ ][ ][ ][ ][ ][ ]
[ ][ ][R][ ][R][ ][R][ ]
[ ][R][ ][R][ ][R][ ][R]
[R][ ][R][ ][R][ ][R][ ]

Red Challengers: 1
(1, 4)
Black Challengers: 1
(2, 3)
Red -Attempting to move from: (1, 4)
 to (3, 2)
2
JumpMove: Red is no longer a challenger.
Black's turn.
true
Incorrect piece selected!
[ ][B][ ][B][ ][B][ ][B]
[B][ ][B][ ][B][ ][B][ ]
[ ][B][ ][R][ ][B][ ][B]
[ ][ ][ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ][ ]
[ ][ ][R][ ][R][ ][R][ ]
[ ][R][ ][R][ ][R][ ][R]
[R][ ][R][ ][R][ ][R][ ]

Red Challengers: 0

Black Challengers: 2
(2, 1)(4, 1)
Red Challengers: 0

Black Challengers: 2
(2, 1)(4, 1)
Black -Attempting to move from: (2, 1)
 to (4, 3)
2
JumpMove: Black is no longer a challenger.
Red's turn.
[ ][B][ ][B][ ][B][ ][B]
[B][ ][ ][ ][B][ ][B][ ]
[ ][B][ ][ ][ ][B][ ][B]
[ ][ ][ ][ ][B][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ][ ]
[ ][ ][R][ ][R][ ][R][ ]
[ ][R][ ][R][ ][R][ ][R]
[R][ ][R][ ][R][ ][R][ ]

Red Challengers: 0

Black Challengers: 0

Red -Attempting to move from: (2, 5)
 to (1, 4)
-1
SingleMove: Red is no longer a challenger.
Black's turn.
[ ][B][ ][B][ ][B][ ][B]
[B][ ][ ][ ][B][ ][B][ ]
[ ][B][ ][ ][ ][B][ ][B]
[ ][ ][ ][ ][B][ ][ ][ ]
[ ][R][ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][R][ ][R][ ]
[ ][R][ ][R][ ][R][ ][R]
[R][ ][R][ ][R][ ][R][ ]

Red Challengers: 0

Black Challengers: 0

Black -Attempting to move from: (4, 1)
 to (3, 2)
-1
SingleMove: Black is no longer a challenger.
Red's turn.
[ ][B][ ][B][ ][B][ ][B]
[B][ ][ ][ ][ ][ ][B][ ]
[ ][B][ ][B][ ][B][ ][B]
[ ][ ][ ][ ][B][ ][ ][ ]
[ ][R][ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][R][ ][R][ ]
[ ][R][ ][R][ ][R][ ][R]
[R][ ][R][ ][R][ ][R][ ]

Red Challengers: 0

Black Challengers: 0

Red -Attempting to move from: (1, 6)
 to (0, 5)
-1
SingleMove: Red is no longer a challenger.
Black's turn.
[ ][B][ ][B][ ][B][ ][B]
[B][ ][ ][ ][ ][ ][B][ ]
[ ][B][ ][B][ ][B][ ][B]
[ ][ ][ ][ ][B][ ][ ][ ]
[ ][R][ ][ ][ ][ ][ ][ ]
[R][ ][ ][ ][R][ ][R][ ]
[ ][ ][ ][R][ ][R][ ][R]
[R][ ][R][ ][R][ ][R][ ]

Red Challengers: 0

Black Challengers: 0

Black -Attempting to move from: (4, 3)
 to (5, 4)
1
SingleMove: Black is no longer a challenger.
Red's turn.
[ ][B][ ][B][ ][B][ ][B]
[B][ ][ ][ ][ ][ ][B][ ]
[ ][B][ ][B][ ][B][ ][B]
[ ][ ][ ][ ][ ][ ][ ][ ]
[ ][R][ ][ ][ ][B][ ][ ]
[R][ ][ ][ ][R][ ][R][ ]
[ ][ ][ ][R][ ][R][ ][R]
[R][ ][R][ ][R][ ][R][ ]

Red Challengers: 2
(4, 5)(6, 5)
Black Challengers: 0

Red -Attempting to move from: (4, 5)
 to (6, 3)
2
JumpMove: Red is Still a challenger.
Red's turn.
[ ][B][ ][B][ ][B][ ][B]
[B][ ][ ][ ][ ][ ][B][ ]
[ ][B][ ][B][ ][B][ ][B]
[ ][ ][ ][ ][ ][ ][R][ ]
[ ][R][ ][ ][ ][ ][ ][ ]
[R][ ][ ][ ][ ][ ][R][ ]
[ ][ ][ ][R][ ][R][ ][R]
[R][ ][R][ ][R][ ][R][ ]

Red Challengers: 1
(6, 3)
Black Challengers: 1
(7, 2)
BUILD SUCCESSFUL (total time: 4 seconds)

I'm trying to chase down the error in the last board (where 5, 2 isn't marked as a challenger, even though it really is Red's turn still).

Design choices you make have to direct impact on your thought process. Had not the pieces implemented the Moveable interface, would the flow have remained the same? Does the ' Moveable ' interface logically make sense? And now do you really think that 'GameBoard' sounds like an Interface name or more so like a name of a Class? Would it make any difference if it were not an interface? Does making it an Interface solve any immediate problem you face?

This is absolutely correct.

I need to take a step back and rethink the design.

Once I'm finished getting it to work, I think I'll write out what objects/functions are dependant on each other, re-write the design, then add concepts that are necessary to get things going (for example, an Engine is made up of parts. I should be delegating specific jobs to the right engine parts to make a CheckersEngine functional).

I'd like to email you my "junk" code as it is before dismembering it later.

I know it's kinda against the rules, and I'm sorry but I really don't want someone else in the class to have any copy of the assignment. I'm technically weeks ahead of the due date and I'm nearly done getting the game to be restrictive to the rules of Checkers, all that is left is making the GUI (easy) and making the Client/Server with Multi-threading (I'm assuming it will be harder than I think).

> I know it's kinda against the rules

And the reason it is against the rules is because instead of the thousands of beginners / needy out there, only a single person gets the solution. Reading individualistic emails / PM's would be kind of difficult given the little time I get for helping people out, not to mention the moderation duties which need to be performed. I hope you understand.

You have been supplied with a lot of good ideas and I am pretty sure you will be able to come with a relatively better implementation than your peers. And hey, getting things right in the first go is kind of a sin. :-)

Comments
Lol, I suppose so. Thanks for all of your help!

> I know it's kinda against the rules

And the reason it is against the rules is because instead of the thousands of beginners / needy out there, only a single person gets the solution. Reading individualistic emails / PM's would be kind of difficult given the little time I get for helping people out, not to mention the moderation duties which need to be performed. I hope you understand.

You have been supplied with a lot of good ideas and I am pretty sure you will be able to come with a relatively better implementation than your peers. And hey, getting things right in the first go is kind of a sin. :-)

Do you use NetBeans? I can draw out some example diagrams of possible designs to code around by making interfaces and using Reverse Engineering (or simply starting from scratch).

I've already, on paper, written out a few possible designs but I am not sure any of them make sense.

Even if something does make sense, applying the concept is a lot harder than simply simulating a theory.

For example, I currently have my pieces being added to the CheckersEngine, which I don't know if it really makes sense.

It would make sense if the pieces were demoted to a different class like...

wait... is this where posiiton would come in? Is this what you were trying to explain to me?

It would make sense for a CheckersEngine to keep track of Positions, then have a GameBoard (which implements displayable) take GamePieces (which implements displayable also) and simply display the pieces based on the location of the Positions within the CheckersEngine.

In order to interact with the pieces I'll most likely have methods in the Engine to select a position if the turn is correct.

Ok... before I continue, am I on the right track?

Edit: If I'm tracking positions, and simply make extensions of Position objects, I can load the engine with the custom extensions, where the engine simply keeps track of the Positions, but I can possible find a way to make the position displayable... bah... serious mind blocks @_@

This is much harder than simply "coding."

I re-thought the process of making the game, and started from scratch pretending I knew nothing and didn't start coding.

I know what I need for the game.

-I need a way for the user(s) to interact with each other during play (Client/Server)
-I need a way for the users to see the game (Display)
-I need a way for the game to be restricted to the rules of some game (Engine)

I know that these are the fundamental elements, and have no real order.

From here I've decided to place these 3 classes away from each other. I know that they will have relationships with each other, I just don't know how yet.

I'm trying to look at the big picture.

The first thing the users need to do is connect to the Client/Server, so I'll make a class called Connect that will deal with the connection of the clients to the server.

When the users are Connected, the game should be displayable. The question is what should I use to tie the Client/Server with the Display, and the Engine in all of this?

I suppose I need a new object called UserInterface that encapsulates the Connect and Display objects.

The UserInterface will have commands that allow the user(s) to interact with the Display. The Display has commands that accept coordinates, but Display is either an abstract class or interface so it must be redefined.

Because Display is just a Display, I'd like to have more functionality so I created a derived object called GameDisplay. Before I could implement methods, I thought to myself "a GameDisplay does more than just move pieces. Games in general don't just move pieces, sometimes they just show things but I want these users to interact with pieces!" So I stopped myself and derived an object called BoardGameDisplay where Board games are known to have pieces, therefore it is acceptable to have commands like selectPiece(int, int) to select a piece at a given location. The int arguments are provided for dual functionality between Mouse and Keyboard messages (and possibly other joysticks too). BoardGameDisplay IS-A display so it also has a display() command just like a general display object.

This is nice and dandy, but the display has no idea what it should be restricting the user to, so I decided to make an Engine object. I don't know how a display works with an Engine directly, but I guess I can make a general GameDisplay Object take a GameEngine that will decide how objects will be displayed. I decided to make the GameEngine much less general by turning it into a BoardGameEngine, but GameEngine will still have its functionality, such as do(Command c), where Command will be specific commands for a game (in this case I'll make them very general but they will exist).

I'm close to something, I can feel it. This makes some sense finally and it's a design I like. It also shows some essence of potential re-use but I can't see it right away.

Here is my approach, based on what i believe the reasonable assumptions should be. One, a good checkers game should be able to function in a variety of environments. Thus it should be written so that it can play the game so that it can be played using sockets using multiple computers or on a single computer without having to be completely rewritten. Thus the Engine and the Display should be written so as to be independent of the socket communication code/classes. The Display should be written in a way that the Engine can be rewritten to account for different checkers rules and the Display would not need to be rewritten at all. The Engine should be written so that the Display could be made into a console a display rather than a GUI display class and the Engine would not have to be rewritten. The Socket class should not care about the rules and should not care about the rules of the game and should not care about whether the Display is GUI or console. Board and Piece similarly should be written to not care whether Display is console or GUI.

So, one thing to consider. What starts the whole thing off Where should main be and how does the pre-game socket connection occur? You can have the socket connection dance start immediately when the program starts, thus having the IP and port information that the sockets need hard wired into the code or you can have a JPanel that is independent of the Display GUI where there are buttons that a user can push to sponsor a game (be the host/server computer) or to join another game (be the guest/client computer), and you can ask the user for the IP/port information when those buttons are clicked.

So since we want versatility, main should not be in the Engine, it should not be in Display, and it should not be in the socket communication class. So write a Main class and stick main in there. Let's say that you decide that you want to have the IP/port information hard coded (or passed by command line argument to main), and a computer knows whether it is the server or the client also by command line argument. If you decide that the client will always be black and the server will always be red, and that the guest always moves first, you only need one socket for all of this, which the server, started first, will create and listen to, and the guest will connect to. So main is in Main and is run and it creates the socket connection and when it connects, then it makes a call to the Display class (or some middle class that coordinates everything) to paint the board and the pieces.

You're doing a GUI, so let's have a MouseListener and a Move class. A piece is selected and a Move function is called from the Display class, which interacts with the Engine and returns the possible legal moves based on the rules. Assuming there is at least one move using that piece, the board is redrawn with the possible moves highlighted. The user clicks on the square that finishes the move, a Move function is called to actually make the move (communicating with the Engine class) and update the Board and Pieces, then redraw the board/pieces. That Move class function then calls the Socket class, which sends the two grid coordinates which comprise the move that was made down the socket, the Socket class on the other calls the Move class function, which implements the move and updates the board, pieces, and now it's the other player's turn and they select their move on the board just like the last player did, call the Move class function, update the board, send the coordinates down the socket, etc.

So if you change anything (i.e. no sockets, console instead of GUI, etc., rules of the game, etc.), the whole thing doesn't have to be written. The socket class is concerned only with socket communication. Remove the sockets and Move stays the same except you are commenting out the last step where it calls the socket class functions. Board and Piece don't care about the Display or the Engine. Display is "dumb" concerning the rules and the sockets. Move handles all of the coordination between the Engine and the sockets and the display. Main is small and simply gets things started. I think that's the best, most versatile, and easiest to revise approach.

Comments
Wow.. although that design is beyond the scope of the class, I like it =)

The craft of good design comes from knowing what a bad design is. Unless you do something wrong, you won't know what is right. It's about time you started implementing something and stopped achieving maximum perfection. Re factoring is a part and parcel of software development and IMO is the thing which makes you learn. This thread has many good contributions so the only thing which remains to be done is; Just do it!

The craft of good design comes from knowing what a bad design is. Unless you do something wrong, you won't know what is right. It's about time you started implementing something and stopped achieving maximum perfection. Re factoring is a part and parcel of software development and IMO is the thing which makes you learn. This thread has many good contributions so the only thing which remains to be done is; Just do it!

I've tried hard to prevent a bad design, but you're right. I probably wont know until I experience a bad design (for example, make a design then later realize the flaws of the design when it comes to versatility and adding new features).

Apparently I have quite a lot to learn about OOD and OOP. I'll probably stick with one design during the course, then after I'll remake this project a few times using some of the designs here and some of my own to get some practice in.

I'll also probably look at all of my old OLD projects and try to make a better design with the concept behind them.

I really didn't think something like this would be this hard. It's going to take awhile, and a lot of study and practice, but I am going to eventually figure it out.

I really didn't think something like this would be this hard. It's going to take awhile, and a lot of study and practice, but I am going to eventually figure it out.

You never "finish" learning good design skills. Each project is different in some way (if it wasn't, you would just keep using the first one right?) and there are many possible ways to design it. Finding the one that best suits the particulars of the problem at hand is the "art" portion of programming and comes only through experience - it's also the challenging part that keeps it interesting.

While good design skills only come with experience, there are several good books available with valuable and thought-provoking advice. If you're interested, I would recommend:

Design Patterns: Elements of Reusable Object-Oriented Software - the canonical book on software design patterns. You will surely here criticism regarding the overuse of patterns and some can certainly be "overkill" for a lot of simple design tasks, but reading and knowing about them will give you a perspective on design and object interaction that you won't get from simple coursework or tutorials.

Refactoring: Improving the Design of Existing Code covers just what the title says: Improving the design of code you already have written and working.

Code Complete, Second Edition has all kinds of useful information and advice on many aspects of programming, design, and software project management. While geared more towards working professionals rather than students, there is a wealth of information for students who wish to look beyond the basics and into things that professionals deal with in larger projects.

Comments
I will have to purchase those books sometime soon =)
This question has already been answered. Start a new discussion instead.