Guess the next position of simultaneously running threads - java

I am making a maze and two threads are moving on it simultaneously.The problem they mustn't share the same position at same time. I don't know how I can do it. Is it possible to know where they will move next and prevent the other thread from moving to that position? Please give me an idea. Thanks.
Here the code :
public int[][] visitedCell=new int[15][15]; // holds how many times visited for each cell
public boolean cntrl=true,repeat=true,end;
public int r=0;
public int cnt;
public boolean find;
public void decision(int posX,int posY){
int distanceToExit;
cnt=0; // holds how many cell is free around the cell which thread is on
r=0;
end=false; // checks robot found exit
find=false; // checks suitable cell found to move in next step
posX=posX/40; // all cells are 40*40 dimension.since it is divided 40 to find poisition
posY=posY/40; // found y position
int[][] neighbours={{posX,posY+1},{posX+1,posY+1},{posX+1,posY},{posX+1,posY-1},{posX,posY-1},{posX-1,posY-1},{posX-1,posY},{posX-1,posY+1}}; // all 8 neighbours of a cell
int[][] freeCellChoises = new int[8][2]; // holds free cells to move
int[][] distanceCell=new int[8][2];
for(int i=0;i<8;i++){ // checks which neighbour cells are free
if((neighbours[i][0] >0 && neighbours[i][0] <14) && (neighbours[i][1] >0 && neighbours[i][1] < 14) || (neighbours[i][0]==1 && neighbours[i][1]==14) || (neighbours[i][0]==14 && neighbours[i][1]==1) ) // [1,14] = enter position and [14,1]= exit position
{
if(Draw.paintArray[neighbours[i][0]][neighbours[i][1]]==0){// cell is free.it is eligible
freeCellChoises[cnt][0]=neighbours[i][0]; // load eligible cells this array
freeCellChoises[cnt][1]=neighbours[i][1];
distanceToExit=(int) Math.sqrt((Math.pow(neighbours[i][0]-560, 2)+Math.pow(neighbours[i][1]-40,2)));
distanceCell[cnt][0]=cnt;
distanceCell[cnt][1]=distanceToExit;
cnt++;}
}
} // eligible cells are ready anymore
if(Frame.radButSel==1){ // random movement
int no=rndm.nextInt(cnt); // choose one of the eligible cell randomly
x=freeCellChoises[no][0] * 40;
y=freeCellChoises[no][1] * 40;
}
if(Frame.radButSel==2){ // closed way movement ( find the most clodes cell to the exit ) .Exit is [14,1].So x must be max, y must be min to a cell has priority
int maxX=freeCellChoises[0][0];
int minY=freeCellChoises[0][1];
int selection1=0,selection2=0;
for(int i=0;i<cnt;i++){ // x i byk y si kck sec
if(freeCellChoises[i][0]> maxX){
maxX=freeCellChoises[i][0];
selection1=i;}
if(freeCellChoises[i][1]<minY){
minY=freeCellChoises[i][1];
selection2=i;
}
}
if(cnt!=0) // checks there is a priority cell
r=rndm.nextInt(2)+1; // selects one of the priority cell
if(r==1 && visitedCell[freeCellChoises[selection1][0]][freeCellChoises[selection1][1]] <2){ //selection1.same cell musnt be visited more than 2 times
x=freeCellChoises[selection1][0] * 40;
y=freeCellChoises[selection1][1] * 40;}
else if(r==2 && visitedCell[freeCellChoises[selection2][0]][freeCellChoises[selection2][1]] <2){//selection2
x=freeCellChoises[selection2][0] * 40;
y=freeCellChoises[selection2][1] * 40;}
else{ // applies when there is not any priority cell
System.out.println("oncelik yok");
int repeat =0;
while(repeat<cnt){
r=rndm.nextInt(cnt); // choose one of the eligible cell
x=freeCellChoises[r][0] * 40;
y=freeCellChoises[r][1] * 40;
if(visitedCell[freeCellChoises[r][0]][freeCellChoises[r][1]] <2){
repeat=10;
}
else
repeat++;
}System.out.println("x="+x+"y="+y);
}
}
if(Frame.radButSel==3){
}
if(x==560 && y==40){ // checks decided cell is exit point
Action.pool.shutdownNow();// thread finished
end=true;
Main.butAct++; // when butAct=2 , "RESULT" button will be active
timer.stopTime();} // stops time for the thread
distance=(int) Math.sqrt(Math.pow(x-560,2) + Math.pow(y-40, 2));// calculates distance between thread - exit
}
public Action() throws InterruptedException{
pool=Executors.newFixedThreadPool(2); // two thread in the pool
robot1=new Robot(40,560); // starts enter position
robot2=new Robot(40,560); // starts enter position
pool.submit(robot1); // loads robot1 to pool
pool.submit(robot2);// loadss robot2 to pool
}
public void run() {
while(true){ // run threads always
try {
Frame.worker.pauseIfNeeded();} // checks whether pause button is pressed
catch (InterruptedException ex) {
Logger.getLogger(Robot.class.getName()).log(Level.SEVERE, null, ex);}
if(end==false){// not reach exit
try{
System.out.println(Thread.currentThread().getName());// displays current thread name
System.out.println("pozisyon x="+x+"y="+y);
decision(x,y); // thread makes decision to move
visitedCell[x/40][y/40]+=1; // increade number of visitide cell count for that cell in the array
visCell++; //increase visited cell count for the thread
Thread.sleep(300);} // thread sleeps for a while to observe movement changing
catch(Exception ex){
}
}
else{// found exit
Thread.currentThread().interrupt(); // Thread killed
if(Main.butAct==2)// after a thread found exit, checks if result button can be active anymore
Frame.button4.setEnabled(true); // activates result button
}
}//end while
}

