I am creating the board game Tic Tac Toe in Java.
A cell will have three states: empty, X or O.
What is the best practice for representing this in Java? Should I create its own Cell class or just use integers (0/1/2) to represent the three states? If it had two states then I could use for example boolean to represent the two states, is there a similar already defined class for something with three states?
I would use an enum for this:
enum CellState {
EMPTY,
X,
O
}
And then in your code:
public static void main(String[] args) {
CellState[][] cellStates = new CellState[3][3];
cellStates[0][0] = CellState.X;
// Do other stuff
}
I just defined the board structure as CellState[][] as example but this can be whatever.
About the most important thing when using an OO language is that objects model behaviour and, where possible, contain the data required to implement the behaviour. Behaviour is what the objects do, not what is done to them.
So unless there is a reason to in a requirement you haven't stated, the cell itself doesn't have any behaviour, it is just a place that the players mark.
So you could have a simple array of marks that both players update, with an enum with three values, or you could have each player update their own data of the marks they have made, in which case each player would have either a boolean array or a short bit mask to indicate their goes. In the latter case, each player then only changes the state of their own 'goes' and can implement the test for their winning condition rather than having shared state - the only sharing is they have to ask the other player whether the chosen cell is valid. It depends how strictly OO you want your design to be as to whether this is 'best practice' or not - for such a simple problem you could write in COBOL and the users would be as happy.
I would use an enum :
public enum CellState {
EMPTY,
X,
O;
}
And a Cell class that has a field of type CellState
You could use an enum which contains the three values, like:
public enum CellState {
EMPTY,
X,
O
}
And use it like in a way like this:
board.setCell(cellposition, CellState.X);
There are multiple approaches but in this case I prefer using an enum to represent your state.
public enum State {
EMPTY,
X,
O
}
And then your cell class would look something like this.
public class Cell {
private State state;
public Cell(State state) {
this.state = state;
}
public State getState {
return state;
}
public void setState(State state) {
this.state = state;
}
}
The other way is just to use Boolean object and to use null as third state.
Boolean state = null; // => empty state
state = Boolean.TRUE // => X state
state = Boolean.FALSE // => O state
Related
Say I have a char array, I wanna classify its element into three states. If it's a number, then mark it as State 1, if it's a operator, then mark it as State 2, if else, mark it State 3.
First, I initialize a boolean array to represent its state, but I fount it only can store two states:(
Then I switch to int array, yet this way is kinda a waste of space.
Could you offer better idea please?
if you need to represent something like the state of a finite state machine, or Values of an hypothetical class Card, you should use enum, something like
public class EnumTest {
public enum State{
START_STATE("1"),INTER_STATE("2"),END_STATE("3");
String name;
State(String name){this.name = name;}
String getName() {return name;}
}
public static void main(String[] args) {
for(State state : EnumTest.State.values())
System.out.println(state.getName());
}
}
PS: Constructor and fields are actually optional if space matters: your enum can also be
public enum{FIRST,SECOND,THIRD;}
According to this SO page: https://stackoverflow.com/questions/952169/what-is-the-third-boolean-state-in-java, you could also use a wrapped Boolean defaulting to null, which could potentially be used as a third type if you do not reassign the boolean to any other value.
Suppose I'm making a game:
public class Game {
Board board;
public ArrayDeque<Player> players;
//Players can have 'knights' and the one with the largest number
//is referenced by the game.
public Player playerWithLargestArmy;
...
}
At the beginning, when a game like this is initialised, no player can have the largest army (a player only has an 'army' once they have a certain number of knights). I want to assign the playerWithLargestArmy a value, but I'm not sure what. I also don't want to use null since I could just leave the implicit assignment to do that (and using null is bad practice anyway).
I am looking for someone to explain to me how I can resolve this issue. I looked up factories and builders but I'm not sure they handle this kind of delayed assignment. For context, each player has an int field specifying how many knights they have.
I could resolve this with a boolean for each player saying whether or not they have the largest army, but then you'd need to iterate through the players to find that player, which isn't ideal. Even if, in my case, that isn't a huge sacrifice, I'd still like to know for future reference.
There is java.util.Optional<T> class for such case.
It have isPresent() and get() (and several other) methods which give you ability to check that object is present and get instance of underlying object.
Examples
Declaration
Optional<Player> playerWithLargestArmy = Optional.empty();
Assignment of value
playerWithLargestArmy = Optional.of(newValue);
Usage of value
if(playerWithLargestArmy.isPresent()) {
Player p = playerWithLargestArmy.get();
}
or even better
playerWithLargestArmy.map(p -> doSomethingWithIt(p));
which will invoke doSomethingWithIt only if value is present.
Null Object Pattern
https://en.wikipedia.org/wiki/Null_Object_pattern
public class Army {
public static final Army NullArmy = new Army(0);
private int size;
public Army(int size) {
this.size = size;
}
}
Now when you create a new Army, just set the initial value to Army.NullArmy.
As you can see, I've created (instantiated?) a static array of Corner objects in the object Corner. Is this good form? I want all the Corner object to have access to all the other Corner objects.
package Main;
public class Corner {
private String biome;
private static Corner[][] corners;
private float elevation, moisture, heat;
private boolean isRiver, isLake;
private int x, y;
public void createArray(int width, int height) {
corners = new Corner[width][height];
}
public String getBiome() { return biome; }
public void setBiome(String biome) {
this.biome = biome;
}
public float getElevation() { return elevation; }
public void setElevation(float elevation) {
this.elevation = elevation;
}
public float getMoisture() {
return moisture;
}
public void setMoisture(float moisture) {
this.moisture = moisture;
}
public float getHeat() { return heat; }
public void setHeat(float heat) { this.heat = heat; }
public boolean isRiver() {
return false;
}
public boolean isLake() {
return false;
}
public static Corner[][] getCorners() {
return corners;
}
}
There are no more details to add.
If the amount of Corners changes you need to create a new bigger array and copy all the Corners from the old array to the new bigger one. This should indicate to you that you might want to ave a different data structure than an array. One that can grow like a List or a Set.
In general, a Corner should not need to know of other Corners. A different type should manage all the Corners and handle dependencies between them.
You did not wrote why 'I want all the Corner object to have access to all the other Corner objects' so I cannot recommend how this managing type could look like.
First of all, taking in not what Kevin has said, you should change
public void createArray(int, int);
to
public static void createArray(int, int);
I do not understand the need to have a two-dimensional array for accessing other Corner objects.
Also array is not a good structure type for dynamic allocation. List is better alternative and in this case List. So you should implement it as -
You should create a list as -
private static List<Corner>;
In general, static is an abnormality in good OO design. You only use it if there are very good reasons to do so.
Your example doesn't look like such a case. You see, you are mixing up things that don't belong together. A "corner" is simply that a "corner". It doesn't know about other "corners".
In the model that you are actually creating, you have some "enclosing" thing that deals with corners in plural. That enclosing thing could have some List<Corner> field that is used to track all Corner objects belonging to the enclosing entity.
static often looks like an easy, convenient way to solve such problems. But in reality, you are just creating a lot of problems by implementing something like this. It works initially, but it breaks as soon you try to enhance your program.
Is this good form?
No.
There are two reasons:-
Reason 1 :- Single responsibility principle. Every object should be responsible about its concern . So its not the concern of corner object to maintain the list of other corner object. Maintaining corner object can go under some util class method or singleton object maintaining the corner cache(which will be easy to test also)
Reason 2 :-
unit testing. Say you want to write unit test for static method you won't be able to do it easily until and unless you provide any third party lib that provides static mocking like jmockit,
Got a design patterns question (some terminology related to Java as that's my current project).
Current layout of code:
class Game - holds game state and manages logic,
Super abstract class Player
Player has subclasses for different types of players (AI, human, etc).
Each player can make up to three moves (A, B, C) but they must be in that order. Hence a player may on their turn choose any of the following move sequences:
(A,B),
(B,C),
(A, B, C)
(A, C),
(a),
etc
Players should receive feedback between each move so that they may decide whether to execute another or end their turn.
Assuming set of type abstract Player here are two designs I have:
Solution 1:
for all players in set call player.takeTurn(game). So every player knows when it is their turn and they have a reference to the current Game object. Their turn ends when takeTurn() returns. Player.takeTurn is overridden by all subclasses of player. Within the method, any player who wishes to carry out moves can reference the passed in Game object. example:
game.makeMoveA(),
game.makeMoveB(),
etc
Game.makeMove() can return ok/error values to tell the player whether the move was legal or not. Also, the updated game state is available by the Game object that is still in scope within the takeTurn() method.
Problem is that you are relying on all subclasses to remember to call makeMove() What if they don't or what if they call them in the wrong order? I guess that calling methods in the wrong order could be handled by exceptions/error messages but we still have the problem that nothing enforces the instantiated class to actually respond and make a move.
Solution 2:
Abstract class Player contains three abstract methods getMoveA getMoveB and getMoveC.
Hence all inheritors must implement these methods.
The abstract super class Player contains a method takeTurn().
takeTurn(Game game) {
game.makeMove(this.getMoveA())
game.makeMove(this.getMoveB());
etc
}
This is nice as behaviour is enforced but now we have a messy problem of how to give feedback to the player who made the move. What if it was an illegal move, etc. You could enforce another method handleMoveResponse() but then every player has to keep track of what move the success/error message refers to.
Any ideas? Would love to hear your opinion on this.
Many thanks
It looks to me like you are trying to get your requirements to fit a pattern rather than breaking down the requirements until you see the pattern.
A brief attempt at implementing your requirements produced this. There's a Strategy pattern and a Template pattern in there that doesn't seem to have the issues you mention.
enum Move {
A, B, C;
}
class Strategy {
final List<Move> moves;
public Strategy(List<Move> moves) {
// TODO: Make sure it is valid.
this.moves = moves;
}
}
class Game {
}
abstract class Player {
// Call before each move.
abstract Strategy getStrategy(Game game);
void move(Game game, Move move) {
// By default do nothing.
}
}
/**
* The rules control the game.
*/
class Rules {
public void play(Game game, Player player) {
while (!gameOver(game)) {
Strategy strategy = player.getStrategy(game);
for (Move move : strategy.moves) {
player.move(game, move);
// Do your feedback here.
}
}
}
private boolean gameOver(Game game) {
return false;
}
}
I'm encountering a couple awkward situations that seem, in some sense, dual to each other, and was wondering if anyone had any thoughts about how to handle them cleanly.
External initialization
class Human {
Collection <Human> nextDoorNeighbors;
}
class Neighborhood {
Collection <Human> humans;
Neighborhood() {
// Make humans
// Then, let them all know who their neighbors are.
}
}
This is awkward because the humans (in this situation) never have to change their next-door neighbors once they've been set up (they are effectively write-once), but this setup can't be done in the Human constructor because the neighbors that need to be put in the nextDoorNeighbors collection don't all exist when the human is constructed.
Holding something for another
Suppose I want to be able to store Humans in a tree-based map. To do so, the Human has to hold a Comparable ID, even if that isn't logically significant to the concept of a Human. The Human constructs this ID, but it never uses it. Only the map uses it (or even should use it).
In the first case, maybe the awkwardness is an indication that neighbours shouldn't be a property of Human. Perhaps the Neighbourhood object should be a property of Human, and a method like human.getNeighbours() can be used to get the actual neighbours when they are needed. Then having a neighbours property becomes a private performance issue for the getNeighbours() method.
In the second case, how is your tree-based map providing a structure if the Human is inherently unstructurable? What's the map for if the ID is irrelevant to the human? Typically an ID is relevant, and is used by the class that has it to ensure that it's uniquely identifiable, but if it's genuinely not required, you can use a separate class, like a HumanKey, to wrap the Human for the map.
I don't really understant what your question is.. Because it's not explicit..
But for the id you can have a static variable in the human class that you will increment in the human constructor and another variable wich will contain the id
It would be something like this
class Human
{
private static int humansCounter=0;
final public int id;
public Human()
{
id=humansCounter++;
}
}
I have an approach that I think is rather clean if the objects themselves need to be aware of the networking. Note that this approach will not work if you concurrently instantiate instances (since each thread will have its own copy of the static fields).
class Foo {
// instance fields
public Foo(/* constructor args */) {
// set instance up
network(this);
}
public boolean isNeighbor(Foo that) {
return areNeighbors(this, that);
}
// static field for tracking edges between neighbors, maybe a
private static Map<Foo, List<Foo>> neighborhood = new HashMap<>();
private static void network(Foo me) {
myNeighbors = new ArrayList<>();
for (Map.Entry<Foo, List<Foo>> x : neighborhood.entrySet()) {
Foo n = x.getKey();
if (/* use me and n's fields to determine whether they are neighbors */) {
myNeighbors.add(n);
x.getValue().add(me);
}
}
neighborhood.put(me, myNeighbors);
}
public static boolean areNeighbors(Foo a, Foo b) {
return neighborhood.get(a).contains(b);
}
}
This approach makes it so that each instance can determine their neighbors without actually knowing their neighbors ahead of time and without using an external class. If an instance's neighbors cannot be inferred from internal state, this approach could be combined with the approach of generating unique IDs (hashes?) for each instance:
class Bar {
// instance fields
public Bar(/* constructor args */, int... neighborIndices) {
// set instance up
network(this, neighborIndices);
}
#Override
public int hashCode() {
return /* a unique value based upon this object's state */;
}
public boolean isNeighbor(Bar that) {
return areNeighbors(this, that);
}
private static Map<Integer, Bar> lookup = new HashMap<>();
private static Map<Bar, List<Integer>> neighbors = new HashMap<>();
private static void network(Bar me, int[] neighbors) {
lookup.put(me.hashCode(), me);
List<Integer> neighborList = new ArrayList<>();
for (int i : neighbors) {
neighborList.add(i);
}
neighbors.put(me, neighborList);
}
public static boolean areNeighbors(Bar a, Bar b) {
return neighbors.get(a).contains(b.hashCode());
}
}
Naturally, if the neighbor relationships are not associative, it is trivial to modify the first example to be a digraph.