Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Thursday, May 7, 2020

Java: Return enum instead of boolean

We have a game where you place down buildings. So there is always a method that looks like that:

public boolean validPlace(BuildingType type, Location location) {

    for (int ix = 0; ix < type.w; ix++) {
        for (int iy = 0; iy < type.h; iy++) {
            
            if (/* check if overlapping */) {
                return false;
            } else if (/* check if road missing */) {
                return false;
            }
        }
    }
    return true;
}

The problem: While writing the game logic everything is fine, but then comes the UI. A can palce / cannot place is not enough for a good UI, you need the reason. And you usually have another method that finds out the reason. But can we use the same method?

First we need an enum with all the possible problems:

public enum PlacementValidity {
    Ok,
    Overlapping,
    RoadMissing;

    public boolean ok() {
        return this == Ok;
    }
}

Then we just return the enum instead of the boolean:

public PlacementValidity validPlace(BuildingType type, Location location) {

    for (int ix = 0; ix < type.w; ix++) {
        for (int iy = 0; iy < type.h; iy++) {
                
            if (/* check if overlapping */) {
                return PlacementValidity.Overlapping;
            } else if (/* check if road missing */) {
                return PlacementValidity.RoadMissing;
            }
        }
    }
    return PlacementValidity.Ok;
}

The helper function ok() method can also be used to reduce verbosity on the game logic side of the code.

if (validPlace(/* ... */).ok()) {




done_

Tuesday, February 18, 2020

Java: Let's serialize with a map

Lets just use a map. So we have a timer like thing:

public class Time implements Serializable {

    private long duration;
    private long start;

    // crazy things

}

Now lets put everything in a map:

    private void writeObject(java.io.ObjectOutputStream out) throws ... {
        Map map = new HashMap<>();

        map.put("duration", duration);
        map.put("start", start);
        out.writeObject(map);
    }

Now lets get everything back from the map:

    private void readObject(java.io.ObjectInputStream in) throws ... {
        Map map = (java.util.Map) in.readObject();

        duration = (long) map.get("duration");
        start = (long) map.get("start");
    }

Lets also put this because we are handling the versioning:

    public static final long serialVersionUID = 1L;

However this is too much stuff to write, so lets make a script to write it for us: https://maanoo.com/testing/JavagenSerialMap.html

Now lets add a new thing to see how to handle versioning

    private TimeUnit unit;  // v.2

So we have to update the things: (our script that is)

    private void writeObject(java.io.ObjectOutputStream out) throws ... {
        Map map = new HashMap<>();

        map.put("duration", duration);
        map.put("start", start);
        map.put("unit", unit);
        out.writeObject(map);
    }

    private void readObject(java.io.ObjectInputStream in) throws ... {
        Map map = (Map) in.readObject();

        duration = (long) map.get("duration");
        start = (long) map.get("start");
        if (map.containsKey("unit")) {
            unit = (TimeUnit) map.get("unit");
        } else {
            // TODO unit
        }
    }

And we replace the TODO by setting the default value of the unit:

    unit = TimeUnit.Milliseconds

Also, if or when we are sure that there is none of the old version left, we can remove the check of the key and remove the setting of the default value.

Except the full control that this system provides, the actual data that are stored are serialized primitives and collections, making possible to be access and/or debug the saved data by external program.



done_


Wednesday, October 9, 2019

Java: Optional or just null

So I was making a simple game on the weekend, as we do, and there was a simple (again) player class:

public class Player {
    public final String name;
    private Team team;
    ....
    public boolean friendly(Player other) {
        return team.has(other);
    }
}

But the obvious thing is, can it be null? Yes it can, in cases where the player does not have a team. So I said 'Let's try Optional, why not`.

    private Optional<Team> team;

Then the possibilities for the return statement where limitless from the most straight forward to the most elegant:

    return team.isPresent() && team.get().has(other)

    return team.map(i -> i.has(other)).orElse(false);

    return team.filter(i -> i.has(other)).isPresent();

    return team.orElse(Team.EMPTY).has(other);
    
Or I could remove the Optional again and have just the old thing:

    return team != null && team.has(other);

But 'How will you remember that it can be null in other places?' said the guy. Its a private field, how many places are there really. Also it is logical to null so I would probably check it anyhow.


done_

Thursday, January 10, 2019

Java: Iterable iterator

We all have been in a position with an Iterator in our hands and trying to pass it to a for each loop. And then for some reason that is totally crazy for a second an error pops up:

"Can only iterate over an array or an instance of java.lang.Iterable"

What... a ok... and then what? You could just fix your logic in order or just google for "java iterator to iterable". But could you just make the iterator also an iterable somehow.

Step one, obviously, add the Iterable interface to your iterator:

public class SuperIterator<T> implements Iterator<T>, Iterable<T> {

Step two, add the missing method by return itself as its iterator:

@Override
public Iterator<Character> iterator() {
    return this;
}


done_

Thursday, July 26, 2018

Java: enum or boolean for two value properties


The is always that tip that floats around that you should always use enums instead of booleans, even when there is only two values.

Of course the point is that it will be much easier to read and mainly to extend in the future.

So from a simple

 public void setVisible(boolean value) { ...

you go to

 public enum Visibility { Visible, Gone }

 public void setVisible(Visibility value) { ...

And in the future you could add eg. the Invisible value.

But you miss the simplicity of a boolean and you also get the verbosity of an enum

 setVisible(Visibility.Visible)

and this happens

 setVisible(value ? Visibility.Visible : Visibility.Gone)

The classic solution is to add methods like show() or hide() to avoid the use of the enum

However a simply solution to collect the benefits of both world:

 public void setVisible(boolean value) {
     setVisible(value ? Visibility.Visible : Visibility.Gone)
 }

 public void setVisible(Visibility value) { ...

where the two boolean values will correspond to the two most used values of the enum

And why not add and some methods for the most used values

 public void show() {
     setVisible(Visibility.Visible)
 }

So in the end you have everything

 show()
 setVisible(true)
 setVisible(Visibility.Visible)


done_

Monday, September 12, 2016

Java: Open link in browser

Open a link with the default browser:

Desktop.getDesktop().browse(new URL("http://maanoo.com").toURI());


done_

Monday, October 26, 2015

Java: Set the Clipboard

The easiest way to make the Clipboard contain a string is:

public void setClipboard(String text) {
  Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
  StringSelection selection = new StringSelection(text);
  c.setContents(selection, selection);
}


done_