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 }