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