Я программирую игру Отелло и сохраняю возможные ходы, найденные в HashMap
, следующим образом:
Hashmap<Matrix, PossibleMovesVector>
Матрица - это объект, содержащий int[8][8]
, которыйописывает текущую ситуацию на доске.Он переопределяет hashCode()
и equals()
следующим образом.(Это было необходимо, потому что стандарт hashCode()
для многомерных массивов не смотрит на содержимое вложенных массивов.)
@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;
}
Это, похоже, работает нормально.Но когда я проверил это и нарисовал около 100 или около того новых плат на моем экране, я внезапно получил следующее сообщение в моей консоли:
Распознанный hashCode xxxxxxxxxx
Получение ходов из HashMap ...
Но это происходит для доски, которая, как я знаю, нова.Может ли быть так, что у Отелло так много состояний, что хэш-коды повторяются?Это единственное объяснение, которое я смог найти.Это или что-то не так в моем коде.Но я не думаю, что в последнем сценарии дело обстоит именно так, потому что для того, чтобы пойти не так, нужно так много времени.
РЕДАКТИРОВАТЬ: Примерно так работает моя программа.getMoves () немного многословно, но все, что он делает: проверяет, проверена ли уже доска на ходы, если нет, проверяет возможные ходы.
- всякий раз, когда игрок делает ход, меняется m.board.(Вместо создания совершенно нового объекта Matrix.)
- boardHash содержит еще одну хэш-таблицу (хотя я бы предпочел простой и простой массив), в которой хранится информация о том, возможен ли ход для игрока 1 или игрока 2. В моем предыдущем постеЯ не думал, что это актуально, поэтому упростил это до одного вектора.
Код, примерно, выглядит так:
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<Integer, Vector<Matrix>>());
boardHash.get(m_board).put(whosTurn, getPossibleMoves(whosTurn));
}
public Vector<Matrix> getPossibleMoves(int forWho) {
// Assign variable so the code doesn't get too cluttered
HashMap<Integer, Vector<Matrix>> 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<Integer, Vector<Matrix>>();
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<Matrix> v_possMoves = new Vector<Matrix>();
//For every empty square on the current field...
for(int column = 0; column<8; column++){
for(int row = 0; row<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);
}