Java – is hashing a suitable solution? Am I overly complicated?

I wrote a 2D platform game. I need room (up to 4) doors I write it in Java, but the language doesn't matter

Each room can have 4 doors at the top, bottom and side I call them north, South, East and West When I build a room, I only give it an integer. Each bit of the integer represents a door

For example, if I want a room with three doors (one in the north, one in the East and one in the West), I give the room number: 11 (1011 in binary)

Therefore, each gate has an integer to identify it

NORTH = 8;//1000
SOUTH = 4;//0100
EAST =  2;//0010
WEST =  1;//0001

If I generate a room, I give them a combination of these identifiers

For example, the room mentioned above will get an identifier

doorStock = NORTH | EAST | WEST;

I store these doors in a simple array:

Door doors[] = new Door[4];

My problem is: I need a function that maps identifiers to the correct index in the array I don't always need four doors

Everything I did initially seems to be the simplest: the gate array always has four elements, and the index I won't use will simply remain empty

public Door getDoor(int doorID){
    switch(doorID){
        case NORTH:{
            return doors[0];
        }
        case SOUTH:{
            return doors[1];
        }
        case EAST:{
            return doors[2];
        }
        case WEST:{
            return doors[3];
        }
    }
    return null;
}

To be safe, I need to make sure that the door I asked for really exists in the room

private boolean doorExists(int doorID){
    return (doorID & doorStock) != 0
}

Therefore, the query function is as follows:

public Door getDoor(int doorID){
    switch(doorID){
        case NORTH:{
            if(doorExists(NORTH))return doors[0];
            else return null;
        }
        case SOUTH:{
            if(doorExists(NORTH))return doors[1];
            else return null;
        }
        case EAST:{
            if(doorExists(NORTH))return doors[2];
            else return null;
        }
        case WEST:{
            if(doorExists(NORTH))return doors[3];
            else return null;
        }
    }
    return null;
}

Which job, but! In this way, the array may waste space with unused elements Plus the door may have any size, increasing memory waste

Not to mention, I may need more "slot" doors (for example, if I try to achieve this in 3D), so I decided to try to make the size of the gate array depend on the door identifier:

Door doors = new Door[Integer.bitCount(doorStock)];

This gives an indexoutofbounds error really fast I'm not surprised, because the gate array can be any size from 0 to 4, so I need a new hash method

I came up with two hash tables. One is array index:

private final int[][] doorhash = {
    /* NORTH  SOUTH   EAST    WEST doorStock*/
    { -1,-1,-1} /*0000*/,{ -1,0} /*0001*/,-1} /*0010*/,1} /*0011*/,-1} /*0100*/,1} /*0101*/,1,-1} /*0110*/,2} /*0111*/,{  0,-1} /*1000*/,1} /*1001*/,-1} /*1010*/,2} /*1011*/,-1} /*1100*/,2} /*1101*/,2,-1} /*1110*/,3} /*1111*/
};

One that helps map the previous table:

private final int[] directionHash = {
    -1,/*0000*/
     3,/*0001 - WEST*/
     2,/*0010 - EAST*/
    -1,/*0011*/
     1,/*0100 - SOUTH*/
    -1,/*0101*/
    -1,/*0110*/
    -1,/*0111*/
     0,/*1000 - NORTH*/
};

So my current mapping functions are as follows:

public Door getDoor(int doorID){
    switch(doorID){
        case NORTH:{
            if(doorExists(NORTH))return doors[doorhash[doorStock][directionHash[NORTH]]];
            else return null;
        }
        case SOUTH:{
            if(doorExists(NORTH))return doors[doorhash[doorStock][directionHash[SOUTH]]];
            else return null;
        }
        case EAST:{
            if(doorExists(NORTH))return doors[doorhash[doorStock][directionHash[EAST]]];
            else return null;
        }
        case WEST:{
            if(doorExists(NORTH))return doors[doorhash[doorStock][directionHash[WEST]]];
            else return null;
        }
    }
    return null;
}

This also seems to work, but I think there is a simpler solution to this problem, or a hash table with less waste I don't think it should be asymptotically flexible, or I'm too complicated What would be a better way?

Thank you for your time!

Solution

Enumeration is your friend:

// Each possible direction - with Up/Down added to show extendability.
public enum Dir {
  North,South,East,West,Up,Down;
}

class Room {
  // The doors.
  EnumSet doors = EnumSet.noneOf(Dir.class);

  // Many other possible constructors.
  public Room ( Dir ... doors) {
    this.doors.addAll(Arrays.asList(doors));
  }

  public boolean doorExists (Dir dir) {
    return doors.contains(dir);
  }
}

It's only natural that we should do something important for you They also provide a very efficient off the shelf enumset

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>