Skip to content

Instantly share code, notes, and snippets.

@jquast
Created September 2, 2023 17:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jquast/4e9d6fc6f8bfa696f2e8830a7bccb5c8 to your computer and use it in GitHub Desktop.
Save jquast/4e9d6fc6f8bfa696f2e8830a7bccb5c8 to your computer and use it in GitHub Desktop.
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