Or you could do it something like this. The manager class is aware of the position of both threads, and the moveTo method checks that they don't coincide at the same location.
class MazeManager {
int x1, x2, y1, y2;
public synchronized boolean moveTo(int threadId, int x, int y) {
..
}
}

The most simple solution would be to "divide" the work in such a way that the two work regions (solutions/paths to be tried out) are mutually exclusive. A workaround would be to have a concurrent set of positions which would be checked by each thread before making a move.

You will have to use the concept of so called mutual exclusion. In the Java programming language, you will have to use the synchronized keyword to do the job for you. A simple example maybe seen at [1]:
public class SynchronizedCounter {
private int i = 0;
public synchronized void increment() {
i++;
}
public synchronized void decrement() {
i--;
}
public synchronized int value() {
return i;
}
}
Here you see a code that makes sure that only one thread is able to modify the value of the shared variable i. Note that the code uses this as the so-called "lock object". You may rewrite the code in the following way:
public class SynchronizedCounter {
private int i = 0;
public void increment() {
synchronized(this) {
i++;
}
}
public void decrement() {
synchronized(this) {
i--;
}
}
public int value() {
synchronized(this) {
return i;
}
}
}
Or you may want to create your own lock object and use it:
public class SynchronizedCounter {
private int i = 0;
private Object lock = new Object();
public void increment() {
synchronized(lock) {
i++;
}
}
public void decrement() {
synchronized(lock) {
i--;
}
}
public int value() {
synchronized(lock) {
return i;
}
}
}
Now any number of threads may call the methods of this object randomly, but only one thread at one time will be able to pass the lock and do the actual modification.
[1] http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

Have the class that manages the maze force the threads to synchronize through itself, and make requests to change their position. The maze manager can then allow or deny requests to move based on the position of other threads.

Like Sanjay says, prevention is better than cure. You can partition the cells traversed by the two robots such that they never share the same cell.
If that is not possible, the cure is to use locks for each of the cells. Robots obtain the corresponding lock before moving into the cell and release the lock when done. This will cause a robot to wait if it is trying to enter the same cell as another robot. This is a more decentralized approach than having the maze manager control the moves and will result in less contention.

Related

How should I make my getMove() method interact with my GUI in my chess application?

