Turning around at the edges of a world (Java) - java

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.

Related

Turning around at edges of a world

For a project I am supposed to write code that will have an actor have a chance to turn left or right 25% and then move 50% and then it is also supposed to avoid running out of bounds. The following code is what I have so far but I am not sure what isn't working because i am still having problem keeping the actor inbounds. Thanks
/**
* Creates a new Food object.
*/
public Food()
{
super();
}
//~ Methods ...............................................................
// ----------------------------------------------------------
/**
* Take one step, either forward or after turning left or right.
*/
public void act()
{
int x = Random.generator().nextInt(100);
this.changeDirection();
if (x < 25)
{
this.turn(LEFT);
}
else if ((25 < x) && ( x < 50))
{
this.turn(RIGHT);
}
else
{
this.move();
}
}
public void turnAround()
{
this.turn(RIGHT);
this.turn(RIGHT);
}
public void changeDirection()
{
if ((this.getGridY() == this.getWorld().getHeight() ||
this.getGridX() == this.getWorld().getWidth()))
{
this.turnAround();
this.move();
}
else if ((this.getGridY() == 0 || this.getGridX() == 0))
{
this.turnAround();
this.move();
}
else if ((this.getGridY() == this.getWorld().getHeight()) &&
this.getGridX() == this.getWorld().getWidth())
{
this.turnAround();
this.move();
}
else if ((this.getGridY() == 0) && (this.getGridX() == 0))
{
this.turnAround();
this.move();
}
}

Function Repeating Itself Even After Returning

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

Looping through LinkedLinkst in two places gives error

So I am making a little game in Java, and in the game you have Entities which are stored in a LinkedList. In the tick method I iterate through the Entities' LinkedList like this:
#Override
public void tick(float delta) {
for (Entity e : entities) {
e.tick(delta);
}
player.tick(delta);
}
And the same for the render method
#Override
public void render(Graphics g) {
g.setColor(Color.DARK_GRAY);
g.fillRect(0, 0, Game.WIDTH, Game.HEIGHT);
for(Entity e : entities) {
e.render(g);
}
player.render(g);
}
One of the Entities is a class called Block. And in the Block class there is a function which returns if a block is near, in this function I also iterate through the Entities' LinkedList and it's called from the following tick method in Block:
#Override
public void tick(float delta) {
if (color == Color.WHITE) {
if (getSurrounding(-32, -32) != null && getSurrounding(-32, -32).getColor() == Color.BLACK) {
if (getSurrounding(-32, -32).getStrength() < strength) {
getSurrounding(-32, -32).setStrength(-50);
}
}
}
if (!inGame.entities.isEmpty() && strength <= 0) {
inGame.entities.remove(this); // <------ REMOVING AN ELEMENT
}
}
public Block getSurrounding(int xOffset, int yOffset) {
for (Entity e : inGame.entities) {
if (e instanceof Block) {
if (x + xOffset == e.getX() && y + yOffset == e.getY()) {
return (Block) e;
}
}
}
return null;
}
(This function is called and used in the tick method of the block by the way)
Now everytime I run the game, the game starts and runs normal for a couple milliseconds and then it throws this exception:
Exception in thread "Thread-2" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
at java.util.LinkedList$ListItr.next(Unknown Source)
at _47b3n.game.engine.gamestate.gamestates.InGame.tick(InGame.java:36)
at _47b3n.game.engine.Handler.tick(Handler.java:17)
at _47b3n.game.engine.Game.tick(Game.java:70)
at _47b3n.game.engine.Game.run(Game.java:52)
at java.lang.Thread.run(Unknown Source)
(The first two code samples are in the InGame.java file, and line 36 is the for-loop in the tick method)
Now how do I stop this error?
ConcurrentModificationException usually relates to modifying the list while iterating through it within a loop.
My assumption is that you are removing an element while you are iterating through.
In order to stop this from happening, i would recommend saving the object you want to delete in a variable while it is in the loop (and has met some condition), then removing it from the list after the loop has completed.
Edit: based on the updated question, you are removing an element within the tick method. I would not do this here, but return the element that you would like to remove and remove it only when you are no longer iterating the list you are removing from.
Possible solution:
I would create another method to check the strength of the Entity and calling that from the tick method (this is to save the tick method having to return an object to delete) as so:
#Override
public void tick(float delta) {
Entity removeEntity = null;
for (Entity e : entities) {
e.tick(delta);
if(e.checkStrength()){
removeEntity = e;
break;
}
}
if(removeEntity != null){
entities.remove(removeEntity);
}
player.tick(delta);
}
In the entity class:
public boolean checkStrength(){
if (!inGame.entities.isEmpty() && strength <= 0) {
return true;
}
return false;
}
Just so you know this is not the best solution by far, but should get you through the problem you have now. Be sure to clean your code up when you have time.
You are removing entities in the tick() method... while in the method, you are still iterating over the entities in the outer tick method... because you're modifying the list inside e.tick(), the list is changing, which causes the next iteration to fail... replacing the method call to e.tick() with the inline method demonstrates the problem more clearly:
#Override
public void tick(float delta) {
for (Entity e : entities) {
//e.tick(delta); --inline below
if (color == Color.WHITE) {
if (getSurrounding(-32, -32) != null && getSurrounding(-32, -32).getColor() == Color.BLACK) {
if (getSurrounding(-32, -32).getStrength() < strength) {
getSurrounding(-32, -32).setStrength(-50);
}
}
}
if (!inGame.entities.isEmpty() && strength <= 0) {
inGame.entities.remove(this); // <------ REMOVING AN ELEMENT
}
}
}
Note that where you have remarked you are "REMOVING AN ELEMENT" is inside the outer-most loop, that's the cause of your issue.
Edit: Suggested solution as others have advised, try something like this (just showing the removal block):
List toRemove = new ArrayList() //somewhere earlier in the code
if (!inGame.entities.isEmpty() && strength <= 0) {
//inGame.entities.remove(this); // <------ REMOVING AN ELEMENT
toRemove.add(this);
}
return toRemove;
Then in the calling function, after you've finished all your iterating
entities.removeAll(toRemove);
A solution using an Iterator:
Replace the first code-block with the following:
public void tick(float delta) {
for (Iterator<Entity> iterator = entities.iterator(); iterator.hasNext();) {
boolean remove = e.tick(delta);
if(remove) {
iterator.remove();
}
}
player.tick(delta);
}
then replace the other tick method with this:
public boolean tick(float delta) {
if (color == Color.WHITE) {
if (getSurrounding(-32, -32) != null && getSurrounding(-32, -32).getColor() == Color.BLACK) {
if (getSurrounding(-32, -32).getStrength() < strength) {
getSurrounding(-32, -32).setStrength(-50);
}
}
}
if (!inGame.entities.isEmpty() && strength <= 0) {
return true;
}
return false;
}
This should solve your problem. The methods return type has to change, so that we have an indicator when to remove any elements and when not. Every time the tick returns true, the corresponding element will be removed

