2

So I have a playerID and numwalls for each player in a board game I'm making. Right now to remove walls when each player uses one, everyone is basically sharing walls.

So I figured I should make a hashmap to hold playerID as the key and numwalls as the value.

But I don't know how to decrement the keys value when it is supposed to use a wall.

I'll show a snip out my code that has the issue.

public int getWallsRemaining(int i) {
    return numWalls;
}

public void lastMove(PlayerMove playerMove) {
    System.out.println("in lastMove... " + playerMove);
    /**
     * if piece moves, update its position
     */
    if(playerMove.isMove() == true){

        Integer player = playerMove.getPlayerId();

        Coordinate newLoc = new Coordinate(playerMove.getEndRow(), playerMove.getEndCol());
        playerHomes.put(player, newLoc);

    }
    /**
     * if a wall is placed, subtract the wall form the player who placed it
     * and subtract the appropriate neighbors.
     */
    if(playerMove.isMove() == false){
        numWalls-=1;
        removeNeighbor(playerMove.getStart(), playerMove.getEnd());

    }


}

Here's where I initialize everything, walls is my map for what I'm trying to do:

private Map<Coordinate, HashSet<Coordinate>> graph;

private int PlayerID;
private int numWalls;
private Map<Integer, Coordinate> playerHomes;
private Map<Integer, Integer> walls;



@Override
public void init(Logger logger, int playerID, int numWalls, Map<Integer, Coordinate> playerHomes) {


    this.PlayerID = playerID;
    this.walls = new HashMap<Integer, Integer>();
    this.numWalls = numWalls;
    this.playerHomes = playerHomes;
    this.graph = new HashMap<Coordinate, HashSet<Coordinate>>();
    walls.put(playerID,numWalls);

    for(int r = 0; r <= 10; r++){
        for(int c = 0; c <= 10; c++){
            HashSet<Coordinate> neighbors = new HashSet<Coordinate>();
                 if(r > 0){
                    neighbors.add(new Coordinate(r - 1, c));
                 }
                if(r < 8){
                     neighbors.add(new Coordinate(r + 1, c));
                 }
                if(c > 0){
                    neighbors.add(new Coordinate(r, c - 1));
                 }
                if(c < 8){
                    neighbors.add(new Coordinate(r, c + 1));
                 }
            graph.put((new Coordinate(r,c)), neighbors);
        }
    }
}

You can see in my lastMove method that I decrement walls by 1. This is my problem. I want to decrement a specified playerID numwall by 1. What I have now works for 1-player only. I need this to work for up to 4-players.

Amir Afghani
  • 37,814
  • 16
  • 84
  • 124
FatFockFrank
  • 169
  • 1
  • 4
  • 17

3 Answers3

4

A HashMap can just contain objects (not primitives) so you must insert an Integer as a value mapped.

Since an Integer is an immutable class you can't directly modify the value, you need to replace it by discarding the old value, something like:

HashMap<Player, Integer> walls = new HashMap<Player,Integer>();

int currentWalls = walls.get(player);
walls.put(player, currentWalls-1);
Jack
  • 131,802
  • 30
  • 241
  • 343
  • This code should (probably) be synchronized. Or else use an [AtomicInteger ](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger.html) as the value. – user949300 Mar 31 '15 at 23:47
2

I'd use an AtomicInteger to hold your values. It's thread safe, in case multiple players are running into walls at the same time. And it's simpler than recreating a new Integer every time (as in @Jack answer)

HashMap<Player, AtomicInteger> walls = new HashMap<Player,AtomicInteger>();

...

walls.get(player).decrementAndGet();

If need be, you can return the value from the decrementAndGet() call to retrieve the new number of walls.

user949300
  • 15,364
  • 7
  • 35
  • 66
  • Hi, thanks for your response. I have this working now by using a map of Integer key and values but your AtomicInteger idea is interesting and new to me. So I created a loop in my init to populate my walls map but when I do walls.put(i, numwalls), I get an error under numWalls saying it requires an AtomicInteger, not an Integer. I''m a bit confused but I like your idea – FatFockFrank Apr 01 '15 at 00:20
  • Java will "autobox" an int to an Integer, but not to an AtomicInteger. In your loop go `walls.put(theKey, new AtomicInteger(numwalls));` – user949300 Apr 01 '15 at 03:16
0

To change the value stored with a key you should remove the old value and add a new value.

That said, have you considered creating a Player class to encapsulate the playerId and the number of walls the player has? It may work better for the plans you have.