I'm developing an application in Java to help me land my first job as a junior developer. It's a chess game with a GUI that both human players click on from the same machine.
When it's, say, white's turn to move, the application calls white's getMove(Interface interaction) method until a valid MoveAttempt is returned. Here's the getMove(Interface interaction) method of HumanPlayer:
public MoveAttempt getMove(Interface interaction) {
while(!interaction.selectionMade()) {
}
byte pieceFile = interaction.getPenultimateFile();
byte pieceRank = interaction.getPenultimateRank();
byte toFile = interaction.getUltimateFile();
byte toRank = interaction.getUltimateRank();
return new MoveAttempt(pieceFile, pieceRank, toFile, toRank, getIsWhite());
}
penultimateFile, penultimateRank, ultimateFile and ultimateRank are supposed to store the file (column) and rank (row) of the last two chess tiles clicked. This is achieved through this actionPerformed(ActionEvent event) which Interface has because it implements ActionListener
public void actionPerformed(ActionEvent event) {
LocalizedButton button = (LocalizedButton) event.getSource();
if(penultimateFile == -1) {
penultimateFile = button.getFile();
penultimateRank = button.getRank();
}
else {
ultimateFile = button.getFile();
ultimateRank = button.getRank();
}
}
and by calling this method before each call to getMove(Interface interaction)
public void resetClicks() {
penultimateFile = -1;
penultimateRank = -1;
ultimateFile = -1;
ultimateRank = -1;
}
So the idea is that a move attempt is not made until someone has clicked on two chess squares which is why I have a while loop indefinitely calling selectionMade():
public boolean selectionMade() {
return penultimateFile != -1 && penultimateRank != -1 && ultimateFile != -1 && ultimateRank != -1;
}
This didn't work---pieces didn't move---so in an attempt to see what was happening I put this print statement
System.out.println(interaction.getPenultimateFile() + ", " +
interaction.getPenultimateRank() + ", " +
interaction.getUltimateFile() + ", " +
interaction.getUltimateRank());
into the while loop to see what was going on and now it works---pieces move---except I may have encountered times in which it didn't work but I last I tried I couldn't get it to fail.
I don't want to print anything to the console; what should I do in lieu of having this while loop?
Edit: Putting boolean lol = 0 just above the loop and lol = !lol in the loop doesn't allow the code to work. Neither does calling doNothing().
Edit: Here's the source code: https://github.com/JosephBGriffith/Chess
Right now only the pawns work because I have other bugs that I need to fix. En passant works except the opponent piece doesn't get eliminated.
I would invert the control, so that the UI pushes moves to the game, rather than the game trying to pull moves from the UI.
So your game class might have:
class Game {
boolean move(int fromFile, int fromRank, int toFile, int toRank) { ... }
...
}
If the move wasn't legal (e.g. if it was the other player's turn) then move returns false and the move doesn't occur. That is, the internal state of the Game is unchanged.
And your actionPerformed method becomes:
public void actionPerformed(ActionEvent event) {
LocalizedButton button = (LocalizedButton) event.getSource();
if(penultimateFile == -1) {
penultimateFile = button.getFile();
penultimateRank = button.getRank();
}
else {
game.move(penultimateFile, penultimateRank, button.getFile(), button.getRank());
penultimateFile = -1;
}
}
You could use the return value of move to provide some feedback to the user if the move is illegal.
Something to note about this suggestion is that move is executed on the Swing event thread. In theory this is bad practice, although unless your move method is very slow it won't matter.
Read https://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html and consider whether you want to use invokeLater.

Java - Loop gets executed, but header doesnt fit condition

This function should check if the explosion hit a box and should be canceled on the first box it hits.
For example bsp.getBomb().getStrength() is currently 2, when a box is hit i=3, but the loop is executed one more time even if the condition isn't met, why is that?
public void detectBomb(BombSpritePair bsp) {
for(int i = 0; i <= bsp.getBomb().getStrength(); i++) {
if(bd.detect(bsp.getBomb().getX(), bsp.getBomb().getY()+i)) {
Sprite sprite = new Sprite(new Texture("gras.png"));
sprite.setPosition(bsp.getBomb().getX()*16, (bsp.getBomb().getY()+i)*16);
// i = bsp.getBomb().getStrength()+1;
sprites.add(sprite);
System.out.println("RIP"+i);
System.out.println(bsp.getBomb().getStrength());
break;
}
}
}
Try adding break to the loop:
public void detectBomb(BombSpritePair bsp) {
for(int i = 0; i <= bsp.getBomb().getStrength(); i++) {
if(bd.detect(bsp.getBomb().getX(), bsp.getBomb().getY() + i)) {
Sprite sprite = new Sprite(new Texture("gras.png"));
sprite.setPosition(bsp.getBomb().getX()*16, (bsp.getBomb().getY()+i)*16);
sprites.add(sprite);
System.out.println("RIP"+i);
System.out.println(bsp.getBomb().getStrength());
break;
}
}
}
You may be seeing duplicate print statements if you are calling the detectBomb method multiple times. Putting a breakpoint or print statement at the beginning of this method will help determine what the problem is.
Another thing to keep in mind is that you are creating a new Texture for the Sprite every time the method get executed - it would be wise to only instantiate the Texture once and share it with all subsequent Sprite instances that require it.

