How to use enums to assign a flag to an object - java

I am creating a boardgame in java, and I'm trying to write a method that flags a chosen object (object represents a Tile on the board) by the user during the game. The method is within a class that sets a single Tile's value and position on the board.
I think using enum types would be a good idea but I am not sure exactly how to implement this. Within my class I have methods that get a Tile's position(row, column) on the grid, and the letter of which it represents.
public class Tile {
private final String letter; //holds the letter value of the tile
private final int row; //holds tile row index
private final int column;
public Tile(String l, int r, int c) {
this.letter = l;
this.row = r;
this.column = c;
}
//setter&getter methods
public String toString() {
return this.getLetter()+" "+ this.getRow() +
"," + this.getColumn();
}
So within this class as well, I want to write a method that flags whether or not a tile object is chosen... I was thinking that if the toString method returns a statement, then that can be used to show that the tile has been chosen. Or... how should I go about this. This is what I have so far:
public enum Status {CHOSEN, NOTCHOSEN};
public static void tileStatus(Status stat){
switch(stat) {
case CHOSEN: //something
break;
case NOTCHOSEN: //something
break;
}
}

you can declare that enum is instance member of Tile class
public class Tile {
private final String letter; //holds the letter value of the tile
private final int row; //holds tile row index
private final int column;
private Status flag; // use getter and setter to set flag on using Status enum
public Tile(String l, int r, int c) {
this.letter = l;
this.row = r;
this.column = c;
}
//setter&getter methods
public String toString() {
return this.getLetter()+" "+ this.getRow() +
"," + this.getColumn();
}

Adding a boolean to the Tile may help you with the state. Since there are only two possible states (chosen, not chosen), a boolean may make more sense. Also don't add getters and setters by default. Only when you need them. Refer to "tell don't ask principle"
public class Tile {
private final String letter; //holds the letter value of the tile
private final int row; //holds tile row index
private final int column;
private boolean isTileFlagged;
public Tile(String l, int r, int c) {
this.letter = l;
this.row = r;
this.column = c;
isTileFlagged = false; // May be false to being with
}
// add getters/setters only when necessary
public void toggleFlaggedState(){
isTileFlagged = !isTileFlagged;
}
public String toString() {
return this.getLetter()+" "+ this.getRow() +
"," + this.getColumn();
}
// add hashcode, equals if necessary
Also, if the enum is necessary, it could be an inner state of Tile class, as its independent existence may not make sense.

Make enum as member variable of class and method to the enum.
like this as bellow:-
package com.robo.lab;
public class Tile {
private final String letter; // holds the letter value of the tile
private final int row; // holds tile row index
private final int column;
private Status status;
public Tile(String l, int r, int c,Status status) {
this.letter = l;
this.row = r;
this.column = c;
this.status=status;
}
// setter&getter methods
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public String toString() {
return this.getLetter() + " " + this.getRow() + "," + this.getColumn()+","+this.getStatus();
}
public String getLetter() {
return letter;
}
public int getRow() {
return row;
}
public int getColumn() {
return column;
}
}
package com.robo.lab;
public enum Status {
CHOSEN, NOTCHOSEN;
public static void tileStatus(Status stat) {
switch (stat) {
case CHOSEN: // something
break;
case NOTCHOSEN: // something
break;
}
}
}
package com.robo.lab;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Tile obj1= new Tile("AUser", 1, 1,Status.CHOSEN);
System.out.println(obj1.toString());
Tile obj2= new Tile("BUser", 1, 1,Status.NOTCHOSEN);
System.out.println(obj2.toString());
}
}

Related

List<List<Box>> is not Serialized

I have a class Player that has three variables, one of these is a List<List<Box>> and of course class Box does implement Serializable.
Box has some variables too, all of them are primitive types except for a class Dice which does implement Serializable too.
I have to send this class through the network with a socket and when I send this to the Client side the List<List<Box>> looks ok, and each Box too, the problem is that the Dice class that should be in the Box is always set to null even if the one I sent to the Client from the Server is not and I am absolutely sure that the network part is correct.
Forgot to mention that List<List<Box>> when instantiated becomes an ArrayList<ArrayList<Box>> which should be Serializable.
Dice class:
package ingsw.model;
import java.io.Serializable;
import java.util.Random;
public class Dice implements Serializable {
private int faceUpValue;
private final Color diceColor;
public Dice(Color diceColor) {
this.diceColor = diceColor;
}
public Dice(int faceUpValue, Color diceColor) {
this.faceUpValue = faceUpValue;
this.diceColor = diceColor;
}
/**
* Draft the dice
* get a random number between 1 and 6 and set the faceUpValue
*/
void roll() {
int value = (new Random()).nextInt(6) + 1;
setFaceUpValue(value);
}
public int getFaceUpValue() {
return faceUpValue;
}
public void setFaceUpValue(int faceUpValue) {
this.faceUpValue = faceUpValue;
}
public Color getDiceColor() {
return diceColor;
}
#Override
public String toString() {
if (faceUpValue != 0) {
return diceColor.toString() + String.valueOf(faceUpValue);
} else {
return diceColor.toString();
}
}
}
Card class implements Serializable:
public abstract class PatternCard extends Card {
private int difficulty;
protected List<List<Box>> grid;
public PatternCard(String name, int difficulty) {
super(name);
fillGrid();
this.difficulty = difficulty;
}
#Override
public String toString() {
return "PatternCard{" +
"'" + getName() + "'" +
'}';
}
public int getDifficulty() {
return difficulty;
}
public void setGrid(List<List<Box>> grid) {
this.grid = grid;
}
public List<List<Box>> getGrid() {
return grid;
}
private void fillGrid() {
this.grid = new ArrayList<>(4);
this.grid.add(new ArrayList<>(5));
this.grid.add(new ArrayList<>(5));
this.grid.add(new ArrayList<>(5));
this.grid.add(new ArrayList<>(5));
}
}
Box class:
public class Box implements Serializable {
private Color color;
private Integer value;
private Dice dice;
public Box(Color color) {
this.color = color;
}
public Box(Integer value) {
this.value = value;
}
public Color getColor() {
return color;
}
public Integer getValue() {
return value;
}
public boolean isValueSet() {
return value != null;
}
public void insertDice(Dice dice) {
this.dice = dice;
//TODO the dice at this point must removed from the dice drafted --> dices (set).remove();
}
public void removeDice() {
if (dice != null) dice = null;
//TODO dice must be re-added?
}
public Dice getDice() {
return dice;
}
#Override
public String toString() {
if (isValueSet()) return String.valueOf(value);
else return color.toString();
}
Boolean isDiceSet(){ return dice != null; }
}
I've investigated a bit and thought that I should probably Serialize the object and De-serialize it by myself but I don't know if that could be the real issue here since ArrayLists are Serializable and every object inluded in these ArrayLists are too.
What could possibly be wrong in this?

Subclass final method not being called

I don't get what's going on here, but the final method
s.castable()
that overrides the motherclass's namesake abstract method doesn't get called.
Here is where I try to call s.castable():
public void cast(String[] request) {
System.out.println("cast called");
if (this.session.getPlayer()==this.game.getTurnPlayer()) {
System.out.println("first condition passed");
Spell s = this.session.getPlayer().getCharacter().getSpells().get(Integer.valueOf(request[1]));
ArrayList<String> usernames = new ArrayList();
System.out.println("Now printing spell: "+s);
for (int i = 6; i < request.length; i++) {
usernames.add(request[i]);
}
System.out.println("username create.d");
if (s.castable()) { //HERE
System.out.println("Second condition passed");
s.cast(Integer.valueOf(request[1]), Integer.valueOf(request[2]),request[3].charAt(0), request[4].charAt(0), usernames);
String str = "";
for (String st : usernames) {
str += st;
}
this.session.send("YOUSPELL "+request[1]+" "+request[2]+" "+request[3]+" "+request[4]+" "+str);
System.out.println("Done");
}
}
}
Here is the "Spell" MotherClass:
public abstract class Spell {
private int manaCost;
private int coolDown;
private int range;
private Player player;
public abstract void cast(int x, int y, char mode1, char mode2,ArrayList<String> usernames);
public abstract Boolean castable();
//Then all getters and setters.
}
And here is the final class "Velocity":
public final class Velocity extends Spell {
private final int manaCost;
private final Player player;
private final int coolDown;
private final int coolDownTime;
private final int additionalMovement;
private final int spellRef;
private final ArrayList<String> usernames = new ArrayList();
public Velocity(Player p) {
this.spellRef = 0;
this.additionalMovement = 5;
this.player = p;
this.manaCost = 5;
this.coolDownTime = 3;
this.coolDown = 0;
super.setCoolDown(coolDown);
super.setManaCost(manaCost);
super.setPlayer(p);
}
#Override
public final void cast(int x, int y, char mode1, char mode2,ArrayList<String> usernames) {
System.out.println("Velocity casted.");
player.setMovement(player.getMovement() + additionalMovement);
setCoolDown(coolDownTime);
}
#Override
public final Boolean castable() {
System.out.println(player.getMana());
System.out.println(manaCost);
System.out.println(getCoolDown());
if (player.getMana() >= manaCost && getCoolDown() >= 0) {
return true;
}
return false;
}
}
Finally, the console output:
cast called
first condition passed
Now printing spell: model.haraka.be.Velocity#739bb60f
username create.d.
As you can see the spell object is known.
Can you help me ?
Thank you
The only possible problem here can be that Abstract class Spell's variable s doesn't contain the reference to Velocity object.
hence the castable method of velocity class never gets called.
If the castable method is returning false as mentioned by many
people System.out.println() statements must be printed which is not
the case I think.
But to be sure this is the problem, Please explain:
Spell s = this.session.getPlayer().getCharacter().getSpells().get(Integer.valueOf(request[1]));
What are below methods return type ?
getPlayer()
getSpells()
get(Integer.valueOf(request[1])
This is too much to ask/comment in comment section hence posting as an answer.

Java Custom Event Handling

Good Day,
I am writing a custom event handler in Java. I have a class called BoogieCarMain.java that instantiates three instances of a type called BoogieCar. Whenever any of the three instances exceeds a certain speed limit, then an event should be fired off. The code I currently have is working, so here is what I have:
// BoogieCar.java
import java.util.ArrayList;
public class BoogieCar {
private boolean isSpeeding = false;
private int maxSpeed;
private int currentSpeed;
private String color;
BoogieSpeedListener defaultListener;
public BoogieCar(int max, int cur, String color) {
this.maxSpeed = max;
this.currentSpeed = cur;
this.color = color;
}
public synchronized void addSpeedListener(BoogieSpeedListener listener) {
defaultListener = listener;
}
public void speedUp(int increment) {
currentSpeed += increment;
if (currentSpeed > maxSpeed) {
processSpeedEvent(new BoogieSpeedEvent(maxSpeed, currentSpeed, color));
isSpeeding = true;
} else {
isSpeeding = false;
}
}
public boolean getSpeedingStatus() {
return isSpeeding;
}
private void processSpeedEvent(BoogieSpeedEvent speedEvent) {
defaultListener.speedExceeded(speedEvent);
}
}
// BoogieCarMain.java
import java.util.ArrayList;
public class BoogieCarMain {
public static void main(String[] args) {
BoogieCar myCar = new BoogieCar(60, 50, "green");
BoogieCar myCar2 = new BoogieCar(75, 60, "blue");
BoogieCar myCar3 = new BoogieCar(65, 25, "pink");
BoogieSpeedListener listener = new MySpeedListener();
myCar.addSpeedListener(listener);
myCar2.addSpeedListener(listener);
myCar3.addSpeedListener(listener);
myCar.speedUp(50); // fires SpeedEvent
System.out.println(myCar.getSpeedingStatus());
myCar2.speedUp(20);
System.out.println(myCar2.getSpeedingStatus());
myCar3.speedUp(39);
System.out.println(myCar3.getSpeedingStatus());
}
}
// BoogieSpeedListener.java
public interface BoogieSpeedListener { // extends java.util.EventListener
public void speedExceeded(BoogieSpeedEvent e);
}
// MySpeedListener.java
public class MySpeedListener implements BoogieSpeedListener {
#Override
public void speedExceeded(BoogieSpeedEvent e) {
if (e.getCurrentSpeed() > e.getMaxSpeed()) {
System.out.println("Alert! The " + e.getColor() + " car exceeded the max speed: " + e.getMaxSpeed() + " MPH.");
}
}
}
// BoogieSpeedEvent.java
public class BoogieSpeedEvent { // extends java.util.EventObject
private int maxSpeed;
private int currentSpeed;
private String color;
public BoogieSpeedEvent(int maxSpeed, int currentSpeed, String color) {
// public SpeedEvent(Object source, int maxSpeed, int minSpeed, int currentSpeed) {
// super(source);
this.maxSpeed = maxSpeed;
this.currentSpeed = currentSpeed;
this.color = color;
}
public int getMaxSpeed() {
return maxSpeed;
}
public int getCurrentSpeed() {
return currentSpeed;
}
public String getColor() {
return color;
}
}
My question is: While this code works, I would like the BoogieCar type to notify BoogieCarMain directly without me have to "poll" the BoogieCar type by having to invoke the getSpeedingStatus() method.
In other words, perhaps defining a variable in BoogieCarMain.java that changes whenever one of the three cars exceeds its predefined speed limit. Is it possible to have the BoogieCar type set the variable?
Is there a cleaner way to do this?
TIA,
coson
Callbacks are ideal for this scenario.
// BoogieCarMain provides a sink for event-related information
public void handleSpeeding(BoogieCar car) {
System.out.println(car.getSpeedingStatus());
}
// MySpeedListener knows about an object that wants event-related information.
// I've used the constructor but an addEventSink method or similar is probably better.
public MySpeedListener(BoogieCarMain eventSink) {
this.eventSink = eventSink;
}
// MySpeedListener handles events, including informing objects that want related information.
// You decide if the event is an appropriate type for the sink to know about.
// Often it isn't, and instead your listener should pull the relevant info out of the event and pass it to the sink.
public void speedExceeded(BoogieSpeedEvent e) {
if (e.getCurrentSpeed() > e.getMaxSpeed()) {
// I've taken the liberty of adding the event source as a member of the event.
eventSink.handleSpeeding(e.getCar());
}
}

Java: how do I create getter/setter methods for a hashmap with a custom type?

I have this sparse matrix implementation:
I'm trying to write getter/setter methods for individual elements based on their key, but I'm not sure how to do this with my custom type Coordinates. For example, theMatrix.get(coordinates) (the usual way) doesn't work.
Could someone show me how to do this?
Class coordinate is not accessible outside of your Matrix class.
Indeed, its an implementation detail that you don't want to make visible to the end-user. Please check the getters and setters in the example below.
If you still want to make Coordinates class available to the end-user, you wan make it public.
public class Matrix
{
private static class Coordinates
{
private int x = 0;
private int y = 0;
private int data = 0;
public Coordinates(final int x, final int y)
{
this.x = x;
this.y = y;
data = ((x + "") + (y + "")).hashCode();
}
#Override
public boolean equals(final Object obj)
{
if (obj instanceof Coordinates)
{
Coordinates Coordinates = (Coordinates) obj;
return ((x == Coordinates.x) && (y == Coordinates.y));
}
else
{
return false;
}
}
#Override
public int hashCode()
{
return data;
}
}
private int numrows;
private int numcolumns;
private HashMap<Coordinates, Double> theMatrix;
public Matrix(final int numrows, final int numcolumns)
{
this.numrows = numrows;
this.numcolumns = numcolumns;
}
public Matrix(HashMap<Coordinates, Double> matrixdata)
{
theMatrix = new HashMap<Coordinates, Double>(matrixdata);
}
public Double get(int row, int col, double defaultValue)
{
Double ret = theMatrix.get(new Coordinates(row, col));
return ret != null ? ret : defaultValue;
}
public void set(int row, int col, Double value)
{
theMatrix.put(new Coordinates(row, col), value);
}
}

What is the Swing-equivalent to HTML <optgroup>

I want my JComboBox to group multiple options together, similar to the HTML optgroup:
<select>
<optgroup label="A">
<option/>
<option/>
</optgroup>
</select>
I could not find any solution for this in Swing. Manipulating the UI-Renderer for the Combobox seems to be a bad idea, as it's OS & L&F-dependent (and they are private so cannot extend).
Consider the following implementation as a basic guide how to apply custom styling and create non-selectable items:
public class ExtendedComboBox extends JComboBox {
public ExtendedComboBox() {
setModel(new ExtendedComboBoxModel());
setRenderer(new ExtendedListCellRenderer());
}
public void addDelimiter(String text) {
this.addItem(new Delimiter(text));
}
private static class ExtendedComboBoxModel extends DefaultComboBoxModel {
#Override
public void setSelectedItem(Object anObject) {
if (!(anObject instanceof Delimiter)) {
super.setSelectedItem(anObject);
} else {
int index = getIndexOf(anObject);
if (index < getSize()) {
setSelectedItem(getElementAt(index+1));
}
}
}
}
private static class ExtendedListCellRenderer
extends DefaultListCellRenderer {
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
if (!(value instanceof Delimiter)) {
return super.getListCellRendererComponent(list, value, index,
isSelected, cellHasFocus);
} else {
JLabel label = new JLabel(value.toString());
Font f = label.getFont();
label.setFont(f.deriveFont(f.getStyle()
| Font.BOLD | Font.ITALIC));
return label;
}
}
}
private static class Delimiter {
private String text;
private Delimiter(String text) {
this.text = text;
}
#Override
public String toString() {
return text.toString();
}
}
}
You can do this in a custom renderer, as discussed in How to Use Combo Boxes: Providing a Custom Renderer.
I don't believe that there is one simple way of doing this, but there is a way to do it.
I would implement a data model class that indicates the grouping that you've describe above. Place instances of those data models in your javax.swing.ComboBoxModel implementation instance.
You can then implement a javax.swing.ListCellRenderer to format the output as you like with indents for the text data. You may just want to extend the javax.swing.DefaultListCellRenderer or possibly borrow its implementation wholesale from the Java source.
As for the L&F you should be able to stay within normal guidelines by using the above methods and you won't have to fight with figuring out how to implement it. Look at the default Swing components they will provide a lot of insight in to how to deal with L&F.
Additionally, I think there are mechanisms (you'll have to forgive me, it's been YEARS since I've done full Swing development) to allow you to determine if an item is selectable or not.
I was wanting this myself today, and I've spent the day figuring it out piecing things together to implement a similar model with a JList rather than with the suggested JComboBox. I've finally come up with a solution using GlazedLists EventList and SeparatorList with the corresponding DefaultEventListModel. I override the CellRenderer and the DefaultListSelectionModel. In the end I posted my own answer to my own question on this: How to prevent selection of SeparatorList.Separator in a JList?
Here's my final working code:
public class MyFrame extends javax.swing.JFrame {
private final EventList<BibleVersion> bibleVersions;
private final SeparatorList<BibleVersion> versionsByLang;
private boolean[] enabledFlags;
public MyFrame(){
bibleVersions = new BasicEventList<>();
bibleVersions.add(new BibleVersion("CEI2008", "Testo della Conferenza Episcopale Italiana", "2008", "Italian"));
bibleVersions.add(new BibleVersion("LUZZI", "Diodati Nuova Riveduta - Luzzi", "1927", "Italian"));
bibleVersions.add(new BibleVersion("NVBSE", "Nova Vulgata - Bibliorum Sacrorum Editio", "1979", "Latin"));
bibleVersions.add(new BibleVersion("NABRE", "New American Bible - Revised Edition", "2011", "English"));
bibleVersions.add(new BibleVersion("KJV", "King James Version", "1611", "English"));
versionsByLang = new SeparatorList<>(bibleVersions, new VersionComparator(),1, 1000);
int listLength = versionsByLang.size();
enabledFlags = new boolean[listLength];
ListIterator itr = versionsByLang.listIterator();
while(itr.hasNext()){
enabledFlags[itr.nextIndex()] = !(itr.next().getClass().getSimpleName().equals("GroupSeparator"));
}
jList = new javax.swing.JList();
jList.setModel(new DefaultEventListModel<>(versionsByLang));
jList.setCellRenderer(new VersionCellRenderer());
jList.setSelectionModel(new DisabledItemSelectionModel());
ListSelectionModel listSelectionModel = jList.getSelectionModel();
listSelectionModel.addListSelectionListener(new SharedListSelectionHandler());
}
public static class BibleVersion {
private String abbrev;
private String fullname;
private String year;
private String lang;
public BibleVersion(String abbrev, String fullname, String year, String lang) {
this.abbrev = abbrev;
this.fullname = fullname;
this.year = year;
this.lang = lang;
}
public String getAbbrev() {
return abbrev;
}
public void setAbbrev(String abbrev) {
this.abbrev = abbrev;
}
public String getFullname() {
return fullname;
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
#Override
public String toString() {
return this.getAbbrev() + " — " + this.getFullname() + " (" + this.getYear() + ")"; //To change body of generated methods, choose Tools | Templates.
}
}
private static class VersionComparator implements Comparator<BibleVersion> {
#Override
public int compare(BibleVersion o1, BibleVersion o2) {
return o1.getLang().compareTo(o2.getLang());
}
}
private static class VersionCellRenderer extends DefaultListCellRenderer{
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof SeparatorList.Separator) {
SeparatorList.Separator separator = (SeparatorList.Separator) value;
BibleVersion bibleversion = (BibleVersion)separator.getGroup().get(0);
String lbl = "-- " + bibleversion.getLang() + " --";
label.setText(lbl);
label.setFont(label.getFont().deriveFont(Font.BOLD));
label.setBackground(Color.decode("#004400"));
label.setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
label.setEnabled(false);
} else {
label.setFont(label.getFont().deriveFont(Font.PLAIN));
label.setBorder(BorderFactory.createEmptyBorder(0,15,0,0));
}
return label;
}
}
private class DisabledItemSelectionModel extends DefaultListSelectionModel {
private static final long serialVersionUID = 1L;
#Override
public void setSelectionInterval(int index0, int index1) {
if(index0 < index1){
for (int i = index0; i <= index1; i++){
if(enabledFlags[i]){
super.addSelectionInterval(i, i);
}
}
}
else if(index1 < index0){
for (int i = index1; i <= index0; i++){
if(enabledFlags[i]){
super.addSelectionInterval(i, i);
}
}
}
else if(index0 == index1){
if(enabledFlags[index0]){ super.setSelectionInterval(index0,index0); }
}
}
#Override
public void addSelectionInterval(int index0, int index1) {
if(index0 < index1){
for (int i = index0; i <= index1; i++){
if(enabledFlags[i]){
super.addSelectionInterval(i, i);
}
}
}
else if(index1 < index0){
for (int i = index1; i <= index0; i++){
if(enabledFlags[i]){
super.addSelectionInterval(i, i);
}
}
}
else if(index0 == index1){
if(enabledFlags[index0]){ super.addSelectionInterval(index0,index0); }
}
}
}
private class SharedListSelectionHandler implements ListSelectionListener {
#Override
public void valueChanged(ListSelectionEvent e) {
ListSelectionModel lsm = (ListSelectionModel)e.getSource();
StringBuilder output = new StringBuilder();
int firstIndex = e.getFirstIndex();
int lastIndex = e.getLastIndex();
boolean isAdjusting = e.getValueIsAdjusting();
output.append("Event for indexes ");
output.append(firstIndex);
output.append(" - ");
output.append(lastIndex);
output.append("; isAdjusting is ");
output.append(isAdjusting);
output.append("; selected indexes:");
if (lsm.isSelectionEmpty()) {
output.append(" <none>");
} else {
// Find out which indexes are selected.
int minIndex = lsm.getMinSelectionIndex();
int maxIndex = lsm.getMaxSelectionIndex();
for (int i = minIndex; i <= maxIndex; i++) {
if (lsm.isSelectedIndex(i)) {
output.append(" ");
output.append(i);
}
}
}
output.append(System.getProperty("line.separator"));
System.out.println(output.toString());
}
}
}

Categories

Resources