How to code the chess stalemate rule ? - chess

I'm trying to write a chess game and find that I cannot find solutions to find a stalemate situation. I'm trying to google, but can't find anything. Is there a well-known algorithm or something?

Your move generator will be one of two different designs;
either it checks for legality while generating the moves
or you generate all possible moves and remove those that are illegal afterwards.
The former is better as it doesn't need post-processing.
A stalemate condition is simply one where there are no legal moves and the moving-side's king is not in check. A checkmate condition is one where there are no legal moves but the moving-side's king is in check.
In other words if you've figured out how to detect check and checkmate, you've already got everything necessary to detect stalemate.

Here is an Open-source code with all the rules for the classic Chess game:
https://github.com/cjortegon/basic-chess
You can run the project right after cloning the project (Android, iOS, Desktop and Web), or you can use the main logic, which is here: https://github.com/cjortegon/basic-chess/tree/master/libgdx/core/src/com/mountainreacher/chess/model
I based my solution on a 3-moments algorithm, first moment is when the player selects a piece from the board, then when the destination of this piece has been chosen and finally when the piece reaches that position (considering that it is an animated game, if not, you can merge step 2 and 3).
The following code has been implemented in Java. From the properties of the model class:
boolean turn;
GenericPiece selected, conquest;
ClassicBoard board;
List<int[]> possibleMovements;
int checkType;
The first method will handle moments 1, 2 and the special 'conquest' moment (applied to pawn piece only):
public boolean onCellClick(int row, int column) {
if (row == -1 && conquest != null) {
checkType = 0;
conquest.changeFigure(column);
return true;
} else if (selected != null) {
if (possibleMovements != null) {
for (int[] move : possibleMovements) {
if (move[0] == row && move[1] == column) {
// Move the PieceActor to the desired position
if (selected.moveTo(row, column)) {
turn = !turn;
}
break;
}
}
}
selected = null;
possibleMovements = null;
return true;
} else {
selected = board.getSelected(turn ? Piece.WHITE_TEAM : Piece.BLACK_TEAM, row, column);
if (selected != null) {
possibleMovements = new ArrayList<>();
possibleMovements.addAll(((GenericPiece) selected).getMoves(board, false));
// Checking the movements
board.checkPossibleMovements(selected, possibleMovements);
if (possibleMovements.size() == 0) {
possibleMovements = null;
selected = null;
return false;
} else {
return true;
}
}
}
return false;
}
And the following method will handle the 3rd moment (when animation finishes):
public void movedPiece(Piece piece) {
Gdx.app.log(TAG, "movedPiece(" + piece.getType() + ")");
// Killing the enemy
Piece killed = board.getSelectedNotInTeam(piece.getTeam(),
piece.getRow(), piece.getColumn());
if (killed != null) {
killed.setAvailable(false);
}
// Checking hacks
GenericPiece[] threat = board.kingIsInDanger();
if (threat != null) {
checkType = board.hasAvailableMoves(threat[0].getTeam()) ? CHECK : CHECK_MATE;
} else {
checkType = NO_CHECK;
}
// Checking castling
if (piece.getFigure() == Piece.ROOK && ((GenericPiece) piece).getMovesCount() == 1) {
Piece king = board.getSelected(piece.getTeam(),
piece.getRow(), piece.getColumn() + 1);
if (king != null && king.getFigure() == Piece.KING && ((GenericPiece) king).getMovesCount() == 0) {
// Left Rook
if (board.getSelected(piece.getRow(), piece.getColumn() - 1) == null) {
king.moveTo(piece.getRow(), piece.getColumn() - 1);
}
} else {
king = board.getSelected(piece.getTeam(),
piece.getRow(), piece.getColumn() - 1);
if (king != null && king.getFigure() == Piece.KING && ((GenericPiece) king).getMovesCount() == 0) {
// Right Rook
if (board.getSelected(piece.getRow(), piece.getColumn() + 1) == null) {
king.moveTo(piece.getRow(), piece.getColumn() + 1);
}
}
}
}
// Conquest
else if (piece.getFigure() == Piece.PAWN && (piece.getRow() == 0 || piece.getRow() == board.getRows() - 1)) {
conquest = (GenericPiece) piece;
checkType = CONQUEST;
}
}
That code covers all the rules from the classic chess, including: regular piece movements, castling, check, check-mate and conquests of pawns.