Alpha-beta pruning

I've implemented the following MiniMax algorithm for my Android Reversi game:
#Override
public Field findBestMove(GameBoard gb, int depth, boolean player)
{
/** maximum depth of search reached, we stop */
if(depth >= max_depth) return null;
//player = (depth+1)%2 + 1;
/** getting a list of moves to chose from */
ArrayList <Field> moves = findAllPossibleMoves(gb, player);
Field best_move = null;
/** iterating over all possible moves, to find the best one */
for (int i=0; i<moves.size(); i++)
{
/** board to simulate moves */
GameBoard temp_board = new GameBoard(gb);
/** getting the current move */
Field move = moves.get(i);
/** simulating the move for the current node */
game.move(move, temp_board, player);
Log.i("board", "Depth:"+depth+" Player:"+player+" Move:"+i+" Rating:"+evaluate(temp_board));
Log.i("board", ""+moves.get(i).getX()+","+moves.get(i).getY());
temp_board.printBoard();
/** getting to the next inferior node */
Field best_deep_move = findBestMove (temp_board, depth + 1, !player);
/** if the maximum depth is reached, we have a null, so we evaluate */
if (best_deep_move == null)
{
move.setRating(evaluate (temp_board));
}
/** if we are not the deepest possible, we get the rating from the lower node */
else
{
move.setRating(best_deep_move.getRating());
Log.i("eval", ""+best_deep_move.getRating());
}
if(best_move == null)
{
best_move = move;
}
else
{
Log.i("update", "Current move rating:"+move.getRating());
Log.i("update", "New move rating:"+best_move.getRating());
if (depth%2==0)
{
Log.i("update", "MAX player");
/** for us, we look for the maximum */
if (best_move.getRating() < move.getRating())
{
best_move = move;
}
}
else
{
Log.i("update", "MIN player");
/** for the opponent, we look for the minimum */
if (best_move.getRating() > move.getRating())
{
best_move = move;
}
}
Log.i("update", "Updated move rating"+best_move.getRating());
}
}
return best_move;
}
I've made myself familiar with the Alpha-Beta pruning in theory, though I'm having some trouble proceeding with applying that knowledge in this algorithm. Thanks in advance
There following changes that need to done to your code to implement alpha-beta pruning:-
pass a parameter public Field findBestMove(GameBoard gb, int depth, boolean player,int aplha_beta)
Stop recursion if current best_move will never affect alpha_beta of previous depth.
if(player == max && best_move!=null && aplha_beta <= best_move.getRating()) {
return(best_move);
}
if(player == min && best_move!=null && alpha_beta >= best_move.getRating()) {
return(best_move);
}
Field best_deep_move = findBestMove(temp_board,depth+1,!player,best_move.getRating());

Always the same thread gets CPU time

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.

Categories