Storing Blocks for Replace Later

Here's my snippet of code. I have Lists for the blocks and player. All I need is for after the five seconds in that runnable is up, it'll replace the blocks that were previously replaced, assigning a player to get the blocks.
#EventHandler
public void onSnowballHit(ProjectileHitEvent e) {
// If it's a snowball...
if (e.getEntity() instanceof Snowball) {
Snowball snowball = (Snowball) e.getEntity();
final Player p = (Player) snowball.getShooter();
// ...if a player threw it...
if (snowball.getShooter() instanceof Player) {
// Make a Player from the Entity
BlockIterator iterator = new BlockIterator(e.getEntity().getWorld(),
e.getEntity().getLocation().toVector(), e.getEntity().getVelocity().normalize(),
0.0D, 4);
// Make a block
Block hitBlock = null;
// Loop through possible blocks
while (iterator.hasNext()) {
// Set the hitBlock to the current block we're checking
hitBlock = iterator.next();
// If it's not air, STOP!
if (!hitBlock.getType().equals(Material.AIR)) {
break;
}
}
int min = 1;
int max = 15;
Random r = new Random();
byte clayBlocks = (byte) (r.nextInt(max - min + 1) + min);
paintBlockList.add(hitBlock);
painters.add(p);
// Set it to stained clay
hitBlock.setType(Material.STAINED_CLAY);
// red = 14, blue = 11 (data values)
hitBlock.setData(clayBlocks);
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
public void run(){
if(painters.contains(p)){
painters.remove(p);
}
}
}, 100);
}
}
}
You could do it the same way you remove the Player from the painters list. Once you've found the first solid block (hitBlock) create a new final reference so that you can access it in the Runnable, for example like this:
final Block solidBlock = hitBlock;
To return the block to the state it was before you changed its type and data, you could keep track of those attributes:
final byte previousData = solidBlock.getData();
final Material previousType = solidBlock.getType();
Then in your run() method you can simply change the block back if it is still at that point different like so:
if (solidBlock.getType() != previousType) {
solidBlock.setType(previousType);
}
if (solidBlock.getData() != previousType) {
solidBlock.setData(previousData);
}
I'm sure there's a cleaner, nicer way to do it but this might be good enough for your purposes (I did find a glitch where if you throw two snowballs at the same block, it won't revert to the true original block but to a stained clay block because of the way the future Runnable tasks are written here, to fix this you'd need to write this completely differently and keep track of more things).

Code works sometime but not others (memory or thread issue)

