quoridor/src/main/java/cz/xelfi/quoridor/Move.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 05 Sep 2010 11:04:26 +0200
changeset 253 ee02205edf13
parent 178 4b78d4f028b3
child 264 d60370059c3c
permissions -rw-r--r--
Showing x when a move to certain position is impossible, showing o when it is fine. Adding Board.findMove method to keep the allowed move logic.
jtulach@3
     1
/*
jtulach@8
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jtulach@8
     3
 *
jtulach@8
     4
 * The contents of this file are subject to the terms of either the GNU
jtulach@8
     5
 * General Public License Version 2 only ("GPL") or the Common
jtulach@8
     6
 * Development and Distribution License("CDDL") (collectively, the
jtulach@8
     7
 * "License"). You may not use this file except in compliance with the
jtulach@8
     8
 * License. You can obtain a copy of the License at
jtulach@8
     9
 * http://www.netbeans.org/cddl-gplv2.html
jtulach@8
    10
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jtulach@8
    11
 * specific language governing permissions and limitations under the
jtulach@8
    12
 * License.  When distributing the software, include this License Header
jtulach@8
    13
 * Notice in each file and include the License file at
jtulach@8
    14
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
jtulach@8
    15
 * particular file as subject to the "Classpath" exception as provided
jtulach@8
    16
 * by Sun in the GPL Version 2 section of the License file that
jtulach@8
    17
 * accompanied this code. If applicable, add the following below the
jtulach@8
    18
 * License Header, with the fields enclosed by brackets [] replaced by
jtulach@8
    19
 * your own identifying information:
jtulach@8
    20
 * "Portions Copyrighted [year] [name of copyright owner]"
jtulach@8
    21
 *
jtulach@8
    22
 * Contributor(s):
jtulach@8
    23
 *
jtulach@8
    24
 * Portions Copyrighted 2009 Jaroslav Tulach
jtulach@3
    25
 */
jtulach@3
    26
jtulach@3
    27
package cz.xelfi.quoridor;
jtulach@3
    28
jtulach@15
    29
import cz.xelfi.quoridor.Player.Direction;
jaroslav@253
    30
import java.util.ArrayList;
jtulach@30
    31
import java.util.Arrays;
jaroslav@253
    32
import java.util.List;
jtulach@3
    33
jtulach@16
    34
/** Encapsulates one possible move that can be applied to existing {@link Board}
jtulach@16
    35
 * by calling its {@link Board#apply} method.
jtulach@3
    36
 *
jtulach@3
    37
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jtulach@3
    38
 */
jtulach@3
    39