Related

Conditional statement in getter method

Am relatively new to java so I have no idea what the problem is. In my getter settings of this class, I'm trying to evaluate if the input is of integer 1, 2 or 3, then it will return one of the previously saved setters described here. I used the same conditional statements in the setter, but the getter tells me that my method needs to return type int. What am I doing wrong? Or should I be doing this a completely different way? lol.
public class AssignmentMarks {
private String courseName;
private int assignment1 = 0, assignment2 = 0, assignment3 = 0;
public AssignmentMarks(String name, int mark1, int mark2, int mark3){
//create constructor to use variables.
this.courseName = name;
this.assignment1 = mark1;
this.assignment2 = mark2;
this.assignment3 = mark3;
}
public void setMark(int assignmentNumber, int mark) {
//assign value of the assignments
if(assignmentNumber == 1) {
mark = this.assignment1;
}else if(assignmentNumber == 2) {
mark = this.assignment2;
}else if(assignmentNumber == 3){
mark = this.assignment3;
}
}
public int getMark(int assignmentNum) {
if(assignmentNum == 1) {
return assignment1;
}else if (assignmentNum == 2) {
return assignment2;
} else if (assignmentNum == 3) {
return assignment3;
}
}
}
public int getMark(int assignmentNum) {
if(assignmentNum == 1) {
return assignment1;
}else if (assignmentNum == 2) {
return assignment2;
} else if (assignmentNum == 3) {
return assignment3;
}
// in another case
throw new Exception("Assignment must be 1, 2 or 3);
}
for setter
public void setMark(int assignmentNumber, int mark) {
//assign value of the assignments
if(assignmentNumber == 1) {
// BAD mark = this.assignment1; don't set parameter is useless
this.assignment1=mark;
}else if(assignmentNumber == 2) {
// BAD mark = this.assignment2;
this.assignment2=mark;
}else if(assignmentNumber == 3){
// BAD mark = this.assignment3;
this.assignment3=mark;
}
// in another case
throw new Exception("Assignment must be 1, 2 or 3");
}
I don't remember if you must import Exception for throwing them.
if yes put import java.lang.Exception on top of your code.
your logic can be improved using arrays, but let's walk, and after you will running...

removing last node linked list in objective -c

I am trying to implement a removeLast function for a linked list in objective-c. My add function property works well because I can see the node I created, but when I try to remove a node it does not work. I have tried looking up general solutions for this, but have not come up with anything. Is there something special with objective-c that I should take a look at?
-(void) removeLast{
Node *newNode = [[Node alloc]init];
Node *tail = [[Node alloc]init];
if (self.head == NULL){
NSLog(#"No items to remove");
}
else{
newNode = self.head;
tail= self.head;
while (tail != NULL) {
tail = tail.next;
if (tail != NULL){
newNode = tail;
}
}
newNode.next = NULL;
}
}
I believe you've overcomplicated the algorithm. You don't need to keep a reference to the previous link if you always look one step ahead:
- (void) removeLast {
if (self.head == NULL) {
NSLog(#"Empty list");
} else if (self.head.next == NULL) {
self.head = NULL;
} else {
Node* current = self.head;
while (current.next.next != NULL)
current = current.next;
current.next = NULL;
}
}
This iterates through until it reaches the next-to-last node when current.next.next will be null. Then it makes that the last node.

Point.Empty.Equals(Point.Empty) == false // why?

Using NetTopologySuite, these expressions are false:
Point.Empty.Equals(Point.Empty); // false
Polygon.Empty.Equals(Polygon.Empty); // false
Debugging shows that this behavior is implemented by
// Geometry
public IntersectionMatrix Relate(IGeometry g)
{
return RelateOp.Relate(this, g); // Point.Empty, Point.Empty
}
// IntersectionMatrix
public bool IsEquals(Dimension dimensionOfGeometryA, Dimension dimensionOfGeometryB)
{
if (dimensionOfGeometryA != dimensionOfGeometryB)
return false;
return IsTrue(_matrix[(int)Location.Interior, (int)Location.Interior]) &&
_matrix[(int)Location.Interior, (int)Location.Exterior] == Dimension.False &&
_matrix[(int)Location.Boundary, (int)Location.Exterior] == Dimension.False &&
_matrix[(int)Location.Exterior, (int)Location.Interior] == Dimension.False &&
_matrix[(int)Location.Exterior, (int)Location.Boundary] == Dimension.False;
}
I wonder what the reason behind this is. Presumably this behavior occurs in related libraries (jts, GEOS) as well and I also assume there is a justification known by geo-algebra insiders. Can someone explain?

I am getting an error (variable y might not have been initialised in the if's in the loop. How to solve that?

import java.util.Scanner;
public class RPS
{
public void show()
{
int i;
System.out.println("1 - Rock 2 - Paper 3 - Scissor");
Scanner in = new Scanner(System.in);
i = in.nextInt();
double x = Math.random();
int y;
if(x<=0.33)
{
y=1;
}
else if(x>0.33 && x<0.67)
{
y=2;
}
else if(x>=0.67)
{
y=3;
}
for(;;)
{
if(i==y)
System.out.println("It's a draw!");
else if(i==1 && y==2)
System.out.println("Computer wins!");
else if(i==1 && y==3)
System.out.println("You win!");
else if(i==2 && y==1)
System.out.println("You win!");
else if(i==2 && y==3)
System.out.println("Computer wins!");
else if(i==3 && y==1)
System.out.println("Computer wins!");
else if(i==3 && y==2)
System.out.println("You win!");
else
System.out.println("Error!");
}
}
}
Whats wrong?
It gives an error that variable y might not have been intialised in the if's in the for loop.
I have assigned a value to y in the previous if-else section.
so why isnt it getting intialised?
javac is not smart enough to realize that the way your conditions are constructed, one of them will always be true.
You can rewrite your if-statements to make javac realize one branch will always be triggered:
int y;
if(x<=0.33)
{
y=1;
}
else if(x>0.33 && x<0.67)
{
y=2;
}
else // This only triggers when x >= 0.67, so no need to check
{
y=3;
}
Now javac sees that if the first two don't trigger, the last will, so y will always have a value.
You can alternatively add an else branch with an error, in case someone breaks the conditions:
int y;
if(x<=0.33)
{
y=1;
}
else if(x>0.33 && x<0.67)
{
y=2;
}
else if(x >= 0.67)
{
y=3;
}
else
{
// This should never happen
throw new IllegalArgumentException("Something's gone terribly wrong for " + x);
}
This also compiles, and if someone later decides to skew the numbers and turns the first condition into x <= 0.2 but forgets to update the other condition, you'll get an exception at runtime.

number changed automatically to the string

I am trying to read Excel file through apache poi. In a column I am having the data `"9780547692289". After iterating all the columns, in the output, the number is displaying like this "9.780547692289E12". I mean number changed automatically to the string(because it has'E'). I have to keep this as number only(as it is). What should I do..?
It is probably just a display setting. The "E" is just for scientific notation for displaying the number.
//while getting values from excel u can use this method
private String getCellValue(Cell cell) {
if (cell == null) {
return null;
}
if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
return cell.getStringCellValue();
} else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
return cell.getNumericCellValue() + "";
} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
return cell.getBooleanCellValue() + "";
}else if(cell.getCellType() == Cell.CELL_TYPE_BLANK){
return cell.getStringCellValue();
}else if(cell.getCellType() == Cell.CELL_TYPE_ERROR){
return cell.getErrorCellValue() + "";
}
else {
return null;
}
}
This worked for me
if (cell.getCellType()==Cell.CELL_TYPE_NUMERIC || cell.getCellType()==Cell.CELL_TYPE_FORMULA )
{
int i = (int)cell.getNumericCellValue();
String cellText = String.valueOf(i);
}