CS 100: Programming Assignment P7A and P7B
Solution
Part A.
Correctness + Style Partial Credit Guidelines:
Regular polygon constructor: 1+1
General Constructor: 1+1
Centroid: 2+1 (-1 if return centroid of relative polygon)
Normalization: 1+1
Intersect: 2+1 (-1 if correct but work with relative vertices.)
// An instance of this class is a polygon public class polygon extends closedPolyline { // The Constructors // Constructs a regular polygon with nSides sides, radius r, and center alpha_point. public polygon(point alpha_point, int nSides, double r) { n = nSides; alpha = alpha_point; relVertex = new point[n]; double mu = 2*Math.PI/n; for (int k=0;k < n;k++) relVertex[k] = new point(r*Math.cos(k*mu),r*Math.sin(k*mu)); } // Let n = theta.length = r.length and assume n>=3. Constructs a polygon with n sides. // The k-th vertex is // // (alpha_point.x + r[k]*cos(theta[k]) , alpha_point.y + r[k]*sin(theta[k])). // // It is assumed that the vertices are distinct and that // // 0<=theta[0]<=theta[1]<=...<=theta[n-1]<=2pi // // and that theta[0] + pi < theta[n-1]. public polygon(point alpha_point, double[] theta, double[] r) { n = theta.length; alpha = alpha_point; relVertex = new point[n]; for (int k=0;k < n;k++) relVertex[k] = new point(r[k]*Math.cos(theta[k]),r[k]*Math.sin(theta[k])); } // Yields the centroid of the polygon. public point centroid() { point origin = new point(0,0); point Ck; double Ak; double A = 0; double xSum = 0; double ySum = 0; for(int k=0;k < n;k++) { Ak = point.triangleArea(origin,relVertex[k],relVertex[(k+1)%n]); Ck = point.triangleCentroid(origin,relVertex[k],relVertex[(k+1)%n]); xSum = xSum + Ak*Ck.get_x(); ySum = ySum + Ak*Ck.get_y(); A = A + Ak; } return new point(alpha.get_x()+xSum/A,alpha.get_y()+ySum/A); } // Translates the polygon so its centroid is at (0,0). public void normalize() { point theCentroid = centroid(); translate(-theCentroid.get_x(),-theCentroid.get_y()); } // Yields true if the boundary of this polygon intersects the boundary of P. public boolean intersect(polygon P) { point[] v1 = this.get_absVertex(); point[] v2 = P.get_absVertex(); for(int i=0;i< v1.length;i++) for (int j=0;j < v2.length;j++) if (point.intersect(v1[i],v1[(i+1)%v1.length],v2[j],v2[(j+1)%v2.length])) return true; return false; } }
Part B
8 points total.
2 points overall for style
2 points if one of the four horizontal/vertical searches is correct. 3points if they all work and Rook-Queen threats processed OK
2 points if one of the four diagonal searches works. 3 points if they all work and Bishop-Queen threats procesed OK.
Other types of deductions:
Everything correct but the loop starting values are wrong: -2.
Everything correct but the post loop calculations wrong: -2
Everything correct but overall logic wrong, e.g., return false without checking all 8 search directions: -3
// Yields true if position (r,c) is threatened by a Queen, a Rook, or a Bishop. public boolean qrbThreat(int r, int c) { int r0,c0; // Row and column indices. // Look left along the row. c0=c-1; while (onBoard(r,c0) && pieceBoard[r][c0].equals("")) c0=c0-1; if(onBoard(r,c0) && (pieceBoard[r][c0].equals("Q")||pieceBoard[r][c0].equals("R"))) return true; // Look right along the row. c0=c+1; while (onBoard(r,c0) && pieceBoard[r][c0].equals("")) c0=c0+1; if(onBoard(r,c0) && (pieceBoard[r][c0].equals("Q")||pieceBoard[r][c0].equals("R"))) return true; // Look up along the column. r0=r-1; while (onBoard(r0,c) && pieceBoard[r0][c].equals("")) r0=r0-1; if(onBoard(r0,c) && (pieceBoard[r0][c].equals("Q")||pieceBoard[r0][c].equals("R"))) return true; // Look down along the column. r0=r+1; while (onBoard(r0,c) && pieceBoard[r0][c].equals("")) r0=r0+1; if(onBoard(r0,c) && (pieceBoard[r0][c].equals("Q")||pieceBoard[r0][c].equals("R"))) return true; // Look along the northeast diagonal r0=r-1; c0=c+1; while (onBoard(r0,c0) && pieceBoard[r0][c0].equals("")) { r0=r0-1; c0=c0+1; } if(onBoard(r0,c0) && (pieceBoard[r0][c0].equals("Q")||pieceBoard[r0][c0].equals("B"))) return true; // Look along the southeast diagonal r0=r+1; c0=c+1; while (onBoard(r0,c0) && pieceBoard[r0][c0].equals("")) { r0=r0+1; c0=c0+1; } if(onBoard(r0,c0) && (pieceBoard[r0][c0].equals("Q")||pieceBoard[r0][c0].equals("B"))) return true; // Look along the southwest diagonal r0=r+1; c0=c-1; while (onBoard(r0,c0) && pieceBoard[r0][c0].equals("")) { r0=r0+1; c0=c0-1; } if(onBoard(r0,c0) && (pieceBoard[r0][c0].equals("Q")||pieceBoard[r0][c0].equals("B"))) return true; // Look along the northwest diagonal r0=r-1; c0=c-1; while (onBoard(r0,c0) && pieceBoard[r0][c0].equals("")) { r0=r0-1; c0=c0-1; } if(onBoard(r0,c0) && (pieceBoard[r0][c0].equals("Q")||pieceBoard[r0][c0].equals("B"))) return true; // If you reach this point then none of the eight searches found a qrb threat. return false; }
Here is an implementation that exploits the similarities that you see in the above eight searches.
// Yields true if position (r,c) is threatened by a Queen, a Rook, or a Bishop. public boolean qrbThreat(int r, int c) { boolean diagSearch; // True if looking along one of the four diagonal directions. int r0,c0; for(int dr=-1;dr<=1;dr++) // dr is the row search step (-1, 0, or +1) for(int dc=-1;dc <=1;dc++) // dc is the column search step (-1, 0, or +1) if (Math.abs(dr)+Math.abs(dc)>0) // Always do the following unless dr = 0 and dc = 0. { r0 = r+dr; c0 = c+dc; while (onBoard(r0,c0) && pieceBoard[r0][c0].equals("")) { r0 = r0+dr; c0 = c0+dc; } diagSearch = Math.abs(dr)+Math.abs(dc)==2; if (onBoard(r0,c0) && diagSearch && (pieceBoard[r0][c0].equals("Q") || pieceBoard[r0][c0].equals("B"))) // Found a bishop or queen on a diagonal search. return true; else if (onBoard(r0,c0) && !diagSearch && (pieceBoard[r0][c0].equals("Q") || pieceBoard[r0][c0].equals("R"))) // Found a rook or queen on a row/column search. return true; } return false; }