aboutsummaryrefslogtreecommitdiff
path: root/src/ch/epfl/xblast/Cell.java
blob: 16632ccf2500f8cf573c85741521366178d4b7b7 (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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
package ch.epfl.xblast;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * A Cell.
 *
 * @author Pacien TRAN-GIRARD (261948)
 * @author Timothée FLOURE (257420)
 */
public final class Cell {

    /**
     * The width of the board (number of columns).
     */
    public static final int COLUMNS = 15;

    /**
     * The height of the board (number of rows).
     */
    public static final int ROWS = 13;

    /**
     * The total number of Cell-s of the board.
     */
    public static final int COUNT = COLUMNS * ROWS;

    /**
     * The list of the board's Cell's, major-ordered.
     */
    public static final List<Cell> ROW_MAJOR_ORDER = Collections.unmodifiableList(rowMajorOrder());

    /**
     * The list of the board's Cell-s, spiral-ordered.
     */
    public static final List<Cell> SPIRAL_ORDER = Collections.unmodifiableList(spiralOrder());
    /**
     * The coordinates of the Cell.
     */
    private final int x, y;

    /**
     * Instantiates a new Cell with the given coordinates.
     *
     * @param x the x-coordinate
     * @param y the y-coordinate
     */
    public Cell(int x, int y) {
        this.x = normalize(COLUMNS, x);
        this.y = normalize(ROWS, y);
    }

    /**
     * Normalizes the given number (using the integer floor modulus).
     *
     * @param max the maximum (the divisor)
     * @param n   the number to normalize (the dividend)
     * @return the normalized value
     */
    static int normalize(int max, int n) {
        return Math.floorMod(n, max);
    }

    /**
     * Builds a major-ordered list of Cell-s.
     *
     * @return the list of Cell-s
     */
    private static ArrayList<Cell> rowMajorOrder() {
        ArrayList<Cell> list = new ArrayList<>(COUNT);

        for (int row = 0; row < ROWS; ++row)
            for (int col = 0; col < COLUMNS; ++col)
                list.add(new Cell(col, row));

        return list;
    }

    /**
     * Builds a spiral-ordered list of Cell-s.
     *
     * @return the list of Cell-s
     */
    private static ArrayList<Cell> spiralOrder() {
        ArrayList<Cell> list = new ArrayList<>(COUNT);
        ArrayList<Integer> ix = range(0, COLUMNS, 1);
        ArrayList<Integer> iy = range(0, ROWS, 1);
        boolean horizontal = true;

        while (!ix.isEmpty() && !iy.isEmpty()) {
            ArrayList<Integer> i1 = horizontal ? ix : iy;
            ArrayList<Integer> i2 = horizontal ? iy : ix;
            int c2 = i2.remove(0);
            for (int c1 : i1)
                list.add(horizontal ? new Cell(c1, c2) : new Cell(c2, c1));

            Collections.reverse(i1);
            horizontal = !horizontal;
        }

        return list;
    }

    /**
     * Creates a list containing an arithmetic progression.
     *
     * @param from the starting value
     * @param to   the boundary value
     * @param step the arithmetic step
     * @return the arithmetic progression
     */
    private static ArrayList<Integer> range(int from, int to, int step) {
        int n = (to - from) / step;
        ArrayList<Integer> list = new ArrayList<>(n);

        for (int i = 0; i < n; ++i)
            list.add(from + (i * step));

        return list;

    }

    /**
     * Returns the normalized x-coordinate of the Cell.
     *
     * @return the x-coordinate
     */
    public int x() {
        return this.x;
    }

    /**
     * Returns the normalized y-coordinate of the Cell.
     *
     * @return the y-coordinate
     */
    public int y() {
        return this.y;
    }

    /**
     * Returns the neighboring Cell at the given Direction.
     *
     * @param dir the Direction
     * @return the neighboring Cell
     */
    public Cell neighbor(Direction dir) {
        return new Cell(this.x + dir.xVector(), this.y + dir.yVector());
    }

    /**
     * Returns the hash code for this Cell, given by its row-major index.
     *
     * @return the hash code
     */
    @Override
    public int hashCode() {
        return this.rowMajorIndex();
    }

    /**
     * Returns T(the given Object is equal to this Cell (have the same coordinates)).
     *
     * @param that the Object to compare against
     * @return T(the given Object is equal to this Cell)
     */
    @Override
    public boolean equals(Object that) {
        if (that == null) return false;
        if (that == this) return true;
        if (!(that instanceof Cell)) return false;
        return (((Cell) that).rowMajorIndex() == this.rowMajorIndex());
    }

    /**
     * Returns the index of the Cell (major ordered).
     *
     * @return the index of the Cell
     */
    public int rowMajorIndex() {
        return this.y * COLUMNS + this.x;
    }

    /**
     * Returns a String representation of the coordinates of the Cell.
     *
     * @return a String representation of the coordinates of the Cell.
     */
    @Override
    public String toString() {
        return String.format("(%d,%d)", this.x, this.y);
    }

}