aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/fr/umlv/java/wallj/board/Board.java
blob: 2e67c536651b3af20cfc025d70312578b6c00095 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package fr.umlv.java.wallj.board;

import fr.umlv.java.wallj.block.BlockType;

import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * An immutable BlockType matrix.
 *
 * @author Pacien TRAN-GIRARD
 */
public final class Board {

  /**
   * Board Builder
   */
  public static final class Builder {
    private final BlockType[][] map;

    /**
     * @param width  width in tiles
     * @param height height in tiles
     */
    public Builder(int width, int height) {
      map = new BlockType[height][width];
    }

    /**
     * @param pos  the tile position vector
     * @param type the BlockType to set
     * @return the Builder
     */
    public Builder setBlockTypeAt(TileVec2 pos, BlockType type) {
      map[pos.getRow()][pos.getCol()] = type;
      return this;
    }

    /**
     * @return the immutable Board
     */
    public Board build() {
      return new Board(map);
    }
  }

  private final BlockType[][] map;

  private Board(BlockType[][] map) {
    int w = Matrix.getWidth(map), h = Matrix.getHeight(map);
    this.map = new BlockType[h][w];
    for (int row = 0; row < h; ++row) System.arraycopy(map[row], 0, this.map[row], 0, w);
  }

  /**
   * @param pos the tile position vector
   * @return the element at the given position
   */
  public BlockType getBlockTypeAt(TileVec2 pos) {
    return map[pos.getRow()][pos.getCol()];
  }

  /**
   * @return the dimension of the Board
   */
  public TileVec2 getDim() {
    return TileVec2.of(Matrix.getWidth(map), Matrix.getHeight(map));
  }

  /**
   * @param v a tile vector
   * @return T(v is a valid position of an element within the board)
   */
  public boolean inside(TileVec2 v) {
    TileVec2 dim = getDim();
    return v.getRow() >= 0 && v.getCol() >= 0 &&
           v.getRow() < dim.getRow() && v.getCol() < dim.getCol();
  }

  /**
   * @return a stream of block types and their associated tile position vectors
   */
  public Stream<Map.Entry<TileVec2, BlockType>> stream() {
    TileVec2 dim = getDim();
    return IntStream.range(0, dim.getRow() * dim.getCol())
           .mapToObj(i -> TileVec2.of(i % dim.getCol(), i / dim.getCol()))
           .map(v -> new AbstractMap.SimpleImmutableEntry<>(v, getBlockTypeAt(v)));
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Board)) return false;
    Board board = (Board) o;
    return Arrays.deepEquals(map, board.map);
  }

  @Override
  public int hashCode() {
    return Arrays.hashCode(map);
  }

}