I am a beginner android "developer" developing a chess app.
There is one variable in the InGameActivity class called currentBoardState which is public static. Every ChessPiece has a boolean[][] possibleMoves. This following method will take the possibleMoves and determine if any of the moves will cause the player to put him/herself in check and set it to false because it is no longer a possible move.
#Override
public void eliminateMovesThatPutYouInCheck() {
ChessPiece[][] originalBoard = InGameActivity.currentBoardState;
final ChessPiece emptyPiece = new EmptyPiece(Color.EMPTY);
final ChessPiece tempKnight = new Knight(side);
//This block eliminates moves that will cause a player
//to put him/her self in check.
InGameActivity.currentBoardState[x][y] = emptyPiece;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (possibleMoves[i][j] == true) {
tempKnight.x = i;
tempKnight.y = j;
InGameActivity.currentBoardState[i][j] = tempKnight;
if (InGameActivity.isPlayerInCheck(side)) {
possibleMoves[i][j] = false;
}
InGameActivity.currentBoardState[i][j] = emptyPiece;
}
}
}
InGameActivity.currentBoardState = originalBoard;
}
The problem is, my currentBoardState variable is being messed up and I dont know why, ive saved the value then reset it at the end of the method why is it losing its values?
EDIT: Here is the isPlayerInCheck method if you need it, thank you.
public static boolean isPlayerInCheck(Color side) {
List<boolean[][]> opponentsMoves = new ArrayList<boolean[][]>();
int xKing = -1;
int yKing = -1;
if (side.equals(Color.WHITE)) {
xKing = whiteKing.x;
yKing = whiteKing.y;
} else {
xKing = blackKing.x;
yKing = blackKing.y;
}
if (side.equals(Color.WHITE)) {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (currentBoardState[i][j].isBlack()) {
opponentsMoves.add(currentBoardState[i][j].possibleMoves);
}
}
}
for (boolean[][] b : opponentsMoves) {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (b[xKing][yKing] == true) {
return true;
}
}
}
}
return false;
} else {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (currentBoardState[i][j].isWhite()) {
opponentsMoves.add(currentBoardState[i][j].possibleMoves);
}
if (currentBoardState[i][j].isBlack() && currentBoardState[i][j].getType().equals(Type.KING)) {
xKing = currentBoardState[i][j].x;
yKing = currentBoardState[i][j].y;
}
}
}
for (boolean[][] b : opponentsMoves) {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (b[xKing][yKing] == true) {
return true;
}
}
}
}
return false;
}
}
Also, I understand and appreciate that my code is probably very inefficient and the design is horrible for chess but that isn't really what I am concerned about at the moment.
I'm assuming by messed up you mean the currentBoardState variable isn't being "reset" to the original board.
This is due to this line:
ChessPiece[][] originalBoard = InGameActivity.currentBoardState;
passing a reference of the current board state to the variable originalBoard.
As you make you modification to currentBoardState, since the originalBoard variable points to the same object, it gets modified as well.
Copy the array to the originalBoard variable like such:
ChessPiece[][] originalBoard = new ChessPiece[InGameActivity.currentBoardState.length][];
for(int i = 0; i < InGameActivity.currentBoardState.length; i++){
ChessPiece[] pieces = InGameActivity.currentBoardState[i];
int len = pieces.length;
originalBoard[i] = new ChessPiece[len];
System.arraycopy(pieces, 0, originalBoard[i], 0, len);
}
//Rest of code here...
Only when you copy by value does a actual copy of the data exist. Disregarding primitive types and some immutable data, using the assignment operator = merely assigns the reference of the RHS to the LHS.
If I understand your code correctly, I think you need to copy the original to a new array, for example:
ChessPiece[][] originalBoard = Arrays.copyOf(
InGameActivity.currentBoardState, InGameActivity.currentBoardState.length);
This prevents modification of the original array.
You have the problem here:
if (possibleMoves[i][j])
{
tempKnight.x = i;
tempKnight.y = j;
InGameActivity.currentBoardState[i][j] = tempKnight;
if (InGameActivity.isPlayerInCheck(side))
{
possibleMoves[i][j] = false;
}
/** whatever was before next line resets the value at i,j: puts empty piece here */
InGameActivity.currentBoardState[i][j] = emptyPiece;
}
Related
For a project I am working on I would like to be abbe to "scroll" an array like so:
Here is the code I have so far:
private boolean[][] display = this.parseTo8BitMatrix("Here");
private int scroll = 0;
public void scroll() {
this.scroll++;
}
//sets the clock's display
public void setDisplay(String s) {
this.display = this.parseTo8BitMatrix(s);
}
//determines the current frame of the clock
private boolean[][] currentFrame() {
boolean[][] currentFrame = new boolean[8][32];
int length = this.display[0].length;
if(length == 32) { //do nothing
currentFrame = this.display;
} else if(length <= 24) { //center
for(int i = 0; i < 8; i++) {
for(int j = 0; j < length; j++) {
currentFrame[i][j+((32-length)/2)] = this.display[i][j];
}
}
this.display = currentFrame; //set display to currentFrame so the display doesn't get centered each time
} else { //scroll
for(int i = 0; i < 8; i++) {
for(int j = 0; j < length; j++) {
if(this.scroll+j <= 32) {
currentFrame[i][j] = this.display[i][j+this.scroll];
} else {
//?
}
}
}
}
return currentFrame;
}
The code I have is effective up until the the array needs to "wrap around" to the other side. Where have I gone wrong?
I'm assuming that you're looking for a formula that would work for the else.
Usually Modulos are very helpful for wrapping around.
What you are looking for is basically
currentFrame[i][j]= this.display[i][(j+this.scroll)%length];
which works even when it's not wrapped around.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
I'm having trouble with a java problem. I get this error:
Exception in thread "main" java.lang.NullPointerException
at DoubleMatrix.getDim1Size(DoubleMatrix.java:28)
at Program3.main(Program3.java:16)
I don't understand where it is null
public class DoubleMatrix
{
private double[][] doubMatrix;
public DoubleMatrix(int firstDim, int secondDim, double upperLimit)
{
if(firstDim > 0 && secondDim > 0 && upperLimit > 0){
firstDim = 1;
secondDim = 1;
upperLimit = 1;
}
}
public DoubleMatrix(double[][] tempArray)
{
if(tempArray != null && tempArray.length != 0){
for(int i =0; i < tempArray.length; i++) {
doubMatrix = tempArray;
}
}
else{
tempArray = new double[1][1];
}
}
public int getDim1Size(){
int firstDim1 = doubMatrix.length;
return firstDim1;
}
public int getDim2Size(){
int secondDim1 = doubMatrix[0].length;
return secondDim1;
}
private void makeDoubMatrix(int firstDim, int secondDim, double upperLimit){
double[][] randomMatrix = new double[firstDim][secondDim];
for(int row = 0; row < doubMatrix.length; row++) {
for(int column = 0; column < doubMatrix[row].length; column++){
doubMatrix[row][column] = (double)(Math.random() * 100);
}
}
}
public DoubleMatrix addMatrix(DoubleMatrix arrayObj)
{
if(doubMatrix.length == arrayObj.doubMatrix.length && doubMatrix[0].length == arrayObj.doubMatrix[0].length){
double[][] TotalTwoDimArray = new double[doubMatrix.length][doubMatrix[0].length];
for(int row = 0; row < TotalTwoDimArray.length; row++){
for(int column = 0; column < TotalTwoDimArray[row].length; column++){
TotalTwoDimArray[row][column] = doubMatrix[row][column] + arrayObj.doubMatrix[row][column];
}
}
return new DoubleMatrix(TotalTwoDimArray);
}
return new DoubleMatrix(1, 1, 1);
}
public DoubleMatrix getTransposedMatrix(){
double[][] TransMatrix = new double[doubMatrix[0].length][doubMatrix.length];
for(int row = 0; row < doubMatrix.length; row++){
for(int column = 0; column < doubMatrix[row].length; column++){
TransMatrix[row][column] = doubMatrix[column][row];
}
}
return new DoubleMatrix(TransMatrix);
}
public DoubleMatrix multiplyMatrix(DoubleMatrix obj1)
{
if(doubMatrix[0].length == obj1.doubMatrix.length){
double[][] multipliedMatrix = new double[doubMatrix.length][obj1.doubMatrix[0].length];
for(int i = 0; i < multipliedMatrix.length; i++){
for(int j = 0; j < multipliedMatrix[i].length; j++){
for(int k = 0; k < doubMatrix[0].length; k++){
multipliedMatrix[i][j] = doubMatrix[i][k] * obj1.doubMatrix[k][j] + multipliedMatrix[i][j];
}
}
}
return new DoubleMatrix(multipliedMatrix);
}
return new DoubleMatrix(1, 1, 1);
}
public void printMatrix(String titles){
System.out.println(titles);
for(int row = 0; row < doubMatrix.length; row++){
for(int column = 0; column < doubMatrix[row].length; column++){
System.out.printf("%9.1f", doubMatrix[row][column]);
}
System.out.println();
}
}
}
// main in different class
public class Program3
{
public static void main(String[] args)
{
DoubleMatrix doubMatObj1;
DoubleMatrix doubMatObj2;
DoubleMatrix doubMatObj3;
int max = 10;
int min = 3;
int firstDim = (int)(Math.random() * (max - min + 1) + min);
int secondDim = (int)(Math.random() * (max - min + 1) + min);
doubMatObj1 = new DoubleMatrix(firstDim, secondDim, 100.);
doubMatObj2 = new DoubleMatrix(doubMatObj1.getDim1Size(), doubMatObj1.getDim2Size(), 100.);
doubMatObj3 = doubMatObj1.addMatrix(doubMatObj2);
doubMatObj1.printMatrix("First Matrix Object");
doubMatObj2.printMatrix("Second Matrix Object");
doubMatObj3.printMatrix("Result of Adding Matrix Objects");
doubMatObj2.printMatrix("Result of Transposing Matrix Object");
doubMatObj1.multiplyMatrix(doubMatObj2);
doubMatObj3.printMatrix("Result of Multiplying Matrix Objects");
}
}
In java, non primitives don't get initialized by just declaring them. So if you get a NullPointerException in a line like foo.bar(), you know that foo had to be null. In your case you have doubMatrix.length, which indicates that doubMatrix has never been initialized. Looking at your code, only the second constructor ever initializes that variable, so calling the first constructor will leave doubMatrix==null to always be true.
I hope that is enough info to help you fix your problem yourself (and similar problems in the future), but I am not going to post a working code example, since fixing your code yourself will be a good exercise!
On a sidenote, in your second constructor you have:
for(int i =0; i < tempArray.length; i++) {
doubMatrix = tempArray;
}
If tempArray.length is for example 5, you would assign the same value 5 times to the same variable. I don't know what you are trying to do there, but it is certainly not what you had in mind.
I'm implementing Insertionsort for university. My code works in theory, but my for-loop is executed only once instead of books.size() (which is 5, I've tested that). I tried it using the number 5, but it won't work and I'm kind of desperate because I can't seem to find the error.
Here is my code:
static void sort(LinkedList<Book> books)
{
int i;
for ( i = 0; i < books.size(); i++)
{
Book temp = books.get(i);
books.remove(i);
for (int j = 0; j < books.size(); j++) {
if (books.get(j).compareTo(temp) > 0) {
books.add(j, temp);
return;
}
}
books.add(temp);
}
}
The compareTo function of the Book-Class looks like the following:
public int compareTo(Book other)
{
int iAutor = autor.compareTo(other.getAutor());
if (iAutor != 0)
return iAutor;
else
{
int iTitel = titel.compareTo(other.getTitel());
if (iTitel != 0)
return iTitel;
else
{
if (this.auflage < other.getAuflage())
return -1;
else if (this.auflage > other.getAuflage())
return 1;
else
return 0;
}
}
}
Am I simply blind?
You need to swap return for break and fix the logic to avoid adding the book twice. There may be more elegant ways than this, but it should work:
int i;
for ( i = 0; i < books.size(); i++)
{
Book temp = books.get(i);
books.remove(i);
bool added = false;
for (int j = 0; j < books.size(); j++) {
if (books.get(j).compareTo(temp) > 0) {
books.add(j, temp);
added = true;
break;
}
}
if (!added) {
books.add(temp);
}
}
Well, I found out how to solve it, just if someone has the same problem (don't think that will happen, but it's a good habit I hope).
As #Klitos Kyriacou pointed out right, I had a twist in my thoughts about the process of Insertionsorting.
The solution is changing the loops in the following:
static void sort(LinkedList<Book> books) {
Book temp;
for (int counter = 0; counter < books.size(); counter++) {
temp = books.get(counter);
for (int position = 0; position < counter; position++)
{
if (temp.compareTo(books.get(position)) < 0)
{
books.remove(counter);
books.add(position, temp);
break;
}
}
}
}
Okay so, I added saving into my game (through serialization), which works completely fine, but these items have things like sprites and stuff that I logically wouldn't save, how I got around that was pretty simple.
I made a method in my Item class (every item extends it) that assigns everything it needs to (called basicInitialization()). This works great!
However, I noticed that any code placed after the loading of items wouldn't run. I investigated and realized I was stuck in an infinite for-loop:
public void loadItems(Player p) {
Item[] temp = SaveGame.loadItems();
for (int i = 0; i < items.length; i++) {
this.removeByIndex(i);
}
for (int j = 0; j < temp.length; j++) {
items[j] = temp[j];
}
for (int t = 0; t < items.length; t++) {
if (items[t] == null) {
t += 1;
}
items[t].basicInitialization();
if (items[t] instanceof EquipableItem) {
items[t].basicInitialization(((EquipableItem)items[t]).slot);
}
}
}
When I removed the:
items[t].basicInitialization();
if (items[t] instanceof EquipableItem) {
items[t].basicInitialization(((EquipableItem)temp[t]).slot);
}
portion and the problem went away.
Am I missing something really obvious here?
Thanks for any help you can give, if anymore code is needed I will happily give it!
Edit:
- Re-structured some code
Here is an example of basicInitialization:
public void basicInitialization() {
this.sprite = Sprite.HealthPotion;
this.name = "Health Potion";
this.value = "25";
this.desc = "Heals Up to 5 HP";
level = Game.getGame().getLevel();
}
You should have the code inside first for loop as :
int j = 0;
if (temp[i] == null) { //If there is no item then continue to the next one
i+= 1
}
else{
items[j] = temp[i];
j++;
}
If the next item is null, then it would get assigned without the else block.
I think I've finally fixed it, thanks for all the help! It was definitely a tough nut to crack!
public void loadItems(Player p) {
Item[] temp = SaveGame.loadItems();
for (int i = 0; i < items.length; i++) {
this.removeByIndex(i); // Remove all current items
}
if (this.lastItemInList(temp) == -1) { // If the loaded item list has no items
return;
}
for (int j = 0; j < temp.length; j++) {
items[j] = temp[j];items
}
for (int t = 0; t < items.length; t++) {
if (items[t] == null) {
if (t != items.length) {
for (int i = t; i < items.length; i++) {
if (items[i] != null) {
t = i; //Gets the next time there is an item that isn't null
break;
}
}
}
}
items[t].basicInitialization();
if (items[t] instanceof EquipableItem) {
items[t].basicInitialization(((EquipableItem)items[t]).slot);
}
if (t == this.lastItemInList(items)) { //Once it hits the last item, then return
System.out.println(":::FULLY LOADED ITEMS >> RETURNING:::");
return;
}
}
}
Hey all, back again. Working on a dungeon generator and I'm actually surprising myself with the progress. Yet I still have a straggling room every now and then. I was wondering if there was a way to loop through an array and see if all the '1s' (the floor tiles) are connected, and if not, how to connect them.
Thanks!
EDIT: The array is randomly filled with rooms and corridors; here's the code:
import java.util.Random;
public class Level
{
Random random = new Random();
int[][] A = new int[100][100];
int minimum = 3;
int maximum = 7;
int xFeature = 0;
int yFeature = 0;
private void feature()
{
int i = 0;
while(i>=0)
{
xFeature = random.nextInt(100-1) + 1;
yFeature = random.nextInt(100-1) + 1;
if(A[xFeature][yFeature]==1)//||A[xFeature++][yFeature]==1||A[xFeature][yFeature--]==1||A[xFeature][yFeature++]==1)
break;
i++;
}
}
private void room()
{
int safeFall = 0;
int xCoPLUS = minimum + (int)(Math.random()*minimum);
int yCoPLUS = minimum + (int)(Math.random()*minimum);
if(yCoPLUS >= xCoPLUS)
{
for(int across = xFeature; across < xFeature+xCoPLUS+2; across++)
{
for(int vert = yFeature; vert < yFeature+yCoPLUS+1; vert++)
{
if(A[vert][across] == 0)
safeFall++;
else
break;
}
}
}
if(yCoPLUS < xCoPLUS)
{
for(int across = xFeature; across < xFeature+xCoPLUS+1; across++)
{
for(int vert = yFeature; vert < yFeature+yCoPLUS+2; vert++)
{
if(A[vert][across] == 0)
safeFall++;
else
break;
}
}
}
if((safeFall== (xCoPLUS+1) * (yCoPLUS+2)) || ((safeFall== (xCoPLUS+2) * (yCoPLUS+1))))
{
for(int across = xFeature; across < xFeature+xCoPLUS; across++)
{
for(int vert = yFeature; vert < yFeature+yCoPLUS; vert++)
{
A[vert][across] = 1;
}
}
}
}
private void corridor()
{
int xCoONE = xFeature;
int yCoONE = yFeature;
int xCoTWO = random.nextInt(10)+10;
int yCoTWO = random.nextInt(10)+10;
while(xCoONE > xCoTWO)
{
A[xCoONE][yCoONE] = 1;
xCoONE--;
}
while(xCoONE < xCoTWO)
{
A[xCoONE][yCoONE] = 1;
xCoONE++;
}
while(yCoONE > yCoTWO)
{
A[xCoONE][yCoONE] = 1;
yCoONE--;
}
while(yCoONE < yCoTWO)
{
A[xCoONE][yCoONE] = 1;
yCoONE++;
}
}
public Level()
{
firstroom();
for(int i = 0; i < 500; i++)
{
int x = random.nextInt(50);
feature();
if(x > 1)
room();
else
corridor();
}
troubleShoot();
}
So basically what happens when I create an object of this class is that a 100x100 array is filled with corridors and rooms determined by a random number. (well, a couple of them) But with how I have my room non-overlapping failsafe (safeFall in room()), I get stuck with a room that is one title out of reach every now and then.
The article Maze Generation Algorithm discusses several approaches to generating a maze. It includes links to Java examples.