001    package core;
002    
003    import java.util.*;
004    
005    /**
006     * Position on the board.
007     * 
008     * @specfield x : int // x location of piece
009     * @specfield y : int // y location of piece
010     * 
011     * Abstract Invariant: 0 <= x <= 7 0 <= y <= 7
012     */
013    public class Position
014    {
015            // Positions are numbered from 0
016            // For a1, x=0 and y=0
017            // For a8, x=0 and y=7
018            // For h8, x=7 and y=7
019            final private int x, y;
020        public static final Position[][] pos = ALLarray();
021        public static final Collection<Position> ALL = ALLfn();
022    
023        public static Position[][] ALLarray(){
024            Position[][] ans = new Position[8][8];
025            for(int x = 0; x < 8; x++){
026                for(int y = 0; y < 8; y++){
027                    ans[x][y] = new Position(x, y);
028                }
029            }
030            return ans;
031        }
032        public static Collection<Position> ALLfn(){
033            Collection<Position> ans = new ArrayList<Position>();
034            for(int x = 0; x < 8; x++){
035                for(int y = 0; y < 8; y++){
036                    ans.add(get(x, y));
037                }
038            }
039            return ans;
040        }
041    
042    
043        public static boolean isValid(int x, int y){
044            return ((x >= 0 && x < 8) &&
045                    (y >= 0 && y < 8));
046        }
047        public boolean isValid(){
048            return Position.isValid(x, y);
049        }
050    
051        public static Position get(int x, int y){
052            //return new Position(x, y);
053            return pos[x][y];
054        }
055            /**
056             * Gives a postion in term of x and y coordinates.
057             */
058        private Position(int x, int y) {
059            this.x = x;
060            this.y = y;
061        }
062    
063        /**
064         * @returns x of this position
065         */
066        public int getX() {
067            return x;
068        }
069    
070            /**
071             * @returns y of this position
072             */
073            public int getY()
074            {
075                    return y;
076            }
077    
078            /**
079             * @see Object
080             */
081            public boolean equals(Object o)
082            {
083                    if (o != null && o instanceof Position)
084                    {
085                            Position p = (Position) o;
086                            return (p.x == x && p.y == y);
087                    }
088                    return false;
089            }
090    
091            /**
092             * @see Object
093             */
094            public int hashCode()
095            {
096                    return x * 8 + y;
097            }
098    
099            /**
100             * @param s
101             *            is a String representing a chess position
102             * @requires s is of the form [row][column], where the row is a character
103             *           from a to h and the column is a number from 1 to 8. For
104             *           example, c7 is a legal argument to this method, as is h4.
105             * @returns a Position corresponding to the String s. Its toString method
106             *          will return a String equal to s.
107             */
108            public static Position fromString(String s)
109            {
110                    int x;
111                    int y;
112    
113                    if (!Position.validPosition(s))
114                    {
115                            throw new RuntimeException("'" + s + "' is not a valid position.");
116                    }
117    
118                    // Determine the column (x)
119                    char colChar = s.charAt(0);
120                    x = ((int) colChar) - ((int) 'a');
121                    if (x < 0 || x >= 8) {
122                            // Shouldn't be reached because we already ran validPosition
123                            throw new RuntimeException("'" + s + "' is not a valid position.");
124                    }
125    
126                    // Determine the row (y)
127                    y = Integer.parseInt(s.substring(1)) - 1;
128    
129                    // Make a new position at (x, y) and return it
130                    assert(x >= 0 && x < 8 && y >= 0 && y < 8);
131                    return get(x, y);
132            }
133    
134            /**
135             * @returns true if s is of the form [row][column], where the row is a
136             *          character from a to h and the column is a number from 1 to 8.
137             *          For example, c7 is a valid position String, as is h4.
138             */
139            public static boolean validPosition(String s)
140            {
141    
142                    // First, validate the input length
143                    if (s.length() != 2)
144                    {
145                            return false;
146                    }
147    
148                    // Check the column (x)
149                    char colChar = s.charAt(0);
150                    if (colChar < 'a' || colChar > 'h')
151                    {
152    
153                            // colChar isn't a character from a to h
154                            return false;
155                    }
156    
157                    // Check the row (y)
158                    try
159                    {
160                            int y = Integer.parseInt(s.substring(1));
161                            if (y < 1 || y > 8)
162                            {
163                                    return false;
164                            }
165                    } catch (NumberFormatException ex)
166                    {
167                            return false;
168                    }
169    
170                    // x and y are both valid
171                    return true;
172            }
173    
174            /**
175             * @returns a String representation of this, of the form [column][row]. The
176             *          columns are represented by letters from a to h, where a
177             *          corresponds to a column argument of 1 to the constructor. The
178             *          rows are numbered from 1 to 8. Thus, from White's perspective,
179             *          the lower-left corner is a1, the lower-right corner is h1, and
180             *          the upper-right corner is h8.
181             */
182            public String toString()
183            {
184                return "abcdefgh".charAt(x) + "" + (y+1);
185            }
186    }