Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy does my HashMap recognize hash keys that aren't supposed to be keys yet?
    primarykey
    data
    text
    <p>I'm programming the game of Othello and I am storing the possible moves found in a <code>HashMap</code> in the following way: </p> <pre><code>Hashmap&lt;Matrix, PossibleMovesVector&gt; </code></pre> <p>Matrix is an object which contains an <code>int[8][8]</code>, which describes the current board situation. It overrides <code>hashCode()</code> and <code>equals()</code> in the following way. (This was necessary because the standard <code>hashCode()</code> for multidimensional arrays don't look at the contents of nested arrays.)</p> <pre><code>@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Arrays.deepHashCode(board); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Matrix other = (Matrix) obj; if (!Arrays.equals(board, other.board)) return false; return true; } </code></pre> <p>This seemed to work OK. But when I tested it out, and painted about 100 or so new boards on my screen, I suddenly got the following message in my console:</p> <blockquote> <p>Recognized hashCode xxxxxxxxxx<br> Getting moves from HashMap...</p> </blockquote> <p>But this happens for a board which I know is new. Can it be that Othello has so many states that hashcodes repeat themselves? This is the only explanation I could find. That, or there's something wrong in my code. But I don't think that last scenario's the case, because it takes so long to go wrong.</p> <p>EDIT: This is roughly how my program works. getMoves() is a bit wordy, but all it does is: check if the board has already been checked for moves, if it's not go check the possible moves.<br> - Whenever a player makes a move m.board is changed. (Instead of making a whole new Matrix object.)<br> - boardHash contains another hash table (I would prefer a plain and simple array, though) which stores whether the possible move is for player 1 or player 2. In my previous post I didn't think this was relevant, so simplified it to a single vector. </p> <p>The code, roughly, looks like this: </p> <pre><code>public void Init(){ //Initialize board m_board = new Matrix(new int[8][8]); m_board.Init(); //Compute initial possible moves boardHash.put(m_board, new HashMap&lt;Integer, Vector&lt;Matrix&gt;&gt;()); boardHash.get(m_board).put(whosTurn, getPossibleMoves(whosTurn)); } public Vector&lt;Matrix&gt; getPossibleMoves(int forWho) { // Assign variable so the code doesn't get too cluttered HashMap&lt;Integer, Vector&lt;Matrix&gt;&gt; moveMap = boardHash.get(m_board); // Maybe moveMap doesn't even exist is our lookup table yet if(moveMap == null){ System.out.println("\nNever before seen board..."); moveMap = new HashMap&lt;Integer, Vector&lt;Matrix&gt;&gt;(); boardHash.put(m_board, moveMap); moveMap.put(forWho,getPossibleMoves(forWho)); }else{ System.out.println("\nRecognized hashCode "+m_board.hashCode()); // If it does exist, maybe no possible moves are stored in it if(moveMap.get(forWho)==null){ boardHash.put(m_board, m_board.board); //So then make it: // System.out.println("No moves for "+side+" yet..."); Vector&lt;Matrix&gt; v_possMoves = new Vector&lt;Matrix&gt;(); //For every empty square on the current field... for(int column = 0; column&lt;8; column++){ for(int row = 0; row&lt;m_board.board[column].length; row++){ if(m_board.board[column][row] == 0){ //Check if this move is valid, and if it is, return the resulting board Matrix possibleMoveMatrix = new Matrix(makeLines(column,row,forWho)); if(possibleMoveMatrix.board != null){ //add it to the vector v_possMoves.add(possibleMoveMatrix); } } } } if(v_possMoves.isEmpty()){ System.out.println("No possible moves for player "+forWho); } moveMap.put(forWho,v_possMoves); } } return moveMap.get(forWho); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload