Space Invader project - java

Hi I have been working on a space invader game in processing, I am relatively new to java/coding. What my problem is that I do not really understand how to make the collision actually work, and also my aliens (which are the space ships), they move left to right but do not move down. These are the 2 major problems that I am having a hard time solving. This is my code underneath, any professional advice would be appreciated.
PImage SpaceShip;
PImage Laser;
int TankX = 450;
int TankY = 450;
int SpaceshipX = 20;
int SpaceshipY = 20;
int MoveSpaceShipDown = 5;
int TankSizeX = 200;
int TankSizeY = 90;
int ShipSizeX = 90;
int ShipSizeY = 80;
int Xtankspeed = 2;
int LaserX = 9999;
int LaserY = TankY;
int LasersizeX = 10;
int LasersizeY = 40;
int spaceShipDirection = 5;
int spaceshipxspeed = 2;
int spaceshipSpeed = 5;
//int Xtankspeed2 = -6;
boolean moveRight = false;
boolean moveLeft = false;
boolean ShowLaser = false;
int[] ShipX = new int [15];
int [] ShipY = new int [4];
int gameState = 1;
int StopWatch = 0;
void setup() {
size(1000, 500);
imageMode(CENTER);
SpaceShip = loadImage("Spaceship.png");
SpaceShip.resize( ShipSizeX, ShipSizeY );
Laser = loadImage ("LaserBeam.png");
Laser.resize(LasersizeX, LasersizeY);
Tank = loadImage("Tank.png");
Tank.resize(TankSizeX, TankSizeY);
setSpaceShipPositions();
}
void setSpaceShipPositions() {
for(int j = 0; j < ShipY.length; j++){
for (int i = 0; i < ShipX.length; i++) {
ShipX[i] = 50 + 50*i;
}
ShipY[j] = 50 + 50*j;
}
}
void draw() {
if (gameState == 1) {
IntroScreen();
} else if (gameState == 2) {
startGame();
}
}
void IntroScreen() {
background(#000000);
textMode(CENTER);
textSize(50);
text("Space Defenders", 325, 250);
}
void startGame() {
background (#2f3069);
MakeLaser();
Maketank();
Maketankmove();
checkiftankhitedge();
for (int j = 0; j < ShipY.length; j++) {
for (int i = 0; i < ShipX.length; i++) {
MakeSpaceShip(i,j);
moveSpaceShip();
checkiflaserhitspaceship(i,j);
}
}
Shootlaser();
Makelaserreturentoorignalposition();
//makespaceshipgodown();
}
void keyPressed() {
println(keyCode);
if (keyCode == 39) { //right key
moveRight = true;
}
if (keyCode == 37) { //leftkey
moveLeft = true;
}
if (keyCode == 32 && ShowLaser == false) { //Spacebar
ShowLaser = true;
LaserX = TankX;
LaserY = TankY;
}
if (keyCode == 10) {
gameState = 2;
}
}
void keyReleased() {
if (keyCode == 39) { //right key
moveRight = false;
}
if (keyCode == 37) { //leftkey
moveLeft = false;
}
if (keyCode == 32) { //Spacebar
}
}
void Maketank() {// this is to make the tank
//PImage.resize(0,5);
imageMode(CENTER);
image(Tank, TankX, TankY);
}
void MakeLaser() {
if (ShowLaser) {
image(Laser, LaserX, LaserY);
}
}
void MakeSpaceShip(int i, int j) {
image(SpaceShip, ShipX[i], ShipY[j]);
//for (int i = 0; i < spaceShipX.length; i++){
// image( spaceShipX[i] - 15, ,SpaceshipX, SpaceshipY ); Confused
}
int lastlaptime = 0;
int timesincelastlap = 0;
//void moveSpaceShip(int i, int j) {
/*StopWatch = millis();
timesincelastlap = StopWatch - lastlaptime;
if (timesincelastlap > 500) {
spaceShipX[i] += spaceshipxspeed;
lastlaptime = millis();
// if (spaceShipX[i] > 990) {
// SpaceshipY = SpaceshipY + 30;
//spaceShipDirection = -1*spaceShipDirection;
// }
//if (spaceShipX[i] < 10) {
// SpaceshipY = SpaceshipY + 30;
//spaceShipDirection = -1*spaceShipDirection;
//}
//}
}*/
void moveSpaceShip() {
/*for (int i = 0; i < 15; i++){
if (spaceShipX[40] > 990){
spaceShipDirection = -1*spaceShipDirection;
SpaceshipY = SpaceshipY + 30;
}
if (spaceShipX[1] < 10){
spaceShipDirection = -1*spaceShipDirection;
SpaceshipY = SpaceshipY + 30;
}
}
for (int i = 0; i < 15; i++){
spaceShipX[i] = spaceShipX[i] + spaceShipDirection;
}*/
if (millis() - StopWatch > 1000) {
StopWatch = millis();
checkIfHitEdge();
moveShips();
}
}
void moveShips() {
for (int i = 0; i < 15; i++) {
ShipX[i] = ShipX[i] + spaceShipDirection*spaceshipSpeed;
}
}
void checkIfHitEdge() {
for (int i = 0; i < 15; i++) {
if (ShipX[14] > 990) {
SpaceshipY = SpaceshipY + 5;
spaceShipDirection = -1*spaceShipDirection;
}
if (ShipX[0] < 10) {
spaceShipDirection = -1*spaceShipDirection;
SpaceshipY = SpaceshipY + 5;
}
}
}
//void makespaceshipgodown(){
// if(SpaceshipX + 45 > width){
//SpaceshipY++;
// }
//}
void Maketankmove() {
if (moveLeft == true) {
TankX--; //this makes the tank go left
TankX = TankX - Xtankspeed;//this is for the speed of the tank
}
if (moveRight == true) {
TankX++;//this makes the tank go right
TankX = TankX + Xtankspeed;//the speed of the tank
}
}
void checkiftankhitedge() {
if (TankX > width-50) {
TankX = 950;
moveRight = false;
}
if (TankX-100 < -50) {
TankX = 50;
moveLeft = false;
}
}
void Makelaserreturentoorignalposition() {
//if(TankX++){
if (LaserY == 0) {
LaserY = TankY;
LaserX = 9999;
ShowLaser = false;
}
}
void checkiflaserhitspaceship(int i, int j) {
/* int Lasertop = LasersizeY - 20;
int Laserbottom = LasersizeY + 20;
int LaserLeft= LasersizeX - 5;
int LaserRight = LasersizeX +5;
int SpaceShipBottom = ShipY[j] - 40;
int SpaceShipTop = ShipY[j] + 40;
int SpaceShipleft = spaceShipX[i] - 45;
int SpaceShipright = spaceShipX[i] + 45;
boolean LaserhitSpaceship = Lasertop > SpaceShipBottom &&
Laserbottom < SpaceShipTop &&
LaserLeft < SpaceShipright &&
LaserRight > SpaceShipleft;
if(LaserhitSpaceship == true){
spaceShipX[0] = 90000;
}*/
}
void Shootlaser() {
if (ShowLaser == true) {
LaserY-=5;
}
}```

Here is what I think the issues are. First of all, processing is not the best language to make a game like Space Invaders. You can't have multiple key inputs at once. For example, if I press the left arrow, hold it, then press the right arrow, and let go of the left arrow, processing will ignore the left arrow. Processing has one key input: key. It can only have one value. You can't track multiple inputs at once. You can maybe replace it with your mouse - if the mouse is far to the left, move left. If it is far to the right, move right. In the middle? Stay still.
Aside from that, you want to check for collision. First of all, make the enemy into an object. I am assuming you know how to make objects. If not, look at this tutorial. Now, we need to check for collision. I'd suggest making a collision method inside of the enemy class, and here is what i'd imagine it to be:
boolean collidingWithPlayer() {
return (playerX > enemyX && playerX < enemyX + enemyW
&& playerY > enemyY && playerY < enemyY + enemyH);
}
Use this as you will. Good luck with your game.

Related

On the main method of my code on the very last line, I have a directory to run maze.txt from my desktop

On the main method of my code on the very last line, I have a directory to run maze.txt from my desktop to run the maze. How can I fix this problem because if I send this code to someone else they have to open the file and change the directory to the directory of the maze.txt which they downloaded with my file.**
Maze.txt
7 7
GOOOOXO
XXOXOOX
OXOOOXX
XXXOOXO
XXXXOXX
SOOOOOX
XXXXXXX
import java.io.*;
public class MazeSolver {
private char [][] maze;
private int startX , startY;
private int counter = 0;
public MazeSolver(String fileName) throws IOException {
maze = fileIterator(fileName);
startX = startX(maze);
startY = startY(maze);
solve(startX,startY);
System.out.println(printMaze());
}
public void solve(int x, int y) {
if (findPath(x,y)) {
maze[x][y] = 'S';
}
}
public boolean findPath(int x , int y){
counter ++;
if (maze[x][y] > 7) {return false;}
if (maze[x][y] == 'G') {return true;}
if (maze[x][y] == 'X' || maze[x][y] == 'O'){return false;}
maze[x][y] ='O';
boolean result;
result = findPath(x , y+1);
if(result){return true;}
result = findPath(x-1 , y);
if(result){return true;}
result = findPath(x , y-1);
if(result){return true;}
result = findPath(x+1 , y);
if(result){return true;}
maze[x][y] = 'O';
return false;
}
public String printMaze() {
String output = "";
for (int x = 0; x < 7; x++) {
for (int y = 0; y < 7; y++) {
output += maze[x][y] + " ";
}
output += "\n";
}
return output;
}
private char[][] fileIterator(String fileName) throws IOException {
File file = new File(fileName);
if(!file.exists()){
System.out.println(fileName+ "does not exists");
}
if(!(file.canRead() && file.isFile())){
System.out.println(fileName + "can not be read");
}
BufferedReader read = new BufferedReader(new FileReader(file));
String rea = read.readLine();
String[] split = rea.split(" ");
int row = Integer.valueOf(split[0]);
int col = Integer.valueOf(split[1]);
String readline;
int num = 0;
char [][] maze = new char[row][col];
while((readline = read.readLine()) != null){
char[] ch = readline.toCharArray();
for(int i = 0;i < ch.length;i++){
maze[i][num] = ch[i];
}
num++;
}
return maze;
}
private static int startX(char[][] charArray){
int startX = 0;
for(int i=0 ; i < charArray.length ; i++){
for(int j=0 ; j < charArray[i].length ; j++){
if(charArray[i][j] == 'S'){
startX = i;
}
}
}
return startX;
}
private static int startY(char[][] charArray){
int startY = 0;
for(int i=0 ; i < charArray.length ; i++){
for(int j=0 ; j < charArray[i].length ; j++){
if(charArray[i][j] == 'S'){
startY = j;
}
}
}
return startY;
}
public static void main(String[] args) throws IOException {
MazeSolver ms = new MazeSolver("C:\\Users\\mypc\\Desktop\\maze.txt");
}
}
There are many solutions for that, depending on what you need.
A simple one, if you want the users to experiment with different maze.txt files that they can provide, is to get the path of the file from the command line arguments (i.e., from the args parameter of the main method).
You could change your main method body to:
MazeSolver ms = new MazeSolver(args[0]);
Of course, further checks need to be made, but that's irrelevant for this exercise.
Then, the users run your program from the terminal as:
java MazeSolver /path/to/their/maze.txt
/path/to/their/maze.txt will be captured by args[0] in your main method.
import java.util.Scanner;
import java.io.*;
public class MazeSolver {
private char[][] maze;
private int startX;
private int startY;
private int row;
private int col;
private int endX;
private int endY;
public MazeSolver (String fileName) {
try {
Scanner get = new Scanner(new FileReader(fileName));
row = get.nextInt(); // Integer.parseInt(sChar[0]);
col = get.nextInt(); //col = Integer.parseInt(sChar[2]);
maze = new char[row][col];
String mazeString = "";
// Read the entire file and store in a String called mazeString
while(get.hasNextLine()) {
mazeString += get.nextLine();
}
char[] temp = mazeString.toCharArray();
for(int x = 0; x < row * col; x++) {
maze[x/row][x%col] = temp[x];
}
}
catch (IOException e) {
System.out.println("\nFile cannot be found. Please try again: \n");
System.exit(0);
}
char start = 'S';
for(int i = 0; i < row; i++) {
for(int x = 0; x < col; x++) {
char setStart = maze[i][x];
if(setStart == start) {
startX = i;
startY = x;
}
}
}
char goal = 'G';
for(int i = 0; i < row; i++) {
for(int x = 0; x < col; x++) {
char setEnd = maze[i][x];
if(setEnd == goal) {
endX = i;
endY = x;
}
}
}
if (solveMaze(startX,startY)){
System.out.println("Solution Found");
printMaze();
}
else{
System.out.println("No solution Found");
printMaze();
}
}
public void printMaze() {
for(int r = 0; r < row; r++) {
for(int c = 0; c < col; c++) {
System.out.print(maze[r][c]);
}
System.out.println();
}
}
public boolean solveMaze(int x, int y) {
// Base case
if(x == endX && y == endY) {
maze[x][y] = 'G';
maze[startX][startY]='S';
return true;
}
// Out of bounds
if((x >= 0 && x < row && y >= 0 && y < col && maze[x][y] != 'X' && maze[x][y] != '.') == true) {
maze[x][y] = '.';
// Right
if(solveMaze(x + 1, y)) {
return true;
}
// Left
if(solveMaze(x - 1, y)) {
return true;
}
// Up
if(solveMaze(x, y - 1)) {
return true;
}
// Down
if(solveMaze(x, y + 1)) {
return true;
}
else {
maze[x][y] = '#';
return false;
}
}
else {
return false;
}
}
}

problems occured when solving mazes using DFS

I am doing an assignment which creates a maze and then solves it,
I simulate the maze as an array,
using 1 to represent the wall, 0 -- road, 5 -- start, 9 -- destination
if the road has been used, change its value to 2;
it works well for creating mazes,
In most cases, it can find the path to the destination, but sometimes it still pops error stating "empty stack error", like the picture shows...
[]
I can't find the problem(s), may you help me out?
package MazeDFS;
import java.util.Random;
import java.util.Stack;
public class maze {
public static void main(String[] args) {
//create maze
//and solve it
//define the size as 9*9
int r,c;
r = 9;
c = 9;
int[][] newMaze = mazeGenerator(r,c);
newMaze[1][1] = 5;
mazePrinter(newMaze,r,c);
Stack<Step> path = new Stack<Step>();
Step s0 = new Step(1,1);
path.push(s0);
long startTime = System.nanoTime();
newMaze = solve(newMaze, 1, 1, path);
long endTime = System.nanoTime();
System.out.println("Time length:" + (endTime - startTime));
}
public static int[][] mazeGenerator(int x, int y){
Random randNum = new Random();
/*I simulated the maze as a x*y array
Values of the array represent elements of the maze
0 -- road, 1 -- wall, 5 -- start, 9 -- destination
*/
int[][] maze = new int[x][y];
for(int i = 0; i < x; i++) {
for(int j = 0; j < y; j++) {
//bound of the maze
if(i==0 || j==0 || i==x-1 || j==y-1) {
maze[i][j] = 1;
}
//build walls
if(j%2 == 0) {
maze[i][j] = 1;
}
}
}
//randomly choose a row of every wall and make it a road
for(int i = 1; i < y-1; i++) {
int row = randNum.nextInt(x-2)+1;
maze[row][i] = 0;
}
maze[x-2][y-2] = 9;
return maze;
}
public static void mazePrinter(int[][] maze,int x, int y) {
for(int i=0; i<x; i++) {
for(int j=0; j<y; j++) {
System.out.print(maze[i][j]);
}
System.out.println();
}
}
public static int[][] solve(int[][] newMaze, int x, int y, Stack<Step> path) {
mazePrinter(newMaze, 9,9);
System.out.println();
if(newMaze[x][y] == 9) {
Step s = new Step(x,y);
newMaze[x][y] = 2;
path.push(s);
return newMaze;
}
//going down
int dx = 1;
int dy = 0;
if(newMaze[x+dx][y+dy] == 0 || newMaze[x+dx][y+dy] == 9) {
//if visited mark as 2
if(newMaze[x+dx][y+dy] != 9) {
newMaze[x+dx][y+dy] = 2;
}
Step ss = new Step(x+dx,y+dy);
path.push(ss);
System.out.println("going down");
return solve(newMaze, x+dx, y+dy, path);
}
//going up
dx = -1;
dy = 0;
if(newMaze[x+dx][y+dy] == 0 || newMaze[x+dx][y+dy] == 9) {
//if visited mark as 2
if(newMaze[x+dx][y+dy] != 9) {
newMaze[x+dx][y+dy] = 2;
}
Step ss = new Step(x+dx,y+dy);
path.push(ss);
System.out.println("going up");
return solve(newMaze, x+dx, y+dy, path);
}
//turn right
dx = 0;
dy = 1;
if(newMaze[x+dx][y+dy] == 0 || newMaze[x+dx][y+dy] == 9) {
//if visited mark as 2
if(newMaze[x+dx][y+dy] != 9) {
newMaze[x+dx][y+dy] = 2;
}
Step ss = new Step(x+dx,y+dy);
path.push(ss);
System.out.println("turn right");
return solve(newMaze, x+dx, y+dy, path);
}
//turn left
dx = 0;
dy = -1;
if(newMaze[x+dx][y+dy] == 0 || newMaze[x+dx][y+dy] == 9) {
//if visited mark as 2
if(newMaze[x+dx][y+dy] != 9) {
newMaze[x+dx][y+dy] = 2;
}
Step ss = new Step(x+dx,y+dy);
path.push(ss);
System.out.println("turn left");
return solve(newMaze, x+dx, y+dy, path);
}
//if their is no way to go then turn back to the last step
Step sss = path.pop();
int x1 = sss.getX();
int y1 = sss.getY();
System.out.println("return to:"+"x1:"+x +", y1:"+ y);
return solve(newMaze, x1, y1, path);
}
}
class Step{
private int x;
private int y;
Step(int x, int y){
this.x = x;
this.y = y;
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
}

Libgdx Generate RogueLIke Dungeon - Algorithm Error

I have used Libgdx to generate a dungeon out of keyboard characters. I have decided to print out the array as a text file.
However this is what I got:
Furthermore, It isn't consistent
I don't get what is wrong?
I checked over my algorithm and didn't find anything wrong.
Here is my code:
public class test1 extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
int X = 50;
int Y = 25;
////////// # wall
////////// . ground
char[][][] mapChars = new char[1000][1000][1000];
private void genDung() {
int clearance = 4;
for (int i = 0; i < Y; i++) {
for (int j = 0; j <= X; j++) {
if(j == X)
mapChars[0][i][j] = '\n';
else
mapChars[0][i][j] = '#';
}
}
int roomCount = MathUtils.random(2, 2);
int[] roomPosX = new int[roomCount];
int[] roomPosY = new int[roomCount];
int[] roomCenterPosX = new int[roomCount];
int[] roomCenterPosY = new int[roomCount];
int[] roomSizeX = new int[roomCount];
int[] roomSizeY = new int[roomCount];
for (int i = 0; i < roomCount; i++) {
int attempts = 0;
while(true) {
boolean rePosition = false;
roomPosX[i] = MathUtils.random(1, X-1);
roomPosY[i] = MathUtils.random(1, Y-1);
roomSizeX[i] = MathUtils.random(2, 12);
roomSizeY[i] = MathUtils.random(2, 8);
for(int j = 0; j <= i; j++) {
if(i != j) {
if(roomPosX[i] >= roomPosX[j] && roomPosX[i] <= (roomPosX[j] + roomSizeX[j] + clearance)) {
if(roomPosY[i] >= roomPosY[j] && roomPosY[i] <= (roomPosY[j] + roomSizeY[j] + clearance)) {
rePosition = true;
break;
}
}
if((roomPosX[i]+roomSizeX[i]) >= roomPosX[j] && (roomPosX[i]+roomSizeX[i]) <= (roomPosX[j] + roomSizeX[j] + clearance)) {
if((roomPosY[i]+roomSizeY[i]) >= roomPosY[j] && (roomPosY[i]+roomSizeY[i]) <= (roomPosY[j] + roomSizeY[j] + clearance)) {
rePosition = true;
break;
}
}
if((roomPosX[i]) >= roomPosX[j] && (roomPosX[i]) <= (roomPosX[j] + roomSizeX[j] + clearance)) {
if((roomPosY[i]+roomSizeY[i]) >= roomPosY[j] && (roomPosY[i]+roomSizeY[i]) <= (roomPosY[j] + roomSizeY[j] + clearance)) {
rePosition = true;
break;
}
}
if((roomPosX[i]+roomSizeX[i]) >= roomPosX[j] && (roomPosX[i]+roomSizeX[i]) <= (roomPosX[j] + roomSizeX[j] + clearance)) {
if((roomPosY[i]) >= roomPosY[j] && (roomPosY[i]) <= (roomPosY[j] + roomSizeY[j] + clearance)) {
rePosition = true;
break;
}
}
}
else if(roomPosX[j] + roomSizeX[j] >= X-1){
rePosition = true;
}
else if(roomPosY[j] + roomSizeY[j] >= Y-1){
rePosition = true;
}
}
attempts++;
if(attempts >= 10000) break;
if(!rePosition) break;
}
}
for(int r = 0; r < roomCount; r++) {
for (int a = roomPosX[r]; a <= (roomPosX[r] + roomSizeX[r]); a++) {
for (int b = roomPosY[r]; b <= (roomPosY[r] + roomSizeY[r]); b++) {
mapChars[0][b][a] = '.';
}
}
}
Gdx.app.log("roomCount", String.valueOf(roomCount)+"\n\n\n");
for(int i =0; i< roomCount; i++) {
roomCenterPosX[i] = roomPosX[i] + roomSizeX[i]/2;
roomCenterPosY[i] = roomPosY[i] + roomSizeY[i]/2;
Gdx.app.log("room", String.valueOf(i)+"\n");
Gdx.app.log("roomPosX", String.valueOf(roomPosX[i]));
Gdx.app.log("roomPosY", String.valueOf(roomPosY[i]));
Gdx.app.log("roomSizeX", String.valueOf(roomSizeX[i]));
Gdx.app.log("roomSizeY", String.valueOf(roomSizeY[i])+"\n");
Gdx.app.log("RoomCenterPosX", String.valueOf(roomCenterPosX[i]));
Gdx.app.log("RoomCenterPosY", String.valueOf(roomCenterPosY[i])+"\n\n");
}
int difference = X;
int[] roomNum = new int[2];
for(int i = 0; i < roomCount; i++) {
for(int j = 0; j < roomCount; j++) {
if(i != j) {
if(abs(roomCenterPosX[i] - roomCenterPosX[j]) < difference) {
difference = abs(roomCenterPosX[i] - roomCenterPosX[j]);
roomNum[0] = i;
roomNum[1] = j;
}
}
}
}
Gdx.app.log("FarthestRooms", String.valueOf(roomNum[0]));
Gdx.app.log("FarthestRooms", String.valueOf(roomNum[1]));
int differenceX = X;
int differenceY = Y;
int[] connectRooms = new int[2];
// int[] roomsConnected = new int[roomCount];
connectRooms[0] = MathUtils.random(0, roomCount - 1);
// roomsConnected[0] = connectRooms[0];
int count;
for(int i = 0; i < roomCount-1; i++) {
int j;
while(true) {
connectRooms[1] = MathUtils.random(0, roomCount - 1);
/* while (true) {
connectRooms[1] = MathUtils.random(0, roomCount - 1);
count = 0;
for (j = 0; j < i; j++) {
if (connectRooms[1] != roomsConnected[j] && connectRooms[0] != roomsConnected[j]){
count++;
}
}
if(count >= i-2)
break;
}*/
if(connectRooms[0] != connectRooms[1])
break;
}
// roomsConnected[i+1] = connectRooms[1];
differenceX = roomCenterPosX[connectRooms[0]] - roomCenterPosX[connectRooms[1]];
differenceY = roomCenterPosY[connectRooms[0]] - roomCenterPosY[connectRooms[1]];
if(roomCenterPosX[connectRooms[0]] < roomCenterPosX[connectRooms[1]])
differenceX *= -1;
if(roomCenterPosY[connectRooms[0]] < roomCenterPosY[connectRooms[1]])
differenceY *= -1;
int k;
try {
if (differenceX > 0) {
for (k = 0; k < differenceX; k++) {
mapChars[0][roomCenterPosY[i]][roomCenterPosX[i] + k] = '.';
}
} else if (differenceX < 0) {
for (k = 0; k > differenceX; k--) {
mapChars[0][roomCenterPosY[i]][roomCenterPosX[i] + k] = '.';
}
} else k = 0;
if (differenceY < 0) {
for (int z = 0; z > differenceY; z--) {
mapChars[0][roomCenterPosY[i] + z][roomCenterPosX[i] + k] = '.';
}
} else if (differenceY > 0) {
for (int z = 0; z < differenceY; z++) {
mapChars[0][roomCenterPosY[i] + z][roomCenterPosX[i] + k] = '.';
}
} else {
}
}
catch (ArrayIndexOutOfBoundsException e) {
Gdx.app.log("Non Fatal Exception", String.valueOf(e));
}
Gdx.app.log("Connect", String.valueOf(connectRooms[0]));
Gdx.app.log("Connect", String.valueOf(connectRooms[1]));
Gdx.app.log("DifferenceX", String.valueOf(differenceX));
Gdx.app.log("DifferenceY", String.valueOf(differenceY)+"\n");
}
for(int q = 0; q < Y; q++) {
mapChars[0][q][X] = '\n';
}
for(int w = 0; w < Y; w++) {
mapChars[0][w][X-1] = '#';
}
for(int e = 0; e < Y; e++) {
mapChars[0][Y-1][e] = '#';
}
}
private void export() {
if(Gdx.files.isLocalStorageAvailable()) {
FileHandle fileHandle = Gdx.files.local("map.txt");
if(Gdx.files.local("map.txt").exists())
fileHandle.writeString("", false);
for(int i = 0; i<= Y; i++) {
for (int j = 0; j <= X; j++) {
fileHandle.writeString(""+mapChars[0][i][j] , true);
}
}
}
}
#Override
public void create () {
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
// genMap();
// for(int i = 0; i< 4; i++)
// refineMap();
genDung();
export();
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(img, 0, 0);
batch.end();
if(Gdx.input.isTouched()) {
// genMap();
// for(int i = 0; i< 4; i++)
// refineMap();
genDung();
export();
}
}
}
I want the two rooms to connect properly every time.
As you can see, one of the time, the rooms connected
The other time the rooms don't connect.
Thanks in advance
The whole thing can be simplified and definitely needs refactoring. Regarding the 2 room connection - check this piece carefully
differenceX = roomCenterPosX[connectRooms[0]] - roomCenterPosX[connectRooms[1]];
differenceY = roomCenterPosY[connectRooms[0]] - roomCenterPosY[connectRooms[1]];
if(roomCenterPosX[connectRooms[0]] < roomCenterPosX[connectRooms[1]])
differenceX *= -1;
if(roomCenterPosY[connectRooms[0]] < roomCenterPosY[connectRooms[1]])
differenceY *= -1;
As #kiheru pointed out it is equivalent to Math.abs(roomCenterPosX[connectRooms[0]] - roomCenterPosX[connectRooms[1]]) (same for Y). So you always "dig" to right and down, never up or left.
Drop that invertion and have fun with the rest of your algorithm :)

Pseudo Infinite Loop (Optimally Deleting 'missing data' from a matrix)

When I use a random matrix (class Determine), my program runs successfully in 1700 miliseconds. However, when I create a matrix by reading a file through a buffered reader (class Construct) my program experiences a logic error and enters and infinite loop.
Again, it works for a random matrix, but does not work for a 'real' matrix of the same size. I've checked my work and cannot find an error in my reading of the file. Does anyone know what may be causing this logic error? I will append my code with comments if it helps!
Update: OK the problem was from my own silly oversight (see my answer below). This did not occur with random data due to my 'haveIt' method and the probability of getting missing data. As such, my code has been updated to reflect this logic error and I will be happy to explain in detail how this code works if anyone asks:
import java.util.Random;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.*;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.BufferedReader;
class ValMax {
public static int valMax;
}
class Construct {
private static int colEnd;
private static int colStart;
private static int[] colSkip;
public static List<List<Integer>> rFile(String[] args){
if (args.length != 4) {
System.out.println("Format: FileName colStart colEnd colSkipped");
System.exit(0);
}
BufferedReader reader = null;
try {
List<List<Integer>> matrix = new ArrayList<List<Integer>>();
Construct.colEnd = Integer.parseInt(args[2]);
Construct.colStart = Integer.parseInt(args[1]);
String[] colSkipped = args[3].split(",");
Construct.colSkip = new int[colSkipped.length];
for (int x = 0; x < colSkipped.length; x++) {
Construct.colSkip[x] = Integer.parseInt(colSkipped[x]);
}
String line;
reader = new BufferedReader(new FileReader(new File(args[0])));
while ((line = reader.readLine()) != null) {
String[] tokens = line.split(",");
List<Integer> rows = new ArrayList<Integer>(colEnd - colStart + 1 - colSkip.length);
for (int x = 1; x <= tokens.length; x++) {
if (x >= colStart && x <= colEnd && contains(x, colSkip) == false) {
try {
Double.parseDouble(tokens[x - 1]);
} catch (NumberFormatException e3) {
break;
}
if (tokens[x - 1].equals("-999")) { //
rows.add(2);
} else {
rows.add(1);
}
}
}
if (rows.size() == colEnd - colStart + 1 - colSkip.length) {
matrix.add(rows);
}
}
System.out.println(matrix.size() + "\t" + matrix.get(0).size());
return matrix;
} catch (IOException e1) {
System.out.println("IOEXCEPTION!!");
System.exit(0);
} catch (NumberFormatException e2) {
System.out.println("NumberFormatException!!");
System.exit(0);
} finally {
try {
reader.close();
} catch (IOException e5) {
e5.printStackTrace();
}
}
return null;
}
private static boolean contains(int a, int[] colSkip) {
boolean bluejay = false;
for (int skip : colSkip) {
if (a == skip) {
bluejay = true;
}
}
return bluejay;
}
}
class Determine {
private static Integer gen(int a, int b, Random r) {
Integer rand = r.nextInt(a) + b;
return rand;
}
public static List<List<Integer>> rando() {
Random r = new Random();
int k = gen(1, 24, r), l = gen(1, 33, r); //userinput
List<List<Integer>> matrix = new ArrayList<List<Integer>>(k);
for (int x = 1; x <= k; x++) {
List<Integer> row = new ArrayList<Integer>(l);
for (int y = 1; y <= l; y++) {
double bias = Math.random();
if (bias > 0.7) {
row.add(2);
} else {
row.add(1);
}
}
matrix.add(row);
}
return matrix;
}
}
class Search {
public static void finalize(List<List<Integer>> matTan, boolean gumDrop, int minimum) {
final int A = matTan.size();
final int B = matTan.get(0).size();
boolean judge = true;
if (minimum > A && gumDrop == false || minimum > B && gumDrop == true) {
System.out.print("\nMinimum too high\n\n");
System.exit(0);
}
ValMax.valMax = 1; //userinput
int[] rows = new int[2 + A + B];
List<int[]> combination = new ArrayList<int[]>(100);
int threads = Runtime.getRuntime().availableProcessors();
ExecutorService service = Executors.newFixedThreadPool(threads);
List<List<int[]>> ranTime = new ArrayList<List<int[]>>(2 * threads);
for (int x = 0; x < 2 * threads; x++) {
List<int[]> jobs = new ArrayList<int[]>(90);
ranTime.add(jobs);
}
if (gumDrop == false) {
for (int x = 1; x <= minimum; x++) {
rows[x] = 1;
}
} else {
rows[1] = 1;
}
rows[A + 1] = 999;
int y = 0, z = 0;
System.out.println(threads);
while (rows[A + 1] == 999) {
y++;
int[] copy = Arrays.copyOf(rows, rows.length);
if (y == 91) {
z++;
y = 1;
if (z < 2* threads) {
ranTime.get(z).clear();
}
}
if (z == 2 * threads) {
processInputs(ranTime, combination, matTan, minimum, gumDrop, service);
z = 0;
ranTime.get(0).clear();
ranTime.get(0).add(copy);
} else {
ranTime.get(z).add(copy);
}
nextComb(A, rows);
}
if (ranTime.get(0).size() > 0) {
for (int x = 0; x < 2 * threads; x++) {
if (judge == false) {
ranTime.remove(x);
threads--;
x--;
}
if (ranTime.get(x).size() != 90 && judge == true) {
judge = false;
}
}
processInputs(ranTime, combination, matTan, minimum, gumDrop, service);
}
service.shutdown();
try {
service.awaitTermination(60, TimeUnit.SECONDS);
} catch (InterruptedException e6) {
System.out.print("Termination Error!");
}
developed(matTan, combination, gumDrop);
}
private static void processInputs(List<List<int[]>> ranTime, List<int[]> combination, List<List<Integer>> matTan, int minimum, boolean gumDrop, ExecutorService service) {
Collection<StringTask> collection = new ArrayList<StringTask>(ranTime.size());
for (List<int[]> jobs : ranTime) {
StringTask analysis = new StringTask(jobs, combination, matTan, minimum, gumDrop);
collection.add(analysis);
}
try {
List<Future<Integer>> futures = service.invokeAll(collection);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void developed(List<List<Integer>> matTan, List<int[]> combination, boolean gumDrop) {
System.out.print("\n\n\n");
for (int[] e : combination) {
if (e[0] == ValMax.valMax) { // == ValMax.valMax
Optimize10.prin(e);
List<List<Integer>> complete = Multi.reduct1(e, matTan);
if (gumDrop == true) {
System.out.println("Solution Matrix, transposed [above data works on column]");
Optimize10.prin(Multi.transpose(complete)); //The solution matrix, reorientated
} else {
System.out.println("Solution Matrix");
Optimize10.prin(complete); //The solution matrix, reorientated
}
}
}
}
private static void nextComb(int bounds, int[] rows) {
int kappas = findMax(rows);
if (rows[bounds] == 0) {
rows[kappas + 1] = 1;
rows[kappas] = 0;
} else {
int y = 1;
int x = bounds;
while (rows[x] == 1) {
rows[x] = 0;
y++;
x--;
}
kappas = findMax(rows);
if (kappas != -1) {
rows[kappas] = 0;
}
int z = kappas + 1;
while (y > 0) {
rows[z] = 1;
z++;
y--;
}
}
}
private static int findMax(int[] rows) {
int y = 0;
for (int x = rows.length - 1; x >= 0; x--) {
if (rows[x] == 1) {
return x;
}
}
return y;
}
}
class StringTask implements Callable<Integer> {
private List<List<Integer>> matTan;
private List<int[]> combination;
private List<int[]> jobs;
private boolean gumDrop;
private int minimum;
StringTask(List<int[]> a, List<int[]> b, List<List<Integer>> c, int d, boolean e) {
this.combination = b;
this.minimum = d;
this.gumDrop = e;
this.matTan = c;
this.jobs = a;
}
public Integer call() {
for (int[] e : jobs) {
int temp = Multi.reduct2(e, matTan, minimum, gumDrop);
if (temp > ValMax.valMax) { //ValMax.valMax //userinput
ValMax.valMax = e[0]; //userinput
combination.add(e);
System.out.print(ValMax.valMax + " ");
}
}
return null;
}
}
class Multi {
public static int[] inverse;
public static void halveIt(int[] col, List<List<Integer>> matCop) {
int size = matCop.size(), a = 0;
inverse = new int[size];
for (int x = 0; x < size; x++) {
for (int y = 0; y < matCop.get(0).size(); y++) {
if (col[y] == 1 && matCop.get(x).get(y) == 2) {
inverse[x + a] = 1;
matCop.remove(x);
size--;
x--;
a++;
break;
}
}
}
}
public static List<List<Integer>> reduct1(int[] row, List<List<Integer>> matCan) {
List<List<Integer>> matTan = new ArrayList<List<Integer>>(matCan);
int with = matTan.size(), high = inverse.length, a = 0;
final int B = matCan.get(0).size() - 1;
final int A = matCan.size();
for (int x = 0; x < A; x++) {
List<Integer> value = new ArrayList<Integer>(matCan.get(x));
matTan.set(x, value);
}
int y = 0, size = 0;
for (int x = 0; x < high; x++) {
if (x < with) {
if (row[x + a + 1] > 0) {
size = matTan.get(0).size();
for (y = 0; y < size; y++) {
if (matTan.get(x).get(y) == 2) {
for (int z = 0; z < with ; z++) {
matTan.get(z).remove(y);
}
size--;
y--;
}
}
} else {
matTan.remove(x);
with--;
high--;
x--;
a++;
}
}
}
return matTan;
}
public static int reduct2(int[] row, List<List<Integer>> matCan, int minimum, boolean gumDrop) {
int b = 0, c = 0, d = 0, e = 0, g = 0, high = inverse.length;
final int B = matCan.get(0).size() - 1;
final int A = matCan.size();
for (int x = 0; x < high; x++) {
if (x < A) {
if (row[x + 1] > 0) {
b++;
for (int y = 0; y < B + 1; y++) {
if (matCan.get(x).get(y) == 2 && row[2 + A + y] == 0) {
row[2 + A + y] = 1; // 1s mean that a column was deleted, 0 is kept.
d -= e;
} else if (row[2 + A + y] == 0) {
d++;
}
}
e++;
}
}
if (inverse[x] == 0 && x < high || gumDrop == true && x < high) {
if (row[x - c + 1] == 1) {
row[x - c + 1] = 1 + c + g;
g++;
} else {
g++;
}
} else {
c++;
}
}
if (d / b < minimum && gumDrop == true) {
row[0] = 0;
d = 0;
} else {
row[0] = d;
}
return d;
}
public static List<List<Integer>> transpose(List<List<Integer>> matTan) {
int d = matTan.get(0).size();
List<List<Integer>> matFlip = new ArrayList<List<Integer>>(d);
for (int y = 0; y < d; y++) {
List<Integer> row = new ArrayList<Integer>();
for (int x = 0; x < matTan.size(); x++) {
row.add(matTan.get(x).get(y));
}
matFlip.add(row);
}
return matFlip;
}
}
// ########## Main Method Start ##########
public class Optimize10 {
public static void main(String[] args) {
double startTime = System.nanoTime() / 1000000;
List<List<Integer>> matrix = Determine.rando();
// List<List<Integer>> matrix = Construct.rFile(args);
List<List<Integer>> matTan = contract(new int[matrix.get(0).size()], matrix);
int a = matTan.size(), b = matTan.get(0).size();
System.out.println(a + "\t" + b);
boolean gumDrop = false;
int minimum = 40; //userinput
BigInteger aNew = new BigInteger("2");
BigInteger bNew = new BigInteger("2");
aNew = aNew.pow(a);
bNew = bNew.pow(b);
for (int x = 1; x < minimum; x++) {
aNew = aNew.subtract(binomial(a, x));
}
if (aNew.compareTo(bNew) > 0) {
gumDrop = true;
matTan = Multi.transpose(matTan);
}
System.out.println(gumDrop);
prin(matrix);
prin(matTan);
Search.finalize(matTan, gumDrop, minimum);
double endTime = System.nanoTime() / 1000000;
double duration = (endTime - startTime);
System.out.println(duration);
}
// ########## MAIN METHOD END ############
private static BigInteger binomial(final int N, final int K) {
BigInteger ret = BigInteger.ONE;
for (int k = 0; k < K; k++) {
ret = ret.multiply(BigInteger.valueOf(N-k)).divide(BigInteger.valueOf(k+1));
}
return ret;
}
private static List<List<Integer>> contract(int[] col, List<List<Integer>> matrix) {
List<List<Integer>> matCop = new ArrayList<List<Integer>>(matrix);
col[0] = 1; //userinput 1 means don't delete!
col[1] = 1; //userinput
col[2] = 1;
col[12] = 1;
col[14] = 1;
col[22] = 1;
col[28] = 1;
col[29] = 1;
Multi.halveIt(col, matCop);
return matCop;
}
public static void prin(List<List<Integer>> matrix) {
for (int x = 0; x < matrix.size(); x ++) {
System.out.print("[" + matrix.get(x).get(0));
for (int y = 1; y < matrix.get(0).size(); y++) {
System.out.print(" " + matrix.get(x).get(y));
}
System.out.print("]\n");
}
System.out.print("\n\n");
}
public static void prin(int[] a) {
System.out.print("[" + a[0]);
for (int x = 1; x < a.length; x ++) {
System.out.print(" " + a[x]);
}
System.out.print("]\n\n");
}
public static void prin(String[] a) {
System.out.print("[" + a[0]);
for (int x = 1; x < a.length; x ++) {
System.out.print(" " + a[x]);
}
System.out.print("]\n\n");
}
public static void prin2(List<Integer> a) {
System.out.print("[" + a.get(0));
for (int x = 1; x < a.size(); x ++) {
System.out.print(" " + a.get(x));
}
System.out.print("]\n\n");
}
}
OK, so there actually was no infinite loop in this code whatsoever. The problem was with line 466 of my code; specifically, I was basing whether I analyzed the original matrix or its transpose on the number of rows after truncation on the original matrix and subtracting the minimum. This is wrong because, for example,
sum_{i = 40)^{54}(54 choose i) >> 2^32.
My program was taking forever because it was told to traverse through over a trillion combinations instead of 'just' a few billion. Granted it can do 10 billion in about 2 hours, and I can save more time by inverting a few nested for loops (another time).
I Guess it's time to learn profiling to see where my code slows down.

Java - NullPointerException, Changing array value

I'm doing a collegeproject to make tetris, however I'm stuck at the moment.
I have a nullpointerexception when I simply want to change a value of an array. Should be easy right?
Apparently not...
I'm not an advanced programmer yet, so if anyone could help me find the incorrect code, and specifically explain to me why it's wrong, it'll be appreciated.
Here's my code:
package tetris;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import engine.*;
public class Tetris extends Game {
private int x = 0, y = 0, maxWidth = 0, bSize = 25;
private int[][] field;
private boolean busy;
private Blok blok = null;
public Tetris() {
title = "Tetris";
height = 600;
width = 400;
delay = 100;
delay2 = 10;
field = new int[20][10];
field[19][7] = 1;
field[18][7] = 2;
field[17][7] = 3;
field[19][2] = 4;
field[19][3] = 5;
}
public static void main(String arg[]) {
GameApplication.start(new Tetris());
}
#Override
/**
* Right Arrow: keycode 39
* Left Arrow: keycode 37
*/
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == 37) {
if (tryMove(-1)) {
x--;
}
}
else if(e.getKeyCode() == 39) {
if (tryMove(1)) {
x++;
}
} else if(e.getKeyCode() == 40) {
if (tryMove(0)) {
y++;
}
}
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void update() {
if(!busy) {
int random = (int) (Math.random()*7);
//debug mode
random = 0;
///
System.out.println(random);
blok = new Blok(random);
y = 1;
x = 3;
busy = true;
}
if (!tryMove(0)){
field[y][x] = 1;
busy = false;
} else {
y++;
}
scanLine();
}
#Override
public void update2() {
}
#Override
public void draw(Graphics2D g) {
g.fillRect(0, 0, width, height);
g.setColor(Color.LIGHT_GRAY);
g.fillRect(0, 0, 250, 500);
for (int i = 0; i<20; i++){
for (int j = 0; j<10; j++){
if (field[i][j]>0) {
g.setColor(Color.black);
g.fillRect(j*25,i*25,bSize,bSize);
}
}
}
if(busy) {
maxWidth = blok.getWidth();
for (int i = 0; i<3; i++){
g.fillRect(blok.getX(i)*25,blok.getY(i)*25,bSize,bSize);
}
}
}
public boolean tryMove(int a) {
boolean b = true;
if (a == -1){
if (x <= 0 || field[y][x-1] != 0){
b = false;
}
} else if (a == 0){
if (y >= 19 || field[y+1][x] != 0){
b = false;
}
} else if (a == 1){
if (x >= (9-maxWidth) || field[y][x+1] != 0){
b = false;
}
}
return b;
}
public void scanLine(){
for (int i = 0; i<20; i++){
boolean vol = true;
for (int j = 0; j<10; j++){
if (field[i][j]==0) {
vol = false;
}
}
if (vol) {
removeLine(i);
}
}
}
public void removeLine(int a){
for (int i = a; i>0; i--){
for (int j = 0; j<10; j++){
field[i][j] = field[i-1][j];
}
}
}
}
and for making the block(and where it goes wrong)
package tetris;
public class Blok {
private int type;
private int[] x,y;
private int width;
public Blok(int type) {
this.setType(type);
setCoords(type);
x = new int[4];
y = new int[4];
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public void setCoords(int type) {
if (type == 0){
setWidth(3);
setX(0,1); setY(0,0);
setX(1,2); setY(1,0);
setX(2,3); setY(2,0);
setX(3,0); setY(3,0);
//x[0] = 1; y[0] = 0;
//x[1] = 2; y[1] = 0;
//x[2] = 3; y[2] = 0;
//x[3] = 0; y[3] = 0;
} else if (type == 1){
setWidth(2);
x[0] = 1; y[0] = 0;
x[1] = 2; y[1] = 0;
x[2] = 0; y[2] = -1;
x[3] = 0; y[3] = 0;
} else if (type == 2){
setWidth(2);
x[0] = 1; y[0] = 0;
x[1] = 2; y[1] = 0;
x[2] = 2; y[2] = -1;
x[3] = 0; y[3] = 0;
} else if (type == 3){
setWidth(2);
x[0] = 1; y[0] = 0;
x[1] = 2; y[1] = 0;
x[2] = 1; y[2] = -1;
x[3] = 0; y[3] = 0;
} else if (type == 4){
setWidth(2);
x[0] = 1; y[0] = -1;
x[1] = 1; y[1] = 0;
x[2] = 0; y[2] = -1;
x[3] = 0; y[3] = 0;
} else if (type == 5){
setWidth(1);
x[0] = 1; y[0] = 0;
x[1] = 1; y[1] = -1;
x[2] = 2; y[2] = -1;
x[3] = 0; y[3] = 0;
} else if (type == 6){
setWidth(2);
x[0] = 1; y[0] = 0;
x[1] = 1; y[1] = 1;
x[2] = 2; y[2] = 1;
x[3] = 0; y[3] = 0;
}
}
public int getX(int type) {
return x[type];
}
public int getY(int type) {
return y[type];
}
public void setX(int index, int value){
x[index] = value; //This is line 82, goes wrong here.
}
public void setY(int index, int value){
y[index] = value;
}
public int getWidth() {
return width;
}
public void setWidth(int w) {
this.width = w;
}
}
Here's the errorcode:
Exception in thread "Thread-2" java.lang.NullPointerException
at tetris.Blok.setX(Blok.java:82)
at tetris.Blok.setCoords(Blok.java:26)
at tetris.Blok.<init>(Blok.java:10)
at tetris.Tetris.update(Tetris.java:75)
at engine.Engine.run(Engine.java:18)
In your constructor you put
public Blok(int type) {
this.setType(type);
setCoords(type);
x = new int[4];
y = new int[4];
}
You call setCoords that calls setX(..) and setX use x that is null then NullPointerException is thrown.
A workaround is to change order.
public Blok(int type) {
this.setType(type);
x = new int[4];
y = new int[4];
setCoords(type);
}
But calling an overridable method in a constructor is not a good practice. Read more What's wrong with overridable method calls in constructors?. A workaround is making setCoords(..) final or making your class final or make that method private or remove from constructor and call it from client code of this class.

Categories

Resources