public final class Move extends Object {
jtulach@3
    40
    final Direction[] direction;
jtulach@3
    41
    final Fence fence;
jtulach@3
    42
jtulach@3
    43
    private Move(Direction... arr) {
jtulach@3
    44
        direction = arr;
jtulach@3
    45
        fence = null;
jtulach@3
    46
    }
jtulach@3
    47
    private Move(Fence f) {
jtulach@3
    48
        fence = f;
jtulach@3
    49
        direction = null;
jtulach@3
    50
    }
jtulach@75
    51
    private Move() {
jtulach@75
    52
        fence = null;
jtulach@75
    53
        direction = null;
jtulach@75
    54
    }
jtulach@3
    55
jtulach@4
    56
    /** Moves the player's figure to north */
jtulach@3
    57
    public static final Move NORTH = new Move(Direction.NORTH);
jtulach@4
    58
    /** Moves the player's figure to east */
jtulach@3
    59
    public static final Move EAST = new Move(Direction.EAST);
jtulach@4
    60
    /** Moves the player's figure to south */
jtulach@3
    61
    public static final Move SOUTH = new Move(Direction.SOUTH);
jtulach@4
    62
    /** Moves the player's figure to west */
jtulach@3
    63
    public static final Move WEST = new Move(Direction.WEST);
jtulach@75
    64
    /** Allows the player to resign the game */
jtulach@75
    65
    public static final Move RESIGN = new Move();
jtulach@3
    66
jtulach@4
    67
    /** Places a fence into given position with specified orientation.
jtulach@4
    68
     * The faces postions are numbered 1-8 and A-H according to following
jtulach@4
    69
     * graph: <pre>
jtulach@4
    70
            H   G   F   E   D   C   B   A
jtulach@4
    71
            |   |   |   |   |   |   |   |
jtulach@4
    72
        +-----------------------------------+
jtulach@4
    73
        |                                   |
jtulach@4
    74
     1--|   +   +   +   +   +   +   +   +   |--1
jtulach@4
    75
        |                                   |
jtulach@4
    76
     2--|   +   +   +   +   +   +   +   +   |--2
jtulach@4
    77
        |                                   |
jtulach@4
    78
     3--|   +   +   +   +   +   +   +   +   |--3
jtulach@4
    79
        |                                   |
jtulach@4
    80
     4--|   +   +   +   +   +   +   +   +   |--4
jtulach@4
    81
[E]     |                                   |     [W]
jtulach@4
    82
     5--|   +   +   +   +   +   +   +   +   |--5
jtulach@4
    83
        |                                   |
jtulach@4
    84
     6--|   +   +   +   +   +   +   +   +   |--6
jtulach@4
    85
        |                                   |
jtulach@4
    86
     7--|   +   +   +   +   +   +   +   +   |--7
jtulach@4
    87
        |                                   |
jtulach@4
    88
     8--|   +   +   +   +   +   +   +   +   |--8
jtulach@4
    89
        |                                   |
jtulach@4
    90
        +-----------------------------------+
jtulach@4
    91
            |   |   |   |   |   |   |   |
jtulach@4
    92
            H   G   F   E   D   C   B   A
jtulach@4
    93
     * </pre>
jtulach@4
    94
     *
jtulach@4
    95
     *
jtulach@21
    96
     * @param column x-coordinate of the middle of the fence from 'A' to 'B'
jtulach@21
    97
     * @param row y-coordinate of the middle of the fence
jtulach@4
    98
     * @param orientation place the fence horizontally or vertically
jtulach@4
    99
     * @return the new board
jtulach@4
   100
     * @exception IllegalPositionException if the move is not possible
jtulach@4
   101
     */
jtulach@21
   102
    public static Move fence(char column, int row, Fence.Orientation orientation) throws IllegalPositionException {
jtulach@21
   103
        if (column < 'A' || 'H' < column) {
jtulach@3
   104
            throw new IllegalPositionException ("x coordinate has to be from A to H"); // NOI18N
jtulach@3
   105
        }
jtulach@31
   106
        if (row < 1 || row > 8) {
jtulach@31
   107
            throw new IllegalPositionException ("y coordinate has to be from 1 to 8"); // NOI18N
jtulach@31
   108
        }
jtulach@21
   109
        return new Move(new Fence ((column - 'A') * 2 + 1, row * 2 - 1, orientation));
jtulach@3
   110
    }
jtulach@3
   111
jtulach@4
   112
    /** Moves the player in given directions. After applying
jtulach@4
   113
     * the first direction, the pawn has to get on a position
jtulach@4
   114
     * that is occupied by other player's pawn.
jtulach@4
   115
     *
jtulach@4
   116
     * @param where one or two directions saying where
jtulach@4
   117
     * @return the new board
jtulach@4
   118
     * @exception IllegalPositionException if the move is not possible
jtulach@4
   119
     */
jtulach@3
   120
    public static Move jump(Direction first, Direction second) {
jtulach@3
   121
        return new Move(first, second);
jtulach@3
   122
    }
jtulach@30
   123
jtulach@34
   124
    /** Converts the value of the move string into valid move, if possible.
jtulach@34
   125
     *
jtulach@34
   126
     * @param move the string in format used by {@link #toString()}
jtulach@34
   127
     * @return the move which's toString() returns the move parameter
jtulach@34
   128
     * @throws IllegalPositionException raised in case the parameter does not
jtulach@34
   129
     *      represent a valid move
jtulach@34
   130
     */
jtulach@34
   131
    public static Move valueOf(String move) throws IllegalPositionException {
jtulach@34
   132
        switch (move.length()) {
jtulach@34
   133
            case 3:
jtulach@34
   134
            if (move.startsWith("H")) {
jtulach@34
   135
                return Move.fence(move.charAt(1), move.charAt(2) - '0', Fence.Orientation.HORIZONTAL);
jtulach@34
   136
            }
jtulach@34
   137
            if (move.startsWith("V")) {
jtulach@34
   138
                return Move.fence(move.charAt(1), move.charAt(2) - '0', Fence.Orientation.VERTICAL);
jtulach@34
   139
            }
jtulach@34
   140
            break;
jtulach@34
   141
            case 2:
jtulach@34
   142
                return Move.jump(Direction.valueOf(move.charAt(0)), Direction.valueOf(move.charAt(1)));
jtulach@34
   143
            case 1:
jtulach@34
   144
                switch (move.charAt(0)) {
jtulach@34
   145
                    case 'N': return Move.NORTH;
jtulach@34
   146
                    case 'S': return Move.SOUTH;
jtulach@34
   147
                    case 'E': return Move.EAST;
jtulach@34
   148
                    case 'W': return Move.WEST;
jtulach@34
   149
                }
jtulach@75
   150
            case 6:
jtulach@75
   151
                if ("RESIGN".equals(move)) {
jtulach@75
   152
                    return Move.RESIGN;
jtulach@75
   153
                }
jtulach@34
   154
        }
jtulach@34
   155
        throw new IllegalPositionException(move);
jtulach@34
   156
    }
jtulach@34
   157
jtulach@30
   158
    @Override
jtulach@30
   159
    public String toString() {
jtulach@30
   160
        if (fence != null) {
jtulach@34
   161
            switch (fence.getOrientation()) {
jtulach@34
   162
                case HORIZONTAL: return "H" + fence.getColumn() + fence.getRow();
jtulach@34
   163
                case VERTICAL: return "V" + fence.getColumn() + fence.getRow();
jtulach@34
   164
            }
jtulach@34
   165
            throw new IllegalStateException();
jtulach@30
   166
        } else {
jtulach@75
   167
            if (direction == null) {
jtulach@75
   168
                return "RESIGN"; // NOI18N
jtulach@75
   169
            }
jtulach@34
   170
            StringBuilder sb = new StringBuilder();
jtulach@34
   171
            for (Direction d : direction) {
jtulach@34
   172
                sb.append(d.name().charAt(0));
jtulach@34
   173
            }
jtulach@34
   174
            return sb.toString();
jtulach@30
   175
        }
jtulach@30
   176
    }
jtulach@30
   177
jtulach@30
   178
    @Override
jtulach@30
   179
    public boolean equals(Object obj) {
jtulach@30
   180
        if (obj == null) {
jtulach@30
   181
            return false;
jtulach@30
   182
        }
jtulach@30
   183
        if (getClass() != obj.getClass()) {
jtulach@30
   184
            return false;
jtulach@30
   185
        }
jtulach@30
   186
        final Move other = (Move) obj;
jtulach@30
   187
        if (!Arrays.deepEquals(this.direction, other.direction)) {
jtulach@30
   188
            return false;
jtulach@30
   189
        }
jtulach@30
   190
        if (this.fence != other.fence && (this.fence == null || !this.fence.equals(other.fence))) {
jtulach@30
   191
            return false;
jtulach@30
   192
        }
jtulach@30
   193
        return true;
jtulach@30
   194
    }
jtulach@30
   195
jtulach@30
   196
    @Override
jtulach@30
   197
    public int hashCode() {
jtulach@30
   198
        int hash = 3;
jtulach@30
   199
        hash = 47 * hash + Arrays.deepHashCode(this.direction);
jtulach@30
   200
        hash = 47 * hash + (this.fence != null ? this.fence.hashCode() : 0);
jtulach@30
   201
        return hash;
jtulach@30
   202
    }
jtulach@30
   203
jaroslav@178
   204
    public Move getMirrorMove(){
jaroslav@178
   205
        if(fence != null){
jaroslav@178
   206
            return new Move(new Fence(16-fence.getX(), fence.getY(), fence.getOrientation()));
jaroslav@178
   207
        }
jaroslav@178
   208
        if(direction == null)
jaroslav@178
   209
            return new Move();
jaroslav@178
   210
        int dirSize = direction.length;
jaroslav@178
   211
        Direction[] mirrorDirection = new Direction[dirSize];
jaroslav@178
   212
        for(int i = 0; i < dirSize; i++){
jaroslav@178
   213
            if(direction[i].equals(Direction.NORTH))
jaroslav@178
   214
                mirrorDirection[i] = Direction.NORTH;
jaroslav@178
   215
            else if(direction[i].equals(Direction.SOUTH))
jaroslav@178
   216
                mirrorDirection[i] = Direction.SOUTH;
jaroslav@178
   217
            else if(direction[i].equals(Direction.EAST))
jaroslav@178
   218
                mirrorDirection[i] = Direction.WEST;
jaroslav@178
   219
            else if(direction[i].equals(Direction.WEST))
jaroslav@178
   220
                mirrorDirection[i] = Direction.EAST;
jaroslav@178
   221
        }
jaroslav@178
   222
        return new Move(mirrorDirection);
jaroslav@178
   223
    }
jaroslav@178
   224
jtulach@30
   225
jaroslav@253
   226
    static List<Move> allMovements() {
jaroslav@253
   227
        List<Move> arr = new ArrayList<Move>();
jaroslav@253
   228
        
jaroslav@253
   229
        arr.add(Move.EAST);
jaroslav@253
   230
        arr.add(Move.WEST);
jaroslav@253
   231
        arr.add(Move.NORTH);
jaroslav@253
   232
        arr.add(Move.SOUTH);
jaroslav@253
   233
        
jaroslav@253
   234
        for (Direction d1 : Player.Direction.values()) {
jaroslav@253
   235
            for (Direction d2 : Player.Direction.values()) {
jaroslav@253
   236
                arr.add(Move.jump(d1, d2));
jaroslav@253
   237
            }
jaroslav@253
   238
        }
jaroslav@253
   239
        return arr;
jaroslav@253
   240
    }
jtulach@3
   241
}