I think you're misunderstanding the concepts behind Model-View-Controller. At some point, the components are going to have to interact with each other, because they have to pass information between them. The point is to decouple the interaction from the implementation of the result.
In other words, the view should have some standard interface that lets the model/controller notify it it needs updating, and the model/controller should have some standard interface that the view uses to inform it of user input, but neither should care how the other goes about handling those events. In theory, a perfect MVC implementation would let you switch out any one of the components for a completely different implementation as long as it stuck to the same interface and everything would work exactly as expected.
In your case, I would design things such that there is a game-engine class which has a method such as this:
int makeMove(row, column)
Where row
and column
are coordinates on the board, and the returned int
represents the player (X = 0, O = 1 or similar. You could even use an enum
to be more explicit``) whose turn it was, so that the GUI can update the appropriate square with that player's icon.
The game engine would then expect the view to have at least these two methods:
void setPlayerTurn(int player)
Which tells the GUI that it should update the display on whose turn it is (same player
as above)
void setPlayerWon(int player, rows, columns)
Which tells the GUI that a player was victorious, and that it should update the three squares identified with rows
and columns
as being the ones that made a player win, and player
is the same player number as above so that it can display the appropriate status message.
The game logic, including tracking the state of the board and whose turn it is can then all be self contained inside the game class, and all the GUI is doing is relaying information from the user to the game, and from the game to the user. You could theoretically swap out either component with a completely different implementation that adhered to those interfaces and still have the game play as expected.
So, the GUI (view) winds up with a reference to the Game Logic (model), and vise-versa. But they're only interacting with each other through a very narrow and generalized interface. Neither really knows or cares what the other does with the information passed through that interface.
Note that in this simplified example I've combined the controller with the view, which is a pretty common thing to do when you're designing a single-purpose GUI. Essentially, the GUI is designed such that it is only ever going to be useful as a Tic Tac Toe board, but it expects you to provide your own set of rules (model).
Having said that, you could see how it wouldn't take much more to decouple these even further by making the GUI simply expose methods that let you set the state (text and icon) of an arbitrary square on a grid, and display a status message. It would expect to be given a controller that provided a method to notify what square on the grid a user interacted with. The controller would then provide the glue to interface between that generic 'grid with status message' view and the game logic model, which expects the interface I described above.
In this case, the GUI (view) gets a reference to the Controller and vise-versa, and then the Controller gets a reference to the Game Logic (model) and vise-versa.