Code is too large, so I'll just copy the part that is problematic.
This is run() method in one class:
public void run(){
try{
sleep(1000);
while(true){
synchronized(space){
if(end)
return;
if(space[X][Y] == null)
break;
if(((Ship)space[X][Y]).isDestroyed){
destroy();
break;
}
if(isThereAnyShipsInTheArea() != 0){
if(team != ((Ship)space[X][Y + isThereAnyShipsInTheArea()]).team){
fight(isThereAnyShipsInTheArea());
}
}
else
move();
if(isDestroyed){
destroy();
break;
}
}
}
}
catch(InterruptedException ie){
System.out.println("Interrupted exception!");
}
}
This is simulation of Star Trek. Variable team represends to which team the ship belongs. Varable isDestroyed is true if the ship is destroyed in battle or crash when moving.
isThereAnyShipsInTheArea() - ship is within range if the distance one or two.
space is matrix whit dimensions [90]x[90].
I think problem is in run method, but I'll give you some other methods.
private int isThereAnyShipsInTheArea(){
if(space[X][Y - 2] instanceof Ship && ((Ship)space[X][Y - 2]).isDestroyed == false)
return -2;
if(space[X][Y - 1] instanceof Ship && ((Ship)space[X][Y - 1]).isDestroyed == false)
return -1;
if(space[X][Y + 1] instanceof Ship && ((Ship)space[X][Y + 1]).isDestroyed == false)
return 1;
if(space[X][Y + 2] instanceof Ship && ((Ship)space[X][Y + 2]).isDestroyed == false)
return 2;
return 0;
}
private synchronized void fight(int meet){
while(((Ship)svemir[X][Y]).isDestroyed == false && ((Ship)space[X][Y + meet]).isDestroyed == false){
if(((Ship)space[X][Y]).getProjectile() != 0){
((Ship)space[X][Y + meet]).setShield(((Ship)space[X][Y + meet]).getShield() - 1);
((Ship)space[X][Y + meet]).setWarp(((Ship)space[X][Y + meet]).getWarp() - 1);
((Ship)space[X][Y]).setProjectile(((Ship)space[X][Y]).getProjectile() - 1);
if(((Ship)space[X][Y + meet]).getShield() == 0 || ((Ship)space[X][Y + meet]).getWarp() == 0){
((Ship)space[X][Y + meet]).isDestroyed = true;
return;
}
}
if(((Ship)space[X][Y + meet]).getProjectile() != 0){
((Ship)space[X][Y]).setShield(((Ship)space[X][Y]).getShield() - 1);
((Ship)space[X][Y]).setWarp(((Ship)space[X][Y]).getWarp() - 1);
((Ship)space[X][Y + meet]).setProjectile(((Ship)space[X][Y + meet]).getProjectile() - 1);
if(((Ship)space[X][Y]).getShield() == 0 || ((Ship)space[X][Y]).getWarp() == 0){
this.isDestroyed = true;
return;
}
}
if(((Ship)space[X][Y]).getProjectile() == 0 && ((Ship)space[X][Y + meet]).getProjectile() == 0)
return;
}
}
To me you shouldn't do Thread.sleep() since it doesn't release any resources it grabs. Either schedule your task using ScheduledExecutorService or do wait() and yield() on an object monitor.
Your sleep is outside of your while(true) block, so instead of sleeping for a second every loop, you sleep once and then go into a tight loop.
Put the sleep at the end of the while(true) block, so you sleep once for every iteration of the loop. Ideally it should be just after the release of the synchronization on the space array.
Actually, full array scanning is far from ideal on finding items. Might want to look into keeping lists of items. Just to get an idea, a 1000x1000 array that has 20 items in it (space is big and mostly empty) will take 1,000,000 checks as you pass over the array, but if you reorganize your checks to be base on the items, you could probably get away with just 1000 or less checks.
For example, a list of ships:
for (Ship ship : ships) {
if (!ship.engaged()) {
ship.scanForEnemies();
}
if (ship.detectEnemies()) {
ship.attack();
}
}
might only have to loop through a dozen or fewer ships, checking a few hundred locations. If you are wondering how the above code works, in my example, the ship would have been constructed with a space array, that it kept a reference to.
Related
I am pretty far along on my project dealing with singly circular linked lists and am still having trouble with one point. My trouble stems from not being able to/knowing how to call the node before the node containing the first of the four consecutive colors and referring it to the beginning.
Prompt for Marbles game:
Place random marbles in a circle and if four of the same color appear, remove them and add four times the color score to the total score.
I would really appreciate if someone could help me figure how to resolve this problem..
Here's the code I'm working on:
public void deleteQuadruples()
{
//if the list has 4 nodes, delete all and make a new head
if (size == 4 && (start.getaMarble().getNumber() == start.getNextLink().getaMarble().getNumber()
&& start.getNextLink().getaMarble().getNumber() == start.getNextLink().getNextLink().getaMarble().getNumber()
&& start.getNextLink().getNextLink().getaMarble().getNumber() == start.getNextLink().getNextLink().getNextLink().getaMarble().getNumber()))
{
sum = 4*start.getaMarble().getNumber();
start = new Link(null, null);
addFirstMarble();
}
//else go thru the list and find whether or not there are four consecutive marbles of the same color/number and if so take them out
else
{
Link tmp = start;
if (tmp == null)
{
return;
}
do
{
/*int colorNumber = tmp.getaMarble().getNumber();
int counter = 1;
tmp = tmp.getNextLink();
if(colorNumber == tmp.getaMarble().getNumber())
{
counter++;
}
if(counter == 4)
{
score += 4*tmp.getaMarble().getNumber();
counter = 1;
//delete the 4 consecutive elements
}
if(tmp.getNextLink() == start && counter == 3 && start.getaMarble().getColor() == tmp.getaMarble().getColor())
{
score += 4*tmp.getaMarble().getNumber();
start = start.getNextLink();
//delete the 4 consecutive elements
}*/
for(Link cursor = start; cursor != end; cursor = cursor.getNextLink)
{
Link temp;
counter = 1;
if(cursor.getaMarble().getNumber() == cursor.getNextLink().getaMarble().getNumber())
{
counter++;
}
if(cursor.getaMarble().getNextLink().getNumber() != cursor.getNextLink().getNextLink().getaMarble().getNumber())
{
counter = 1;
}
if (counter == 4)
{
//deletes the four consecutive nodes with same color
//something.getNextLink() = start;
score += 4* cursor.getaMarble.getNumber();
}
}
}
while (tmp != start);
}
}
I made some changes to your code (it may not compile but will give an idea)
public void deleteQuadruples()
{
if (start == null || size == 3)
return;
//if the list has 4 nodes, delete all and make a new head
if (size == 4 && (start.getaMarble().getNumber() == start.getNextLink().getaMarble().getNumber()
&& start.getNextLink().getaMarble().getNumber() == start.getNextLink().getNextLink().getaMarble().getNumber()
&& start.getNextLink().getNextLink().getaMarble().getNumber() == start.getNextLink().getNextLink().getNextLink().getaMarble().getNumber()))
{
sum = 4*start.getaMarble().getNumber();
start = new Link(null, null);
addFirstMarble();
}
//else go thru the list and find whether or not there are four consecutive marbles of the same color/number and if so take them out
else
{
Node end = start;
while (end.getNextLink().getaMarble().getNumber() != start.getNextLink().getaMarble().getNumber())
{ end = end.getNextLink(); }
// no data
if(end.getNextLink().getaMarble().getNumber() == start.getaMarble().getNumber())
return;
// we have data
else {
sum = 4*start.getaMarble().getNumber();
// loop four times
// set the end.getNextLink() with start.getNextLink()
}
}
}
I am making a Tic-Tac-Toe game with a computer player. However, whenever I call the computer's makeMove method, the computer continues to play without the user being able to do anything. Just to be sure that the function stopped, I made it return after each move, but it still plays the entire game without the user's input.
Here are the relevant parts:
Board Class:
public String addToBoard(char c, int square) {
if (!spaceFull(board, square)) {
int[] coords = getRowAndColumn(square);
//System.out.println("[" + coords[0] + "][" + coords[1] + "]");
board[coords[0]][coords[1]] = c;
return "VALID";
} else {
System.out.println("Space Is Occupied");
return "OCCUPIED";
}
}
public boolean spaceFull(char[][] b, int square) {
return (twoDimenToOneDimen(b).get(square - 1) == 'X' || twoDimenToOneDimen(b).get(square - 1) == 'O');
}
Computer Class
public void makeMove() {
int square;
//Checks For Any Winning Computer Moves
System.out.println("Here");
if ((square = nextMoveWinCheck(playerChar)) != 0) {
board.addToBoard(playerChar, square);
return;
//Checks For Any Opponent Winning Moves
} else if ((square = nextMoveWinCheck(opponentChar)) != 0) {
board.addToBoard(playerChar, square);
return;
} else {
//Checks If Computer Has First Move
if (boardEmpty()) {
board.addToBoard(playerChar, 9);
return;
} else {
//Moves Into Opposite Corner if Bottom Corner is Occupied By Itself
if (!board.spaceFull(board.board,1) && board.board[2][2] == playerChar) {
board.addToBoard(playerChar, 1);
return;
//Move Into Center If Second Move or Possible
} else if (!board.spaceFull(board.board,5)) {
board.addToBoard(playerChar, 5);
return;
} else if ((square = emptyCorner()) != 0) {
board.addToBoard(playerChar, square);
return;
} else {
board.addToBoard(playerChar, randomEmptySpot());
return;
}
}
}
}
If you want the full code, it's:
Computer
Board
Player
Tic-Tac-Toe Main Class
Your problem lies in your class Computer. On line 57, you assign board.board to tempBoard. However tempBoard still holds the reference to the object board.board, so whatever modifications you make there is reflected on the actual board. To resolve this, COPY the board values to tempboard:
http://www.java2s.com/Code/Java/Collections-Data-Structure/clonetwodimensionalarray.htm
I'm trying to get an object to wander around the world randomly.
This object has a 25% chance of turning left, 25% chance of turning right, and 50% chance of moving straight.
I have to ensure that the random direction chosen is not one that will take the object out of bounds. I used getGridX() and getGridY() to check the current object's coordinate position to determine if it is at the edge. And I've only actively considered 2 of the corners of the world.
However, it keeps getting forced outside the world.
What is my code doing wrong?
import sofia.micro.*;
import sofia.util.Random;
//-------------------------------------------------------------------------
public class Food extends SimpleActor
{
//~ Constructor ...........................................................
/**
* Creates a new Food object.
*/
public Food()
{
super();
}
//~ Methods ...............................................................
// ----------------------------------------------------------
/**
* 25% chance of turning left
* 25% chance of turning right
* 50% chance of moving forward
*/
public void act()
{
int value = Random.generator().nextInt(100);
this.changeDirection();
if (value < 25)
{
this.turn(LEFT);
this.changeDirection();
}
else if (value < 50)
{
this.turn(RIGHT);
this.changeDirection();
}
else
{
this.move();
this.changeDirection();
}
}
/**
* make a U-turn
*/
public void turnAround()
{
this.turn(RIGHT);
this.turn(RIGHT);
}
/**
* detects edge condition and moves away
*/
public void changeDirection()
{
if ((this.getGridY() == this.getWorld().getHeight()) ||
(this.getGridX() == this.getWorld().getWidth()))
{
this.turnAround();
this.move();
}
if ((this.getGridY() == 0) || (this.getGridX() == 0))
{
this.turnAround();
this.move();
}
if ((this.getGridY() == this.getWorld().getHeight()) &&
(this.getGridX() == this.getWorld().getWidth()))
{
this.turnAround();
this.move();
}
if ((this.getGridY() == 0) && (this.getGridX() == 0))
{
this.turnAround();
this.move();
}
}
}
It looks like the following condition is written twice. If you're facing out of bounds, wouldn't you do a 360, instead of a 180? I would remove the latter 2 if statements.
if ((this.getGridY() == this.getWorld().getHeight()) &&
(this.getGridX() == this.getWorld().getWidth()))
{
this.turnAround();
this.move();
}
Assuming that the turn() method is properly implemented (I don't see it in your code), here is one problem I found:
if (value < 25)
{
this.turn(LEFT);
this.changeDirection();
}
else if (value < 50)
{
this.turn(RIGHT);
this.changeDirection();
}
else
{
this.move(); // < --- You shouldn't be using this here
this.changeDirection();
}
Remove that line. Because when this statement is reached, it is possible that your actor is in an edge and facing into emptiness - and you are literally telling it to move forward.
Instead, remove the line and just call changeDirection(), which will cause the actor to turn 180 degrees. I see that changeDirection() will also cause the actor move, so basically your actor will move away from the edge.
In my method under the if statement:
if (currentLocationX == 0 && currentLocationY == 4)
I have a break statement that should make the program exit out of the while loop and return true for 'answer' and for the method. Yet after some testing it seems that after returning true for 'answer', it goes back into the while loop giving the wrong results int the end. Why is my break statement not doing what it's supposed to? Thank you!
P.S. (this method calls on some other method that were not relevant to mention here)
public boolean solveMaze()
{
boolean answer = false;
int currentLocationX;
int currentLocationY;
//push starting location
pushX(2);
pushY(1);
while((isEmptyX() == false) && (isEmptyY() == false))
{
printMaze();
System.out.println();
currentLocationX = popX();
currentLocationY = popY();
//mark current location as visited
visited(currentLocationX, currentLocationY, maze);
System.out.println("Current Location: " + currentLocationX + ", " + currentLocationY);
if (currentLocationX == 0 && currentLocationY == 4)
{
answer = true;
break;
}
else
{
//push all unvisited OPEN neighbor locations into stack
if (checkEast(currentLocationX, currentLocationY) == 0)
{
pushX(eastX(currentLocationX));
pushY(eastY(currentLocationY));
}
else;
if (checkSouth(currentLocationX, currentLocationY)== 0)
{
pushX(southX(currentLocationX));
pushY(southY(currentLocationY));
}
else;
if (checkWest(currentLocationX, currentLocationY)== 0)
{
pushX(westX(currentLocationX));
pushY(westY(currentLocationY));
}
else;
if (checkNorth(currentLocationX, currentLocationY)== 0)
{
pushX (northX(currentLocationX));
pushY(northY(currentLocationY));
}
else;
}
}
return answer;
}
I wrote out the basic logic of your method as
public static boolean solveMaze() {
boolean answer = false;
int currentLocationX = 0;
int currentLocationY = 4;
while (true) {
if (currentLocationX == 0 && currentLocationY == 4) {
System.out.println("Hit the break");
break;
} else {
System.out.println("Missed the break");
}
}
return answer;
}
and if you execute it you get Hit the break. So your solveMaze() method is fine in terms of breaking out of the loop once it satisfies your if-statement. I would say that if you see your code subsequently going back into the while loop, it must be that solveMaze() was called a second time.
I need to override execute method of executor where I need to change the behavior that threads more than core pool size will be created only when queue is full.
However in real time applications this behavior is undesirable as it can lead to unending wait of task present in queue.
I have changed the execute method as below:
public void execute(Runnable command)
{
System.out.println("ActiveCount : " + getActiveCount() + " PoolSize : " + getPoolSize()
+ " QueueSize : " + getQueue().size() +" Idle Threads : " +(getPoolSize()-getActiveCount()));
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
else if (isRunning(c) && workQueue.offer(command))
{
int recheck = ctl.get();
if (getActiveCount() < workerCountOf(recheck) && isRunning(recheck) && workQueue.offer(command)) {
return;
}
if (addWorker(command, false)) {
return;
}
else if (! isRunning(recheck) && remove(command))
{
reject(command);
}
else if (workerCountOf(recheck) == 0)
{
addWorker(null, false);
}
}
else
{
reject(command); // add task to the queue
}
}
Trying to achieve:
CoreThreads -> Non-CoreThreads -> Queue instead of CoreThreads -> Queue -> Non-CoreThreads.
I dont understand why you need to change execute method, I think, max pool size should not be preferred over queue, as I can see in you code.
I had same problem and you can follow the link :
click to follow the thread.
I feel this should be you last choice, try something else first.