Created
September 2, 2023 17:08
-
-
Save jquast/4e9d6fc6f8bfa696f2e8830a7bccb5c8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ChessPiece { | |
String kind; | |
Position pos; | |
ChessPiece next; | |
ChessPiece(String kind, int xpos, int ypos) | |
{ | |
this.kind = kind; | |
this.pos = new Position(xpos, ypos); | |
next = null; | |
} | |
public String toString(){ | |
String str_color = isWhite() ? "White" : "Black"; | |
return kind + "(" + pos + ", " + str_color + ")"; | |
} | |
public boolean isWhite(){ | |
// piece is "White" if kind string lowercase | |
return kind.toLowerCase().equals(kind); | |
} | |
public boolean isBlack(){ | |
return !isWhite(); | |
} | |
public boolean isMoveLegal(Position dest) { | |
// Firstly, a move must *move*, if the destination position | |
// is equal to our current position, this is illegal. | |
if (dest.x == pos.x && dest.y == pos.y) { | |
System.out.println("Chess piece must move, illegal."); | |
return false; | |
} | |
if (kind.equalsIgnoreCase("r") || kind.equalsIgnoreCase("q")) { | |
// Queen or Rook: | |
// determine horizontal or vertical move. This can be determined if either | |
// the dest_x is equal to our current xpos, or dest_y is equal to our | |
// current ypos, as we can always assume that the other coordinate has | |
// changed given the guard at the top of our method. | |
if (dest.x == pos.x || dest.y == pos.y) { | |
System.out.println("Move is horizontal or vertical, legal."); | |
return true; | |
} | |
} | |
if (kind.equalsIgnoreCase("b") || kind.equalsIgnoreCase("q")) { | |
// Bishop or Queen: | |
// Determine if we move in any 45 degree angles. We can already safely | |
// assume that either dest_x or dest_y is different than our given, so, | |
// as long as the absolute delta between (dest_x, x) is equal to | |
// the absolute delta of (dest_y, y), then a diagonal move has | |
// occurred. | |
if (Math.abs(dest.x - pos.x) == Math.abs(dest.y - pos.y)) { | |
System.out.println("Move is diagonal, legal."); | |
return true; | |
} | |
} | |
if (kind.equalsIgnoreCase("k")) { | |
// King: | |
// if the delta between (x,y)->(x,y) is less than or equal to 1, | |
// then the king has moved in any of its 8 legal positions | |
if (Math.abs(pos.y - dest.y) <= 1 && | |
Math.abs(pos.x - dest.x) <= 1) { | |
System.out.println("Move is fit for King, legal."); | |
return true; | |
} | |
} | |
if (kind.equalsIgnoreCase("n")) { | |
// Knight: | |
// Determine if the delta difference of (x,y) is (1,2) or (2,1), which | |
// tells us whether it has performed any of its legal L-shaped maneuvers. | |
int delta_x = Math.abs(dest.x - pos.x); | |
int delta_y = Math.abs(dest.y - pos.y); | |
if ((delta_x == 1 && delta_y == 2) || (delta_x == 2 && delta_y == 1)) { | |
System.out.println("Knights move is legal."); | |
return true; | |
} | |
} | |
if (kind.equalsIgnoreCase("p")) { | |
// Pawn: TODO request clarification of board layout for starting positions! | |
// | |
// White may only move upward, black downward, and only 1 position, unless | |
// either piece is at their starting position, then they move 2 positions. | |
// I can't tell whether (0, 0) is bottom-left or top-right, and whether | |
// white begins on the bottom, or the top, so its hard to discern that.0w | |
} | |
System.out.println("This move is not legal."); | |
return false; | |
} | |
} | |
// Linked List Class | |
public class ChessPieces | |
{ | |
// head of list | |
private ChessPiece head; | |
// XXX length is never used | |
//private int length; | |
//constructor | |
ChessPieces() | |
{ | |
// length = 0; | |
head = null; | |
} | |
// appends new data node to front of list | |
public void push(String kind, int ypos, int xpos) | |
{ | |
// first new piece defines 'head' ChessPiece. | |
if (head == null) | |
{ | |
head = new ChessPiece(kind, ypos, xpos); | |
// length += 1; | |
} | |
else | |
{ | |
// declare next node, | |
ChessPiece new_piece = new ChessPiece(kind, ypos, xpos); | |
// set next pointer to null (last piece in linked list). | |
new_piece.next = null; | |
// Search through entire linked list, finding the last piece | |
// (where 'next' points to null), | |
ChessPiece last = head; | |
while (last.next != null) | |
{ | |
last = last.next; | |
} | |
// then, redefine 'next' to point to our current 'new_piece'. | |
last.next = new_piece; | |
} | |
} | |
// return ChessPiece at given (x,y) location, if found. | |
public ChessPiece pieceAt(Position pos) | |
{ | |
ChessPiece piece = head; | |
while (piece != null) | |
{ | |
if(piece.pos.x == pos.x && piece.pos.y == pos.y) | |
{ | |
return piece; | |
} | |
piece = piece.next; | |
} | |
return null; | |
} | |
public boolean deletePieceAt(Position dest_pos) | |
{ | |
ChessPiece prev = null; | |
ChessPiece curr = head; | |
boolean oppPieceInDest = false; | |
boolean emptySquare = false; | |
while (curr != null) | |
{ | |
//if the current piece is at the desired destination | |
if(curr.pos.x == dest_pos.x && curr.pos.y == dest_pos.y) { | |
// delete the current piece by dereference, we no longer | |
// point to this piece from the previous, but by pointing beyond it. | |
if (prev != null) | |
{ | |
prev.next = curr.next; | |
} else { | |
// this is the first piece in list, set new head | |
head = curr.next; | |
} | |
return true; | |
} | |
//go to next Node in linked list | |
prev = curr; | |
curr = curr.next; | |
} | |
return true; | |
} | |
} | |
// simple object stores coordinates (x, y). This will make it easy | |
// to create a LinkedList of moves in a "path". | |
public class Position { | |
public int x, y; | |
Position(int x, int y) { | |
this.x = x; | |
this.y = y; | |
} | |
public String toString(){ | |
return x + "," + y; | |
} | |
} | |
import java.io.*; | |
import java.util.Scanner; | |
public class SuggestedChess { | |
public static void main(String[] args) throws IOException { | |
// check number of command line arguments is at least 2 | |
if (args.length < 2){ | |
System.out.println("Usage: java –jar Chessboard.jar <input file> <output file>"); | |
System.exit(1); | |
} | |
// open input file, | |
Scanner fin = new Scanner(new File(args[0])); | |
// output file, | |
Writer fout = new BufferedWriter(new FileWriter(args[1])); | |
// for every line of input file, | |
while( fin.hasNextLine() ) | |
{ | |
// read line | |
String line = fin.nextLine().trim(); | |
// search for ':' character, and split into array of pieces[] and moves[], | |
// representing single-character strings of unit. For example, input line: | |
// k 2 3 K 1 1: 2 3 3 3 | |
// | |
// becomes: | |
// pieces = ["k", "2", "3", "K", "1", "1"] | |
// moves = ["2", "3", "3", "3"] | |
int idx_colon = line.indexOf(": "); | |
String[] strPieces = line.substring(0, idx_colon).split(" "); | |
String[] strMoves = line.substring(idx_colon + ": ".length()).split(" "); | |
// convert string of numbers to array of numbers: | |
// ["2", "3", "3", "3'] | |
// becomes: | |
// [2, 3, 3, 3] | |
int[] moves = StringArrayToInt(strMoves); | |
// convert string of pieces to a linked list of chess pieces | |
ChessPieces pieces = parsePiecesStringArray(strPieces); | |
// track previously moved piece, to ensure turns are taken correctly. | |
ChessPiece last_moved_piece = null; | |
System.out.println("==============================="); | |
System.out.println("Analyzing: " + line); | |
boolean legal = true; | |
for (int i = 0; i < moves.length && legal == true; i+=4) { | |
Position start_pos = new Position(moves[i], moves[i+1]); | |
Position end_pos = new Position(moves[i+2], moves[i+3]); | |
ChessPiece piece_for_move = pieces.pieceAt(start_pos); | |
// was a piece found at starting position? | |
if(piece_for_move == null) { | |
System.out.println("No piece found at " + start_pos); | |
writeIllegalAtIndex(fout, moves, i); | |
legal = false; | |
break; | |
} | |
System.out.println(); | |
System.out.println("Analyzing " + piece_for_move + " moves to (" + end_pos + "):"); | |
// is this the first move? is it white? | |
if(last_moved_piece == null && !piece_for_move.isWhite()) { | |
System.out.println("start piece is black!"); | |
writeIllegalAtIndex(fout, moves, i); | |
legal = false; | |
break; | |
} | |
// a subsequent move? ensure that we are taking turns, | |
if(last_moved_piece != null) { | |
if(last_moved_piece.isBlack() && piece_for_move.isBlack()) { | |
System.out.println("Black tried to move twice"); | |
writeIllegalAtIndex(fout, moves, i); | |
legal = false; | |
break; | |
} | |
else if(last_moved_piece.isWhite() && piece_for_move.isWhite()) { | |
System.out.println("White tried to move twice"); | |
writeIllegalAtIndex(fout, moves, i); | |
legal = false; | |
break; | |
} | |
} | |
// verify that the given coordinate is legal for the given piece. | |
if(!piece_for_move.isMoveLegal(end_pos)) { | |
writeIllegalAtIndex(fout, moves, i); | |
legal = false; | |
break; | |
} | |
// check for blocks, which does not apply to knights. | |
if (!piece_for_move.kind.toLowerCase().equals("n")) { | |
// Create temporary position variable, beginning at our starting position. | |
// Each loop iteration, add or subtract from x and y to reach towards our destination. | |
// This makes perfect horizontal, vertical, and 45 degree angles where appropriate by | |
// simple addition and subtraction at each step, and we are sure whether the move is | |
// legal in this direction, because we already verified that. | |
Position temp_pos = new Position(start_pos.x, start_pos.y); | |
ChessPiece blocked_piece; | |
do { | |
// adjust x value towards destination | |
if (temp_pos.x < end_pos.x) { | |
temp_pos = new Position(temp_pos.x + 1, temp_pos.y); | |
} else if (temp_pos.x > end_pos.x) { | |
temp_pos = new Position(temp_pos.x - 1, temp_pos.y); | |
} | |
// adjust y value towards destination | |
if (temp_pos.y < end_pos.y) { | |
temp_pos = new Position(temp_pos.x, temp_pos.y + 1); | |
} else if (temp_pos.y > end_pos.y) { | |
temp_pos = new Position(temp_pos.x, temp_pos.y - 1); | |
} | |
// check for block | |
System.out.println("Checking for blocking at position " + temp_pos); | |
blocked_piece = pieces.pieceAt(temp_pos); | |
if (blocked_piece != null) { | |
// we are at our final destination, "steal piece" candidate. | |
if(blocked_piece.pos.x == end_pos.x && blocked_piece.pos.y == end_pos.y) { | |
if (piece_for_move.isWhite() && blocked_piece.isWhite()) { | |
System.out.println("White tried to steal its own piece"); | |
writeIllegalAtIndex(fout, moves, i); | |
legal = false; | |
break; | |
} | |
else if (piece_for_move.isBlack() && blocked_piece.isBlack()) { | |
System.out.println("White tried to steal its own piece"); | |
writeIllegalAtIndex(fout, moves, i); | |
legal = false; | |
break; | |
} else { | |
System.out.println("Steals piece " + blocked_piece); | |
// delete piece which was stolen, | |
pieces.deletePieceAt(blocked_piece.pos); | |
} | |
} | |
else { | |
System.out.println("Blocked by " + blocked_piece); | |
writeIllegalAtIndex(fout, moves, i); | |
legal = false; | |
break; | |
} | |
blocked_piece = null; | |
} | |
} while (!(temp_pos.x == end_pos.x && temp_pos.y == end_pos.y)); | |
} | |
// second break for outer loop, if a blocked_piece was discovered. | |
if(!legal) { | |
System.out.println("breaker, breaker!"); | |
break; | |
} | |
// delete moved piece at original location | |
pieces.deletePieceAt(piece_for_move.pos); | |
// and insert at new location | |
pieces.push(piece_for_move.kind, end_pos.x, end_pos.y); | |
System.out.println(piece_for_move + " moves to " + pieces.pieceAt(new Position(end_pos.x, end_pos.y))); | |
// save reference to the last piece that we moved, we want to check | |
// that we are honoring black-white transition in next loop iteration. | |
last_moved_piece = piece_for_move; | |
} | |
if(legal) { | |
System.out.println("All moves legal."); | |
fout.write("legal\n"); | |
} else { | |
System.out.println("One or moves were not legal."); | |
} | |
} | |
System.out.println("----------------------------------"); | |
System.out.println("All moves analyzed satisfactorily."); | |
System.out.println("----------------------------------"); | |
fout.close(); | |
} | |
static void writeIllegalAtIndex(Writer output, int[] moves, int idx) throws IOException { | |
// build simple string of 'illegal' move | |
String illegal = moves[idx] + " " + moves[idx+1] + " " + moves[idx+2] + " " + moves[idx+3] + " illegal\n"; | |
// write to screen | |
System.out.print(illegal); | |
// write to output file | |
output.write(illegal); | |
} | |
public static int[] StringArrayToInt(String[] string_array) { | |
// Convert array of Strings of numbers to an array of integers. | |
int[] result = new int[string_array.length]; | |
for (int i = 0; i < string_array.length; i++) | |
{ | |
result[i] = Integer.parseInt(string_array[i]); | |
} | |
return result; | |
} | |
public static ChessPieces parsePiecesStringArray(String[] pieces){ | |
ChessPieces result = new ChessPieces(); | |
for(int i=0; i<pieces.length; i+=3) | |
{ | |
// The next two items are the (X,Y) locations | |
String kind = pieces[i]; | |
int xpos = Integer.parseInt(pieces[i+1]); | |
int ypos = Integer.parseInt(pieces[i+2]); | |
// add chess piece to linked list | |
result.push(kind, xpos, ypos); | |
} | |
return result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment