I'm having some problems with a battleship solution I'm creating using Java. A random set of ships are loaded onto a 10x10 board. 1 2hit ships 2 3hit ships 1 4hit ship and 1 5hit ship (total of 17 hits goal)
I made a nested loop to basically fire at every cell coordinate until I either used 100 shots or destroyed all the ships. The GOAL is to find a way to sink all the ships with 50 or less shots. My problem is I can't tell where the ships are in accordance to their sink location (as it only tells me if I sunk a ship, not if I hit) Also, it doesn't tell me what kind of ship I've sunk, but I can figure that out a lot easier if I know how to solve the hit issue.
So how can I deduct if I've "hit" a ship? the only "hit" i can confirm on my board is the final shot triggered by the "a ship has sunk" message.
Edit: Sorry, I should also mention I do not have access to the battleship class, I only have a class I make that will be used to solve this problem. I was given some methods of the class such as:
" public BattleShip() - you need to call the constructor once in your program to create an instance of the battleship game.
public boolean shoot(Point shot) - you need to call this function to make each shot. See the sample source code for an example use.
public int numberOfShipsSunk() - returns the total number of ships sunk at any point during the game. It is a good idea to use this method to determine when a ship has been sunk.
public boolean allSunk() - returns a boolean value that indicates whether all the ships have been sunk.
public int totalShotsTaken() - returns the total number of shots taken. Your code needs to be responsible for ensuring the same shot is not taken more than once.
public ArrayList shipSizes() - returns an ArrayList of all of the ship sizes. The length of the array indicates how many ships are present.
public enum CellState - this enum object is very useful for marking cells has either Empty, Hit or Miss. It also has a convenience toString method so that can be used for printing purposes. You may also create your own Enum / Class for this in your code, but it is suggested that you use this instead of integers / characters to mark a Cell state"
The CellState property doesn't actually exist/is private so i can't use that. This is my loop.
x = 0;
for(int i = 0; i < 10; i++)
{
y = 0;
for(int j = 0; j < 10;j++)
{
if(x <=9 && y <=9) //X and Y are less than or equal to 9...
{
Point shot = new Point(x, y);
// At the end of each decision on where to fire next you need to shoot
if(shotTracker[x][y] == '-') // if space is free...
{ battleShip.shoot(shot);
if (sunkShip != battleShip.numberOfShipsSunk())
{
shotTracker[x][y] = 'O'; //The hit that sunk the ship
sunkShip++;
}
else
shotTracker[x][y] = '*'; // set space to fired miss
}
}
gameShots = battleShip.totalShotsTaken();
System.out.printf("You've shot %d times. The last shot's location was (%d,%d). You've hit something (not sure) times. You've sunk %d ships.\n", gameShots, x, y, battleShip.numberOfShipsSunk() );
if(battleShip.allSunk() || gameShots >= shotLimit)
{
break;
}
y+=3;
}
if(battleShip.allSunk() || gameShots >= shotLimit)
{
break;
}
x++;
}
if( gameShots >= shotLimit)
{
break;
}
}
And the output:
* - - * - - * - - *
* - - * - - * - - *
* - - * - - * - - *
* - - * - - * - - *
* - - * - - * - - *
* - - O - - * - - *
* - - * - - * - - *
* - - * - - * - - *
* - - * - - * - - *
This is a random output. I took a shot every 3 cells, and as you can see I sunk a ship but the O only tells me that was the finishing hit, so that was a vertical ship of unknown size on a random game...
Whatever code you are using to determine if a ship has been sunk should be able to tell you if a ship is hit. Otherwise, how does it aggregate to know its sunk?
I figured it out. My shot command
battleShip.shoot(shot)
evaluates to true or false, or hit or miss. When i check if true use "O" else use "*" O's pop up, so I guess I can do more work now. Thanks for trying to help!
Related
I creating pacman game. I have array of size 15x15, total 225fields. When I move from 255 to i.e.256, I got ArrayIndexOutOfBoundsException, this makes sense. So I can catch it and do some operation, lets say I set new starting point of pacman. But if I go from field 75 to 74 nothing happened.
So I asking, can I somehow catch this and do some operation, like I mention above.
You should not rely on ArrayIndexOutOfBoundsException for normal logic. This exception is an indication of a programming error.
Instead, you should check the index before incrementing it:
if (currentIndex == 255) {
// "special logic"
} else {
// "usual logic"
}
This way you can also handle any "special" indexes, e.g.
if ((currentIndex + 1) % 15 == 0) {
// "special logic"
} else {
// "usual logic"
}
Another point: consider using two indexes - x and y - if you are programming a 2-D game.
Every move modifies x and/or y, which can easily "wrap around" like in pacman (e.g. 13 -> 14 -> 15 -> 1 -> 2 -> ...).
And convert the (x,y)-Pair to an index only when you need to access the field element:
// Assuming that x and y are 1-based, not 0-based:
public FieldElement getFieldElementAtPosition(final int x, final int y) {
final int index = (y - 1) * FIELD_WIDTH + x - 1;
return fieldArray[index];
}
In Java, I am trying to implement the following equation for calculating the current velocity of a skydiver not neglecting air resistance.
v(t) = v(t-∆t) + (g - [(drag x crossArea x airDensity) / (2*mass)] *
v[(t-∆t)^2] ) * (∆t)
My problem is that I am not sure how to translate "v(t - ∆t)" into a code. Right now I have this method below, where as you can see I am using the method within itself to find the previous velocity. This has continued to result in a stack overflow error message, understandably.
(timeStep = ∆t)
public double calculateVelocity(double time){
double velocity;
velocity = calculateVelocity(time - timeStep)
+ (acceleration - ((drag * crossArea * airDensity)
/ (2 * massOfPerson))
* (calculateVelocity(time - timeStep)*(time * timeStep)))
* timeStep;
}
return velocity;
}
I am calling the above method in the method below. Assuming that the ending time = an int, will be the user input but written this way to be dynamic.
public void assignVelocitytoArrays(){
double currentTime = 0;
while(currentTime <= endingTime){
this.vFinal = calculateVelocity(currentTime);
currentTime += timeStep;
}
}
I would like to figure this out on my own, could someone give me a general direction? Is using a method within itself the right idea or am I completely off track?
The formula you want to implement is the recursive representation of a sequence, mathematiacally speaking.
Recursive sequences need a starting point, e.g.
v(0) = 0 (because a negative time does not make sense)
and a rule to calculate the next elements, e.g.
v(t) = v(t-∆t) + (g - [(drag x crossArea x airDensity) / (2*mass)] * v[(t-∆t)^2] ) * (∆t)
(btw: are you sure it has to be v([t-∆t]^2) instead of v([t-∆t])^2?)
So your approach to use recursion (calling a function within itself) to calculate a recursive sequence is correct.
In your implementation, you only forgot one detail: the starting point. How should your program know that v(0) is not defined be the rule, but by a definite value? So you must include it:
if(input value == starting point){
return starting point
}
else{
follow the rule
}
On a side note: you seem to be creating an ascending array of velocities. It would make sense to use the already calculated values in the array instead of recursion, so you don't have to calculate every step again and again.
This only works if you did indeed make a mistake in the rule.
double[] v = new double[maxTime/timeStep];
v[0] = 0; //starting point
for(int t = 1; t < maxSteps; t++){
v[t] = v[t-1] + (g - [(drag x crossArea x airDensity) / (2*mass)] * v[t-1]^2 ) * (∆t)
}
I'm working on some vector math, and I need to calculate the normal vector of a polygon.
My code:
//p is a parameter, is a Vec2, second point on first line
double[][] vert = getVerticies(); //[any length, # of verticies][2]
for(int i = 0; i < vert.length; i++) {
Vec2 cm = Vec2.ZERO_VEC;//first point on first line, always is <0, 0> as it is the origin
Vec2 rcm = getCM(); // just used to get relative positions.
Vec2 v1 = cm.sub(new Vec2(vert[i])); //the first point in one of all edges of the shape, second line
Vec2 v2 = cm.sub(new Vec2(i == vert.length - 1 ? vert[0] : vert[i + 1])); // the second point on the second line.
double den = (v2.getY() - v1.getY()) * (p.getX() - cm.getX()) - (v2.getX() - v1.getX()) * (p.getY() - cm.getY());
if(den == 0D) {
continue;
}
double a = ((v2.getX() - v1.getX()) * (cm.getY() - v1.getY()) - (v2.getY() - v1.getY()) * (cm.getX() - v1.getX())) / den;
double b = ((p.getX() - cm.getX()) * (cm.getY() - v1.getY()) - (p.getY() - cm.getY()) * (cm.getX() - v1.getX())) / den;
if(a >= 0D && a <= 1D && b >= 0D && b <= 1D) {
Vec2 mid = v2.add(v2.sub(v1).scale(0.5D)); //this is just normal vector calculation stuff, I know the error isn't here, as if it was, it would return a non-unit-scale vector.
return mid.uscale(); //hats the vector, returns
}
}
return p; // return the parameter, second point on first line, used as a contingency, should never actually run, as the first line is fully contained in the lines were testing against
I've done some debugging, and I just don't see what's happening. Can anyone tell me what's wrong with my math? It just seems to flow absolutely fine, but the math just doesn't seem right. My goal with this code is to determine the index of the two verticies that my line intersects.
Oops, figured it out by virtue of attempted to explain it. I need to be ray tracing, or use ray intersection testing.
If you are trying to calculate the normal of a polygon, it looks like you are trying to do something overly complicated. You can simply use cross product of two adjacent edges to get it. Even better, with a simple math explained here, you don't even need to calculate the edge vectors. Just take the cross product of each adjacent vertex pair and sum them up:
I am trying to reproduce the Game of Life but I've a bug. Cells are born according to design, but they don't die. This confuses me because my strategy for killing cells is the same as for giving birth to them. Here is a segment of the console output, 'x' represents living cells, '-' represents dead cells.
---------
---------
---------
---xx----
----x----
----x----
----xx---
---------
---------
---------
---------
---------
---xx----
----xx---
---xx----
----xx---
---------
---------
---------
---------
---------
---xxx---
----xx---
---xx----
---xxx---
---------
---------
And the relevant piece of code:
public class Life {
final static int WIDTH = 9, HEIGHT = 9;
void start(){
// scanning input file
char[][][] board = new char[WIDTH][HEIGHT][maxAllowedGenerations];
board = getInitialBoard(initialBoardString, maxAllowedGenerations, board);
for (int generation = 1; generation < maxAllowedGenerations; generation++){
for (int y = 0; y < HEIGHT; y++)
for (int x = 0; x < WIDTH; x++){
int numberOfNeighbours = getNumberOfNeighbours(x, y, generation - 1 , board);
if (board[x][y][generation - 1] == '-' && numberOfNeighbours == 3)
board[x][y][generation] = 'x';
else if (board[x][y][generation - 1] == 'x' && numberOfNeighbours < 2)
board[x][y][generation] = '-';
else board[x][y][generation] = board[x][y][generation - 1];
if (board[x][y][generation] == 'x')
ui.place(x, y, LifeUserInterface.ALIVE);
else
ui.place(x, y, LifeUserInterface.DEAD);
out.print(board[x][y][generation]);
}
out.println();
}
}
out.println("Max number of generations reached");
System.exit(0);
}
I agree with #elyashiv - if you change char[][][] board to SomeEnum[][][] board, with SomeEnum defined with values LIVE_CELL and DEAD_CELL that would make things much more readable.
Also, there is no such thing as an empty character ''. An empty String is simply a String with zero length (ie no characters), but '' makes no sense. You could use null, but then you'd have to move away from the primitive char declaration and use Character instead since primitives can't be null.
That said, much better to use enums to represent the data. If you want, you can even make your enum look like this so you can represent your X and empty characters like so:
public enum SomeEnum {
LIVE_CELL("X"),
DEAD_CELL("");
public final displayString;
SomeEnum(String displayString) {
this.displayString = displayString;
}
}
Then for your display you could reference SomeEnum.LIVE_CELL.displayString in your code
Found two bugs! One of them was impossible for you to spot because I didn't post the code in which it was contained: I am a cell at [x][y][g]. I was considering [x][y][g - 1] to be a neighbour, but that is of course me! I am not my own neighbour.
The other bug was a bit embarrasing actually. I had left out rule number 2... >.<
I also realize I should have posted the rules of the Game of Life instead of assuming that you all know them or that you would bother researching them. It's a bit late now of course, but I'll post them anyway in case you are interested. Also, I really reccomend the wiki article for anyone interested in self-organization.
Rules:
Live cells with < 2 live neighbours die, as if by loneliness.
Live cells with > 3 live neighbours die, as if by overpopulation.
Live cells with 2 || 3 live neighbours survive to the next generation.
Dead cells with 3 live neighbours are revived, as if by reproduction.
Thank you for all input!
i am trying to make my algorithm more efficient but for some reason its not working correctly could someone tell me if my logic is correct. The general problem is that if u have a height of 'x', and you can jump 'u' distance but you fall 'd' distance if you havent cleared the height already. i have to calculate the number of jumps.
Initial code works correctly
while(x-u>0) {
x=x-u+d;
i++;
}
i++;
more efficient code (for some reason fails some cases, I don't know which cases though)
int k=u-d;
if(x-u<=0){
i++;
} else {
int z=x/k;
if (x-((z-1)*k)-u <= 0) {
i+=z;
} else {
i=i+z+1;
}
}
let me try and clarify the problem you have a wall of height X, you can jump up distance U but every time you jump you also slip down distance D.
so lets say if u have a wall of height x=4, u=4, d=1. Then you would only have to jump once because the first time you jump you have cleared the wall, so you dont slip down at all. now lets say x=6, u=4,d=1. Then you would have to jump twice because the first time you would jump up to 4 but fall 1 so you are at 3 then the next jump you clear the wall.
Okay, let's see. The last jump comes from the height of x - u or higher. The rest you have to cover in (u - d)-size steps, the number of such steps is of course (x - u)/(u - d).
After i-th step you are at height i * (u - d) + u (and falling down). So, in approx. (x - u)/(u - d) steps you are at height x - u + u = x. Recalling that the number of steps should be a whole number, we get the final result:
if (u >= x)
return 1;
if (u <= d)
throw "Impossible";
return ceil((x - u)/(u - d));
(ceil is a mathematical function returning the smallest integer not less than the given number.)