I am having this odd issue, and I am not sure what is causing it. Some times the issue isn't even there. From what I am guessing, is that this is a Java memory issue or some sort of threading issue.
I have a Ship and the ship shoots Bullets If I hold down the Space key the ship shoots the bullets. I have the bullets set to fire off every 200 milliseconds. Some times they shoot fine and move at the same speed! Other times, they shoot they move at different speeds. What could cause this?
package JGame.Actions;
import JGame.GameObject.GameObject;
import javax.swing.AbstractAction;
public class MoveAction extends Action implements Runnable{
protected GameObject obj;
protected int endX = 0, endY = 0;
protected int moveAmount = 0;
protected Thread thread;
public void moveToY(GameObject obj, int y, int amount, AbstractAction complete){
this.obj = obj;
this.endY = y;
this.moveAmount = amount;
this.complete = complete;
thread = new Thread(this);
thread.start();
}
public void run(){
try{
boolean run = true;
while(run){
int objY = obj.getY();
if(objY > this.endY){
obj.setY(obj.getY() - 1);
}else if(objY < this.endY){
obj.setY(obj.getY() + 1);
}else{
run = false;
this.actionComplete();
}
thread.sleep(moveAmount);
}
}catch(Exception e){
}
}
}
Action Complete:
package JGame.Actions;
import javax.swing.AbstractAction;
public class Action {
protected boolean actionComplete = false;
protected AbstractAction complete;
public void actionComplete(){
complete.actionPerformed(null);
}
}
In my code I call moveToY it is a very simple call but sometime the Bullets move at different speeds (wrong), and others they move at the same speed (right). I don't know if it would help to mention that as the bullets move sometimes they slow down for a second or two then speed back up to the correct speed.
Edit: Main Thread
The following is my main thread with the paintComponent
#Override
public void run(){
try{
while(true){
// Check for key press events
Iterator actions = KeyboardMap.map.entrySet().iterator();
while(actions.hasNext()){
Map.Entry ap = (Map.Entry)actions.next();
Mapping mp = (Mapping)ap.getValue();
if(mp.pressed){
mp.run();
}
}
// Check for click mouse events
Iterator actions2 = MouseMap.map.entrySet().iterator();
while(actions2.hasNext()){
Map.Entry ap = (Map.Entry)actions2.next();
Mapping mp = (Mapping)ap.getValue();
if(mp.pressed){
mp.run();
}
}
for(GameObject go : gameObjects){
if(!go.getLeaveScreen()){
int goWidth = go.getWidth();
int goHeight = go.getHeight();
int goX = go.getX();
int goY = go.getY();
int gameWidth = Game.width;
int gameHeight = Game.height;
if(goX + goWidth >= gameWidth){
go.setX(gameWidth - goWidth);
}
if(goX <= 0){
go.setX(0);
}
if(goY + goHeight >= gameHeight){
go.setY(gameHeight - goHeight);
}
if(goY <= 0){
go.setY(0);
}
}
}
this.repaint();
Thread.sleep(roomSpeed);
}
}catch(Exception e){
}
}
public void paintComponent(Graphics g){
try{
g.drawImage(bg, 0, 0, this);
for(int i = 0; i < gameObjects.size(); i++){
GameObject go = gameObjects.get(i);
g.drawImage(go.getSprite(), go.getX(), go.getY(), this);
}
}catch(Exception e){
}
}
Well, I guess you have a large number of concurrent threads running (one by moving bullet), and you expect each thread to wake up after exactly moveAmount milliseconds. You can't have such a guarantee, because the thread scheduler allows each thread to run for some time one at a time, and you might thus have glitches.
Another problem is that you seem to execute modification on Swing components out of the event dispatch thread, which is clearly forbidden by Swing's threading policy.
The most important thing to change in your code is don't model time with Thread.sleep. Use a Swing Timer, which you'll schedule to execute every moveAmount milliseconds and, as a bonus, the code is executed on the Event Dispatch Thread with no effort on your part.
Inform yourself about the usage of multiple threads and how the processing structure of a game is made correctly.
The most important info for your case: You should only use ONE thread to process/move all your bullets and then render them.

Counters not decrementing or not being read in Breakout

Okay, I've got this game loop which never terminates --
public void run() {
setup();
addMouseListeners();
int Turns = NTURNS;
int TotalBricks = NBRICKS_PER_ROW * NBRICK_ROWS;
while ((Turns>0) && (TotalBricks>0)) {
moveBall();
checkForCollision();
pause(DELAY);
}
System.exit(0);
}
-- even though I have this method decrementing the Turns value every time the ball is missed:
private void checkForCollision() {
GObject collider = getCollidingObject();
if (collider !=null) {
if (collider == Paddle) {
vy= -vy;
}
else {
vy= -vy;
remove(collider);
TotalBricks = TotalBricks - 1;
}
}
if((ball.getX()>=(WIDTH-BALL_RADIUS)) || (ball.getX()<=0)) {
vx = -vx;
}
if(ball.getY()<=0) {
vy = -vy;
}
if(ball.getY()>=HEIGHT) {
Turns = Turns -1;
remove(ball);
newBall();
}
}
plus this
private int Turns;
at the bottom to ensure that the variable is shared among both methods.
No matter how many times the ball is missed, the game never stops.
What am I missing?
Thx
You are declaring a new Turns variable in your run method which is what is getting used by that method since it has a more local scope. This is called variable shadowing. Use a decent Java IDE like Eclipse and it will warn you when you do this. It's almost always a mistake.
http://www.xyzws.com/Javafaq/what-is-variable-hiding-and-shadowing/15
You're declaring your Turns variable twice, once for the entire class and once for the the run() method. Since you are also checking the value of the Turns variable that you've declared in the run() method, it never decreases because the one being used in checkForCollision() isn't the one that's being checked in the while loop.
In run(), this:
int Turns = NTURNS;
needs to be:
Turns = NTURNS;

Categories

Resources