I am having a bit of issues with design. Maybe I am thinking about this all wrong, but it seems that what I am designing only works well in a procedural manner.
The Game
I am working on a game, this game has about 10-20 players inside of it, and consists of 3 rounds. When players start up the game, the server loads their data from a database, stores it in a java class, and sends data that is requested to the client. Lets call this Player.java. This class is persistent in between the rounds of the game.
Every player in the game also has a role. This role changes in-between each round and I need this role to be linked with Player.java in some way. Right now I have 3 roles: Hunter, Seeker, and Spectator. Each role has the same basic things: onDeath(), onRespawn(), onKill(KillEvent event). I also need to be able to easily check what role a player is. (For example linking the roles with a enum).
The Problem
The problem I am running into now is how do I implement this in a OOP way? Originally, I had each role as a class that implements Role.java, and every time a role is created, it takes a Player in the constructor. This is all fine and dandy until I start changing people's roles in the middle of the rounds and after the end of each round. It seems like bad practice to me if I am consistently setting the players role to a new object.
Summary
To sum this up (since I am terrible at describing things), it seems like all of this would work perfectly in a procedural manner, but I can't figure out for the life of me a good way to implement this concept using OOP. The way I have it implemented now, each Player has a enum stating what role they are, and to change that role I simply change the enum in Player. With that being said though, once I get to the game logic, I end up with a TON of nested if statements, something that I feel could be greatly reduced with some polymorphism.
So to end with a question, what would be a good plan of attack to implement this (or a slightly modified version of this system) in a object oriented way without having to consistently create new objects that take in data from old objects? (I don't have a ton of experience with OOP, but to me this just seems like a bad idea)
I think I would go for this solution:
Make Player an Interface
Create a Proxy-Class for it (a class that has only one property, which is of type Player, and redirects all methods to this object). Lets call it ConcretePlayer
Add a setRole method, taking a Role to ConcretePlayer.
Make Role implement Player
Create Subclasses of Role like you did, each takes a ConcretePlayer in their constructor.
Store the stats that are shared among all Roles in the ConcretePlayer
Externally use Player or ConcretePlayer to access everything.
It's not fleshed out perfectly, but I think you get the idea. You may find that Role and Player shouldn't share the same interface, or that you want to create an own interface for the callbacks, but that depends on the rest of your code and usecases.
Related
I have been coding in java for about a year and a half, and have made some small games and programs that I think turned out very well. The problem is that I am mostly self taught and I most of my code and class structure is not organized or "correctly structured". This didn't matter to me for the smaller things I made, but if I were to take on a larger project I would want to structure it correctly and make it organized.
In a previous mini-RPG game I had
Main Class (Main loop + Main method)
Player Class (containing player position and player stats)
Engine Class (containing map and collision detection between player and map
Map Class (containing map data)
My Main class contained an instance of Player and of Engine, and Engine had an instance of Map. The problem is that Player then could't tell the Engine where it was, and the Engine couldn't adjust Player's position and stats when something happened on the Map. So I ended up having some static variables and methods in both Player and Engine to get them to communicate.
I guess my overall question is is this the correct structure of classes, and is it correct to use static methods and variables here? If not, how would you structure these classes, or would there need to be more or less classes?
My overall objective is to understand how to structure classes in this previous game so I can better structure classes in a bigger project I want to take on.
It is a rather broad question, but the general answer is no.
As a rule you shouldn't use static fields to connect instances. (There are a couple of possible exceptions, but as a rule of thumb it's a useful one.) The basic idea of OOP is that everybody has a reference to whoever they want to send messages to. So if a Player needs to tell the Engine something, it should have a reference to whichever Engine instance it belongs to. Or you can redesign your architecture so only Engine sends messages to Map and Player, it's difficult to tell without more detail about your setup whether that would be appropriate in this case.
Another piece of general advice is to try to sit down with a piece of paper, write down the name of all three of your classes and in a separate column write down all the things the system has to do. And then you should try to figure out who's responsible for what. In a good design this decision is simple, if you find yourself shoehorning different things into one class, that's a sign that you should maybe need a more detailed model with more classes.
I would also suggest you take a look at the observer pattern and the publish-subscribe pattern, as it might be what you need.
Try take take a look at some design-patterns.
Which design pattern you want to use depends on what you prefer. Some can be found here on Wikipedia.
I also take it that you are familiar with OOP? Some more general info can be found here on Wikipedia.
Looking at your specific story, I think a MVC-design would be a nice solution.
MVC meaning Model View Controller.
Here you have your Model, classes holding different forms of data.
Your Controller, controls your Model, contains all the real logic.
And your View, this is the graphic end of your application.
You'd probably want to put and instance of your player in your engine as well. That way your engine will control everything (the player and the map). Hope that helps!
From what you described there a few possible ways to handle this. One would be to use a messaging system. I would look into Java Messaging Service (JMS). Another would be to make your app event drive. Here is a neat little tutorial on how to do this using spring : https://spring.io/guides/gs/messaging-reactor/. Having said that, if your intent is get a better understanding of problem solving using Java, I would first try and mimic these two approaches on your own, without any bulky frameworks.
I'm curious as to which is the better practice and the reasoning behind it, for this example I'm going to be using a social application which contains a 'friends' and a 'ignore' list with some custom logic based on them, (For sending messages directly, etc)
Which would be the better practice, and why?
Scenario 1:
class user {
List<> friends;
List<> ignores;
...
logical methods here
}
Scenario 2:
class User {
Social social;
...
}
class Social {
List<> friends;
List<> ignores;
...
logical methods here
}
I've seen both scenarios used throughout numerous applications and I'm curious as to which is the "Correct" way to lay it out in java, these will have methods such as
#addFriend(User user)
check ignore
check valid user
check other info
add to list
end
#getFriend(int id)
find friend by id
check online status
return friend
It seems like while have a 'Social' class may be a cleaner approach, does it really follow good practices? Seems like it'd use more memory/user just for cleaner code.
The reason why you have such constructs as your Social, most of the time, is that they represent a logical set of data and operations which is needed for different entities in your application.
If nothing other than User has those properties and actions, then there is no point in doing it separately from User. But you may design it separately anyway, for future uses (for example, if you want to be able to expand it later and you believe there will be other entities which will need Social functionality).
Looking at this from an object-oriented viewpoint, it means that the Social is a type. And then you have to ask yourself, is whether your User is_a Social or whether your User has_a Social. Does it make sense to say that the user has a "social subsystem" or is the user a "social object"? If the correct relation is is_a, then User should extend Social. If not, it should have a Social member, such as you described.
However, in Java, since you can't have multiple inheritance of implementation, sometimes your type may inherit from several types, and you have to decide which of them to extend. Many times, you simulate multiple inheritance of implementation, by having a member of what should have been the "second parent class", declare all the methods in your class, and delegate them to that member.
So the general guidelines are, more or less:
If in your application's domain, the only class where it will make sense to have friends and ignores and their operations is User, and no other conceivable entity would ever need them, then implement them directly in User.
If other entities may need similar functionality, and not all of them extend User anyway, you may consider this functionality to be an entity or class in its own right, and then you should have every class which has an is_a relationship to this entity extend it.
If Java's limitations of multiple inheritance don't allow extending directly, as it makes more sense for the class to extend some other class, you should embed an object and delegate the operations.
There may be other practical reasons to separate the Social entity from User, despite User being the only class to use them. For example, if you have several different possible implementations of "social" behavior, you may want to be able to use various Social subclasses as "plug-ins" inside User, rather than subclassing User.
Don't worry about memory so early. Go for readable/cleaner code. Premature optimization is root of all evil.
This is really based on the logic of your program. But consider that increasing the number of classes unnecessarily, is not good practice.
In your example, if the User class only contains a Social field, and you will just delegate all the method calls to the Social class, then go with scenario one.
On the other hand, if the User class has many more fields, like name, date of joining ... then it would be even better to create a separate class for such fields such as UserInfo in order to better structure your program and enhance code readability.
Now the main concerns are not the memory or performance costs of class structure.
Way more important are readability and clean code, AND the possibility to persist domain classes in a DB in the most simple and efficient way.
The later include composition or aggregation concern which is specific for different DB's.
You should care about the design aspects becoz with this you will have maintainable,scalable and readable code.
Now going by your example , i find second scenario as good case as it follows the SRP(Single Responsibilty Principle)
Don't worry about memory here as it wont make iota of difference here.
So do you want to do something like:
for(Connection connection : userSocialConnections ){
sendMessageTo(connection);
}
If so, then the method sendMessageTo would need to accept a connection (friend or ignored, basically a user) and probably if the runtype connection is ignored (or has blocked the user) then the sendMessageTo will return without sending a message polymorphically. This would require that in java that the IgnoredPeople And Friends are subtypes of something called as Connection(or people or anything you like; in fact, a connection is also a user - current or potential, isn't it?). This approach seems (to me) more like thinking in problem domain. Storing as two list inside user or inside social inside user does not matter much as long as they both (ignored and friends) have a common interface.
I would ask, what all other scenarios can be there for user's friends or ignored list. Do they need to be loaded lazily or stored separately.
I'm making a 2D game in java using the MVC pattern and after reading and searching my ass off I still haven't found a satisfying answear to how I'm supposed to handle the graphical representation of objects.
Should I divide every object, for example Player into PlayerModel (stored in Model) and PlayerView (stored in View)?
That seems kinda messy becuase then I would have to keep track of which grapical-representation-object, i.e. "ScaryMonsterEnemyView" is connected to which logical-representation-object, "ScaryMonsterEnemyModel". Is this really how I'm supposed to do it according to MVC? If so, where should this connection be stored? In the view?
I know this might be a silly problem to get stuck on, but I want to get as much as possible right from the start. Thanks for helping out :)
If I am not mistaken, you are basically asking how to split up a game into the Model-View-Controller paradigm.
Simply put, the Model is the state of your game. In O-O terms, you can think of the Model as all of the objects in your game.
The Controller is the set of rules that are applied to your game's state (in this case, all of your game objects) in every update cycle. This can be implemented as a method called update() in all of your objects, or it can be a function called in your game loop that systematically goes through all the objects that need updated and, well, updates them. You can also think of the Controller as the game loop itself. It calls everything to update, and then draws it on the screen and repeats, unless some conditions are met, then it tells the program to do something else. In this way, you almost have two nested MVC structures. One controlling the flow of the program through menus and such, and one dedicated to the game itself.
The View is just the graphical representation of your game. This can be as simple as text on a screen, but in your case it is 2D graphics. To implement this, you could have each object also contain their graphical state, either directly, or by encapsulation. The View would do little more than query all of the objects for their graphical state, and then shunt it to the screen. Again, this can be implemented on a per-object basis, such as a method called draw(), or another systematic function to be called directly from the game loop. A common practice is to create an object called 'Sptite' or something similar to hold the graphical information, and have every game object that is drawn have a personal instance. Also note that the View need not be an object unto itself. A mere function called in a game loop will suffice, although it is sometimes necessary to store information that directly effects the View's operation (like window size), in which case the View can be an object. The same goes for the Controller.
Also keep in mind that these divisions can be sectioned up even further to make life simpler. For example: The Controller can be divided up into AI processing, movements updating, and collision checking. The View could be separated into the game object display and the HUD, and the Model can be all the objects + all the state independent of the game objects (like the games settings for resolution, window size, key config and such).
I know this might be a little overkill, and it probably has extra information, but hopefully it answers your question and gives you ideas on where to start.
The Model and View are two collections/categories/domains of objects.
The controller provides a set of interfaces to perform some functions on the model objects. And if required, the view can talk directly to model objects regarding their state information.
Traditionally, The View domain corresponds to GUIs, with concepts such as Buttons, Forms, Windows etc. In a desktop environment.
Your View domain (Or one of them) will correspond to a 3D environment that you will build. (Trees, Houses, Person etc). This includes collision details, and your physics. Both of which require the geometry relating to your 3D environment.
It may be very rare in a game for any of these objects to have to collaborate with an object in another domain. But an example, consider a telephone. The object will exist in your 3D environment, but will also collaborate with another domain which describes "half-calls", "channels", "switches" etc. These objects do not belong in your View domain but in a separate Model domain.
A more relevant example maybe some sort of scoring system, such as RPG stats, which would belong in a Model domain.
As a project over summer while I have some downtime from Uni I am going to build a monopoly game. This question is more about the general idea of the problem however, rather than the specific task I'm trying to carry out.
I decided to build this with a bottom up approach, creating just movement around a forty space board and then moving on to interaction with spaces. I realised that I was quite unsure of the best way of proceeding with this and I am torn between two design ideas:
Giving every space its own object, all sub-classes of a Space object so the interaction can be defined by the space object itself. I could do this by implementing different land() methods for each type of space.
Only giving the Properties and Utilities (as each property has unique features) objects and creating methods for dealing with the buying/renting etc in the main class of the program (or Board as I'm calling it). Spaces like go and super tax could be implemented by a small set of conditionals checking to see if player is on a special space.
Option 1 is obviously the OO (and I feel the correct) way of doing things but I'd like to only have to handle user interaction from the programs main class. In other words, I don't want the space objects to be interacting with the player.
Why? Errr. A lot of the coding I've done thus far has had this simplicity but I'm not sure if this is a pipe dream or not for larger projects. Should I really be handling user interaction in an entirely separate class?
As you can see I am quite confused about this situation. Is there some way round this? And, does anyone have any advice on practical OO design that could help in general?
EDIT: Just like to note that I feel I lost a little focus on this question. I am interested in the general methodology of combining OO and any external action(command line, networking, GUI, file management etc) really.
In the end, it is up to you. That is the beauty of OO, in that it is subject to interpretation. There are some patterns that should usually be adhered to, but in general it is your decision how to approach it.
However, you should carefully consider what each actor in the system should know about the rest of it. Should a property really know about the player, his account balance, and the other players? Probably not. A property should know what it costs, how much its rent is, etc.
On the other hand, should the main playing thread be concerned about trivial matters such as paying rent? Probably not. Its main concern should be the state of the game itself, such as dice rolling, whether each player wants to trade or buy or unmortgage/mortgage, things like that.
Think for a moment about the action of landing on a square. Once landed, the player has 3 options:
Buy the property
Ignore the property
Pay rent
Now, which actor in the system knows all the information required to complete that. We have the Game class, which isn't concerned with such tedium. We have the Property, which doesn't really care about the players. But the Player object knows all this information. It keeps a record of what each player owns, and can easily access the proper data.
So, if it were me, I would make a Player.performMove(Die d) method. It has easy access to the accounts. This also allows for the least coupling among classes.
But in the end, it's up to you. I'm sure people have created Monopoly clones in perfect OO, as well as Functional or Procedural languages too. In the end, use what you know and keep refactoring until you're happy with the end design.
I agree option #1 seems better.
As for "user interaction" - it all depends. You could leave some of your code in another class. For example,
// in main class
user.landOn(space);
if (space.containsProperties()) doSomething(); // Option #1 for some user-interaction code
// in User.java
public void landOn(Space s) {
// do some checks
s.land(this);
if (s.containsProperties()) {...} // Option #2
// something else?
}
// in GetMoneySpace.java
#Override
public void land(User u) {
u.awardCash(200);
// Option #3 - no properties so nothing here
}
This is far more OOP-y (and better, in my opinion) than something like
if (space.isCashAwardSpace()) {
user.awardCash(space.getAward());
}
if (user.something()) doSomething(); // Some user-interaction code
I am not entirely sure if I understand it correctly. You have always such choice when designing software. I would personally go for the first choice. One argument is personal experience with small games (Scrabble), which prooved to me that good design matters for smaller projects as well. The point of OOP is that you can think differently about your design and you get some design benefits. For example imagine how hard it will be to add new field, change existing one, reuse behaviour of one field in multiple fields.
Your first approach is the one I'd go for. It encapsulates the behaviour where it's needed. So, you'd have Space subclasses for Utilities, Properties, GotoJail, FreeParking - basically all the different cateogires of spaces. What groups a category is it's common behaviour.
Your properties spaces may themselves have a group object as a member, e.g. to group all the dark blue properties together.
As to interaction with the user, you pass a Board (or better a GameController) instance to each space, so it knows which Game it is part of and can influence the game. The Space can then invoke specific actions on the board, such as, moving a piece, asking the user a question etc. The main point is that there is separation - the user interaction is not happening inside each Space - but the space is allowed to request that some interaction happens, or that a piece is moved. It's up to your GameController to actually do the interaction or move pieces etc. This separation makes it easy to test, and also provide alternative implementations as the need may arise (E.g. different game rules in different editions/countries?)
Go with the first design. You'd have a Property class, and subclass the special properties, overriding the default behavior.
As far as interaction, you could have a Token class, and move an instance of that around the board. You have to give the user some options, but yes, from the responses, you should be calling methods on objects, not putting complex logic in the user events.
Sample classes:
Property
name
price
baseRent
houseCount
hotelCount
mortgaged
getCurrentRent()
RailRoad extends Property
Utility extends Property
Board
properties
User
token
playerName
currentProperty
ownedProperties
buyProperty()
payRentOnProperty()
mortgageProperty()
move()
Option 2 doesn't make much sense, or at least it's not as clear to me as option 1. With option 1 you don't need to handle user interaction inside your space object. You could have in your main class or a separate class dedicated to handle user interaction:
public void move(Player p, int spaces){
Space landingSpace = board.getLandingSpace(p,spaces);
landingSpace.land(p); //apply your logic here
}
As you can see, the Space class is responsible for checking the Player p that intends to land on that space. It applies any custom logic, checks if it has enough money, if it's something that the player owns, etc. Each subclass of Space will have its own set of rules, as you described in option 1.
Part of the point of object-oriented design is to simplify the representation of the problem within the solution space (i.e., modeling the system in the computer). In this case, consider the relationships between objects. Is there enough functionality in a Space to warrant abstracting that into a class, or does it make more sense for there to be discrete Property and Utility classes unrelated to Space because of the unique features of both? Is a Property a special kind of Space, or merely a field within Space? These are the kinds of problems you probably will need to grapple with in designing the game.
As far as interaction, it's generally bad news for a design when you have a 'god class' that does all the work and merely asks the other classes for information. There are plenty of ways to fall into this trap; one way to determine whether you are dealing with a god class is to look for a class name including Manager or System. Thus, it's probably not the best idea to have some sort of "game manager" that asks all the other objects for data, makes all the changes, and keeps track of everything. Eliminate these as much as possible.
God classes violate the concept of encapsulation, which involves more than data hiding (though that's certainly a big part of it). Good encapsulation means that related methods and data are part of a single object. For example, a Property doesn't need to make requests of its owner, so a field containing a reference to the Player could violate encapsulation. Some of these encapsulation violations aren't obvious at all, and can be hard to spot. When designing the object, try to determine the smallest amount of information about the object that needs to be shared with external objects. Trim out anything unnecessary.
You can obviously go about this in a lot of ways, but my design would be something like this (iteration could certainly prove it wrong):
Space class that contains basic data and methods that are common to all spaces (such as their position on the board, occupied or not, etc.).
Subclasses moving from most common (Property and Utility) to most unique (Go, Jail, FreeParking, and so on; probably singletons) with fields and methods related to each.
Player class to contain player information.
GameState class that is concerned with game state; whose turn it is, how many houses are left in the bank, and so on.
Good luck with the game and your continued studies.
Naturally, Google is your friend, but here's a sampling of things I would recommend reading:
ATM simulation (this idea is
also discussed in Rebecca
Wirfs-Brock's book below)
Object-Oriented Design Heuristics - Arthur Riel
How Designs Differ (PDF), Designing Object-Oriented Software - Rebecca Wirfs-Brock
Whenever I try to write graphical programs (whether a game or really any GUI app) I always wind up with one or two god classes with way too many methods (and long methods, too), and each class having far too many responsibilities. I have graphics being done at the same time as calculations and logic, and I feel like this is a really bad way to go about organizing my code. I want to get better at organizing my code and abstracting out responsibilities to different classes. Here's an example of where I'd like to start - I want to write a Minesweeper clone, just sort of as practice and to try to improve my software engineering skills. How would I go about making this nice and object-oriented? For the sake of discussion, let's just say I'm using Java (because I probably will, either that or C#). Here's some things I would think about:
should each tile inherit from JButton or JComponent and handle drawing itself?
or should the tiles just be stored as some non-graphical MinesweeperTile object and some other class handles drawing them?
is the 8-segment display countdown timer (pre-Vista, at least) a separate class that handles drawing itself?
when the user clicks, do the tiles have mouse event listeners or does some other collision detection method loop through the tiles and check each one to see if it's been hit?
I realize that there's not just one way to write a GUI application, but what are some pretty basic things I can start doing to make my code more organized, manageable, object-oriented, and just over all write better programs?
edit: I guess I should add that I'm familiar with MVC, and I was originally going to incorporate that into my question, but I guess I didn't want to shoehorn myself into MVC if that's not necessarily what I need. I did searched for topics on MVC with GUI apps but didn't really find anything that answers my specific question.
edit2: Thanks to everyone who answered. I wish I could accept more than one answer..
Here is a simple (but effective) OO design to get you started:
First create a Game object that is pure Java/C# code. With no UI or anything else platform specific. The Game object handles a Board object and a Player object. The Board object manages a number of Tile objects (where the mines are). The Player object keeps track of "Number of turns", "Score" etc. You will also need a Timer object to keep track of the game time.
Then create a separate UI object that doesn't know anything about the Game object. It is completely stand alone and completely platform dependent. It has its own UIBoard, UITile, UITimer etc. and can be told how to change its states. The UI object is responsible for the User Interface (output to the screen/sound and input from the user).
And finally, add the top level Application object that reads input from the UI object, tells the Game what to do based on the input, is notified by the Game about state changes and then turns around and tells the UI how to update itself.
This is (by the way) an adaption of the MVP (Model, View, Presenter) pattern. And (oh by the way) the MVP pattern is really just a specialization of the Mediator pattern. And (another oh by the way) the MVP pattern is basically the MVC (Model, View, Control) pattern where the View does NOT have access to the model. Which is a big improvement IMHO.
Have fun!
use a MVC framework that handles all the hard organization work for you. there's a ton of MVC framework topics on SO.
using high quality stuff written by others will probably teach you faster - you will get further and see more patterns with less headache.
I'm not suggesting this is the only way to do it, but what I would suggest is something like the following. Other people, please feel free to comment on this and make corrections.
Each tile should inherit from something and handle drawing itself. A button seems like the best solution because it already has the button drawing functionality (pressed, unpressed, etc) built in.
Each tile should also be aware of its neighbors. You would have eight pointers to each of its eight neighbors, setting them to null of course if there is no neighbor. When it goes to draw, it would query each neighbor's IsMine() function and display the count.
If none of its neighbors are a mine, it would then recurse into each neighbor's Reveal() method.
For the 7-segment display, each digit is its own class that handles drawing. Then I would make a CountdownSegmentDigit class that inherits from this class, but has additional functionality, namely CountDown(), Set(), and Reset() methods, as well as a HitZero event. Then the display timer itself is a collection of these digits, wired up to propagate zeroes left. Then have a Timer within the timer class which ticks every second and counts down the rightmost digit.
When the user clicks, see above. The tile itself will handle the mouse click (it is a button after all) and call its Reveal() method. If it is a mine, it will fire the MineExploded event, which your main form will be listening to.
For me, when I think of how to encapsulate objects, it helps to imagine it as a manufacturing process for physical parts. Ask yourself, "How can I design this system so it can be most efficiently built and reused?" Think about future reuse possibilities too. Remember the assembly process takes small pieces and builds them up into larger and larger pieces until the entire object is built. Each bit should be as independent as possible and handle its own logic, but be able to talk to the outside world when necessary.
Take the 7-segment display bit, you could have another use for it later that does not count down. Say you want a speedometer in a car or something. You will already have the digits that you can wire up together. (Think hardware: stock 7-segment displays that do nothing but light up. Then you attach a controller to them and they get functionality.)
In fact if you think hard enough, you might find you want CountUp() functionality too. And an event argument in HitZero to tell whether it was by counting up or down. But you can wait until later to add this functionality when you need it. This is where inheritance shines: inherit for your CountDownDigit and make a CountUpOrDownDigit.
Thinking about how I might design it in hardware, you might want to design each digit so it knows about its neighbors and count them up or down when appropriate. Have them remember a max value (remember, 60 seconds to a minute, not 100) so when they roll over 0, they reset appropriately. There's a world of possibilites.
The central concern of a Graphic User Interface is handling events. The user does X and you need to response or not respond to it. The games have the added complexity in that it needs to change state in real time. In a lot of cases it does this by transforming the current state into a new state and telling the UI to display the results. It does this in a very short amount of time.
You start off with a model. A collection of classes that represents the data the user wants to manipulate. This could represent the accounts of a business or vast frontiers of an unknown world.
The UI starts with defining a series of forms or screens. The idea is that is for each form or screen you create a interface that defines how the UI Controller will interact with it. In general there is one UI Controller classes for each form or screen.
The form passes the event to the UI Controller. The UI Controller then decides which command to execute. This is best done through the Command design pattern where each command is it own class.
The Command then is executed and manipulate the model. The Command then tells the UI Controller that a screen or a portion of a screen needs to be redraw. The UI Control then looks at the data in the model and uses the Screen Interface to redraw the screen.
By putting all the forms and screen behind a interface you can rip out what you have and put something different in. This includes even not having any forms at all but rather mock objects. This is good for automated testing. As long as something implements the Screen Interface properly the rest of the software will be happy.
Finally a game that has to operate in real time will have a loop (or loops) running that will be continually transforming the state of the game. It will use the UI Controller to redraw what it updated. Commands will insert or change information in the model. The next time the loop comes around the new information will be used. For example altering a vector of a object traveling through the air.
I don't like the MVC architecture as I feel it doesn't handle the issues of GUIs well. I prefer the use of a Supervising Controller which you can read about here. The reason for this is that I believe automated tests are one of the most important tools you have. The more you can automate the better off you are. The supervising presenter pattern makes the forms a thin shell so there is very little that can't be tested automatically.
Sorry to say it, but it seems you have mess in your head trying to improve your coding too much in one step.
There is no way to answer your question as such, but here we go.
First start with OOP, think about what objects are required for your game/GUI and start implementing them a little at a time, see if there are chances to break up these objects further, or perhaps reunite some objects that make no sense on their own, then try to figure out if you have repeated functionality among your objects, if you do, figure out if this repeated functionality is a (or many) base class or not.
Now this will take you a few days, or weeks to really grok it well, then worry about dividing your logic and rendering.
I have some tutorials that are written in C#. It discusses this very same topic. It is a starting point for a RogueLike game.
Object Oriented Design in C# Converting Legacy Game
Object Oriented Design: Domain Type Objects
Object Oriented Design: Rethinking Design Issues
BROKEN LINK - Object Oriented Design: Baby Steps in Acceptance Testing