I am creating a simple maze game in java. The code reads a data file and assigns it to a String array. The player inputs what direction he or she would like to go in and each position contains a certain number of points (0, 1, or 2) that corresponds to the obstacleNumber (0, 1, or 2). I want to keep track of the points as well as the number of times the player has moved but I cannot figure out where to call my methods to make sure that the counting is correct. I'm sorry if this is a really stupid question but I am new to java!
The array is being filled correctly but I cannot count the moves and points.
import java.util.*;
import java.io.File;
public class Program12
{
static public void main( String [ ] args ) throws Exception
{
if(args.length != 1) {
System.out.println("Error -- usage is: java Lab11 roomData.txt");
System.exit(0);
}
File newFile = new File(args[0]);
Scanner inputFile = new Scanner(newFile);
int numberOfRows = inputFile.nextInt();
int numberOfColumns = inputFile.nextInt();
Room[][] game;
game = new Room[numberOfRows][numberOfColumns];
int rowNumber = 0;
int columnNumber = 0;
int moves = 0;
int points = 0;
for(int i = 0; i < numberOfRows; i++)
{
for (int j = 0; j < numberOfColumns; j++)
{
String obstacle = inputFile.nextLine();
int obstacleNumber = inputFile.nextInt();
Room room = new Room(obstacle, obstacleNumber);
game[i][j] = room;
}
System.out.println();
countPoints(obstacleNumber, points);
}
while(true)
{
printPlayerLocation(numberOfRows, numberOfColumns, rowNumber, columnNumber);
System.out.println();
System.out.print("Enter up, down, left, or right to move: ");
Scanner userInput = new Scanner(System.in);
String in = userInput.nextLine();
if(in.equals("left") || in.equals("right") || in.equals("up") || in.equals("down"))
{
if (in.equalsIgnoreCase("up"))
{
rowNumber = rowNumber - 1;
}
if (in.equalsIgnoreCase("down"))
{
rowNumber = rowNumber + 1;
}
if (in.equalsIgnoreCase("left"))
{
columnNumber = columnNumber - 1;
}
if (in.equalsIgnoreCase("right"))
{
columnNumber = columnNumber + 1;
}
}
else
{
System.out.println("Input invalid! Please enter up, down, left, or right.");
}
try
{
System.out.println(game[columnNumber][rowNumber].toString());
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("You cannot leave the boardwalk during the hunt! Please start over.");
System.exit(0);
}
countMoves(in, moves);
//countPoints(obstacleNumber, points);
}
}
public static void printPlayerLocation(int numberOfRows, int numberOfColumns, int rowNumber, int columnNumber)
{
System.out.println();
System.out.print("***** PLAYER LOCATION *****");
String[][] game = new String[numberOfRows][numberOfColumns];
for (int i = 0; i < numberOfRows; i++)
{
for (int j = 0; j < numberOfColumns; j++)
{
game[i][j] = "*";
}
}
game[rowNumber][columnNumber] = "P";
for (int i = 0; i < numberOfRows; i++)
{
System.out.println();
for (int j = 0; j < numberOfColumns; j++)
{
System.out.printf("%-5s", game[i][j]);
}
}
System.out.println();
}
//doesn't correctly count the moves
public static void countMoves(String in, int moves)
{
if(in.equals("left") || in.equals("right") || in.equals("up") || in.equals("down"))
{
moves++;
}
System.out.println("You have used " + moves + " moves.");
}
//doesn't correctly count the points
public static void countPoints(int obstacleNumber, int points)
{
if(obstacleNumber == 0)
{
points = points;
}
if(obstacleNumber == 1)
{
points++;
}
if(obstacleNumber == 2)
{
points = points + 2;
}
System.out.println("You have obtained " + points + " points so far. Keep hunting!");
}
The data file has the size of the array (4 4) and an obstacleNumber and obstacle
0 this obstacleNumber would award 0 points
1 this obstacleNumber would award 1 point
2 this obstacleNumber would award 2 points
16 times to fill the array.
I would like the sample output to print the player location (which it does correctly), ask the user to input a direction (which it does correctly), print the text in the data file (again already done) and then print the number of moves already used and the amount of points the player has gained so far.
How do you correctly calculate the number of times the user typed "up, down, right, or left" and how many points does the user have so far? Thank you in advance for your help I sincerely appreciate your time.
The moves arent count right, because countMoves doesnt increment the Variable moves from the main function.
If you do :
System.out.println(moves);
countMoves(in, moves);
System.out.println(moves);
You will see that the value didnt changed.
So you could add a return value to countMoves and assingn moves with it :
moves = countMoves(in,moves);
Or you could increment the moves here :
if(in.equals("left") || in.equals("right") || in.equals("up") || in.equals("down"))
{
moves++;
if (in.equalsIgnoreCase("up"))
{
rowNumber = rowNumber - 1;
}
if (in.equalsIgnoreCase("down"))
{
rowNumber = rowNumber + 1;
}
if (in.equalsIgnoreCase("left"))
{ columnNumber = columnNumber - 1;
}
if (in.equalsIgnoreCase("right"))
{ columnNumber = columnNumber + 1;
}
}
The same with Points i think.
The line
points = points;
Would only make sense if you have a classvariable that would get the point value but assign a variable with its own value doenst make sense .
So maybe add a return to the countPoints and assign points with it :
points = countPoints(obstacleNumber, points);
In Java, arguments to methods are always passed by value. It can get confusing with objects though. But with primitive types like int it's very simple. To the functions countMoves and countPoints you are only giving the value of the moves and points, respectively, but not their reference. That is, the methods are working in fact with another variable. This variable is initialized to the value you give in and you can change it as you want, but the changes made to this variable are only visible to the method. Therefore in order to make the changes visibile to the outer variables you must reset their values. For instance you could do this:
public static int countMoves(String in, int moves) {
//... change the value of moves as you want
return moves; //return the new value
}
And then use the method like:
moves = countMoves(in, moves);
Where the set variable is the one you define in main. Analogously for countPoints. Another possibility would be to define moves and points in the class Program12 and make the methods count methods modify these variables directly without passing them, like:
public static void countMoves(String in) {
moves = ...
}
In this case the moves moves defined in Program12 is visible to the countMoves and so you are changing directly the variable you want; there is no need to reset it.
--
But big but. The code you have is rather spaghetti. You should think how to better structure and compartmentalize the code into closely-related logical units. In object-oriented programming you do it with classes. For example, you could define a class called GameState that keeps the variables moves and points or anything else shall you need it, and define there the count methods or other methods to modify the statistics of the game. Don't make the main method define the logic of the program. It should merely be used to read the input to initialize some sort of class Game and write to output the results of the Game.
I might be wrong here (early in the morning...) but I'm guessing you always get the same moves and points value? This is because you are not increasing the values of the actual moves and points. When you send an Int as a parameter to a method you are not sending a pointer to the Int but a copy of it which will be used by the method and then removed when leaving it. You need to either return moves and points after increasing the values or put them as static attributes. Try doing it this way instead:
...
moves = countMoves(String in, int moves);
...
public static int countMoves(String in, int moves) {
if(in.equals("left") || in.equals("right") || in.equals("up") || in.equals("down")) {
moves++;
}
System.out.println("You have used " + moves + " moves.");
return moves;
}
Or you could increase them when identifying the moving direction (which is more efficient since you don't have to redo the check if the move was valid):
if (in.equalsIgnoreCase("up")) {
rowNumber = rowNumber - 1;
moves++;
}
...
EDIT
Points Problem:
Since you didn't post how Room is implemented I just improvise, but I figure it should look something like this:
...
points = countPoints(game[rowNumber][columnNumber].getObstacleNumber(), points);
...
and change countPoints() to:
public static int countPoints(int obstacleNumber, int points) {
if(obstacleNumber == 0) points = points;
if(obstacleNumber == 1) points++;
if(obstacleNumber == 2) points += 2;
System.out.println("You have obtained " + points + " points so far. Keep hunting!");
return points;
}
or just (provided you know that the input is correct):
public static int countPoints(int obstacleNumber, int points) {
points += obstableNumber;
System.out.println("You have obtained " + points + " points so far. Keep hunting!");
return points;
}
Related
I'm making battleships and I've currently come across an issue where my ships overlap. I've tried to incorporate an if statement that will judge whether it can be placed. Here's an example of me placing two ships of length 3 down.
public static void PlaceCruiser(String[][] board) {
ThreadLocalRandom random = ThreadLocalRandom.current();
int timesplaced = 0;
int size = 3;
while (timesplaced < 2) {
int randomcruisercheck =(int)(Math.random()*2);
if (randomcruisercheck == 0) {
int column = random.nextInt(0,9);
int row = random.nextInt(0,7);
if (row + 2 < 11 && board[row][column] == "." && board[row + 1][column] == "." && board[row + 2][column] == ".") {
for(int i = 0; i<size; i++)
{
board[row+i][column] = "#";
}
System.out.println(board[row][column]);
}
timesplaced++;
}
else if (randomcruisercheck == 1) {
int column = random.nextInt(0,9);
int row = random.nextInt(0,7);
if (column + 2 < 11 && board[row][column] == "." && board[row][column + 1] == "." && board[row][column + 2] == ".") {
for (int i = 0; i<size; i++)
{
board[row][column + i] = "#";
}
System.out.println(board[row][column]);
}
timesplaced++;
}
}
}
Basically, I use "#" to represent a ship in a 10x10 2D array of ".". I feel like the if statement about if the row or column plus 1 then plus 2 is a dot i.e a free space, a ship will be generated but this does not seem to be the case. Can anyone help me out?
Your code works well, you only need to take care of the indexes and initialize the board:
public class Main {
public static String[][] board;
public static void main(String[] args) {
PlaceCruiser pc = new PlaceCruiser();
board = new String[10][10];
// Initialize the board
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
board[i][j]=".";
}
}
pc.placeCruiser(board);
// Show thew board
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
System.out.print(board[i][j]);
}
System.out.println();
}
}
}
Result:
..........
..###.....
..........
..........
....#.....
....#.....
....#.....
..........
..........
..........
Also check that your initial position is not already "#".
Stylistical remarks:
if you use ThreadLocalRandom for generating position, you should also use it for other randomness (in other words: (int)(Math.random()*2) could rather be random.nextBoolean(), because actually a boolean could decide if ship should be horizontal or vertical)
nextInt(0,x) is just a longer variant of nextInt(x).
Actual bugs:
due to a presumably copy-paste issue, column (0-"9") and row (0-"7") are generated in the same way in both cases, making it possible to index out of the array when placing a vertical ship
which you seem to have noticed, but fixed it with that row + 2 < 11 check which has two problems in itself:
when row+2 ends up being 10 (which is <11), that is an invalid index (valid indices are 0...9)
as row stays between 0 and "7", there will not be horizontal ships in the last few rows
nextInt(a,b) generates numbers a...b-1, so it will not generate b itself
as the other answer points out string comparison with == generally and usually does not work, use equals()
Generally I would suggest having a single check+placement function, which can deal with an entire rectangle (given position+size). Also, I switched to array of characters, that simplifies both comparisons and printing.
boolean tryPlace(int x,int y,int width,int height) {
for(int i=0;i<height;i++) {
for(int j=0;j<width;j++) {
if(board[y+i][x+j]!='.') {
return false; // ship can not be placed
}
}
}
// if we reach here, ship can be placed
for(int i=0;i<height;i++) {
for(int j=0;j<width;j++) {
board[y+i][x+j]='#';
}
}
return true; // ship placed successfully
}
This routine could be called to place a pair of 3-long ships this way:
board=new char[10][10];
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
board[i][j]='.';
int size=3;
int amount=2;
while(amount>0) {
if(random.nextBoolean()) {
// horizontal
if(tryPlace(random.nextInt(10-size+1),random.nextInt(10),size,1)){
amount--; // one placed
}
} else {
// vertical
if(tryPlace(random.nextInt(10),random.nextInt(10-size+1),1,size)){
amount--; // one placed
}
}
}
// and a 4x2 mothership
while(!(random.nextBoolean()
?tryPlace(random.nextInt(7),random.nextInt(9),4,2)
:tryPlace(random.nextInt(9),random.nextInt(7),2,4)
));
for(int i=0;i<10;i++)
System.out.println(board[i]); // char[] has special overload for print/ln()
Test: https://ideone.com/DjYqjB
However, when I was a kid we had a rule that ships could not match, there had to be empty space (or a border of the board) around them. If you need that, tryPlace() could check a larger block, and put the ship into the middle of it. Also, a usual trick of implementing board games is that you can keep a larger array in the memory than what you will actually display. So instead of fighting with "check if field is empty or it is outside the board", it is simpler to have a 12x12 board, and place ships into the middle 10x10 portion of it:
boolean tryPlaceWithBorder(int x,int y,int width,int height) {
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
if(board[y+i][x+j]!='.')
return false; // ship can not be placed
// if we reach here, ship can be placed
for(int i=1;i<height-1;i++)
for(int j=1;j<width-1;j++)
board[y+i][x+j]='#';
return true; // ship placed successfully
}
and modified usage:
board=new char[12][12];
for(int i=0;i<12;i++)
for(int j=0;j<12;j++)
board[i][j]='.';
int size=3;
int amount=2;
while(amount>0) {
if(random.nextBoolean()) {
// horizontal
if(tryPlaceWithBorder(random.nextInt(12-size-1),random.nextInt(10),size+2,3))
amount--; // one placed
} else {
// vertical
if(tryPlaceWithBorder(random.nextInt(10),random.nextInt(12-size-1),3,size+2)){
amount--; // one placed
}
}
}
// and a 4x2 mothership
while(!(random.nextBoolean()
?tryPlaceWithBorder(random.nextInt(7),random.nextInt(9),6,4)
:tryPlaceWithBorder(random.nextInt(9),random.nextInt(7),4,6)
));
for(int i=1;i<11;i++)
System.out.println(String.valueOf(board[i],1,10));
Test: https://ideone.com/LXAD7T
I am teaching myself java using the cs106a course from Stanford.
Currently I am on chapter 10 of the book "The Art and Science of Java".
The problem is to write a 3x3 Magic Square.
The exercise:
You have to write a 3x3 array
Each side of the array(Magic Square) has to equal 15
The problem:
The program I wrote works, the assignment is complete, this question is for self learning. As a beginner I would like to improve the method SumOfSides() and make it smaller and more efficient. I tried iterating the array in this method but still have issues. Is there a way to make it more efficient?
public void run() {
//set the font
setFont("Helvetica-40");
//fill the array
fillArray();
//sum up all sides
SumOfSides();
//check if all of the sides in the magic square array equal 15:
checkSides(mSqr);
//I used this for debugging purposes only:
//showSides();
}
//for debugging purposes:
public void showSides() {
println(sumRight0);
println(sumRight1);
println(sumRight2);
println(sumBottom0);
println(sumBottom1);
println(sumBottom2);
println(sumDiagonalUp);
println(sumDiagonalDown);
}
public void SumOfSides() {
sumRight0 = mSqr[0][0] + mSqr[0][1] + mSqr[0][2];
sumRight1 = mSqr[1][0] + mSqr[1][1] + mSqr[1][2];
sumRight2 = mSqr[2][0] + mSqr[2][1] + mSqr[2][2];
sumBottom0 =mSqr[0][0] + mSqr[1][0] + mSqr[2][0];
sumBottom1 =mSqr[0][1] + mSqr[1][1] + mSqr[2][1];
sumBottom2 =mSqr[0][2] + mSqr[1][2] + mSqr[2][2];
sumDiagonalUp = mSqr[2][0] + mSqr[1][1]+ mSqr[0][2];
sumDiagonalDown = mSqr[0][0] + mSqr[1][1] + mSqr[2][2];
}
/*This predicate method checks if the sides
of the array add up to 15: */
public boolean checkSides(int[][] myArray) {
if (sumRight0 ==15 && sumRight1 ==15&& sumRight2==15 && sumBottom0==15&& sumBottom1==15&&
sumBottom2==15&& sumDiagonalUp==15&&sumDiagonalDown==15) {
println("True, this is a Magic Square");
return true;
} else {
println("False, the sides do not equal 15");
return false;
}
}
public void fillArray() {
int num =0;
for(int row=0; row <3; row++) {
for (int col=0; col<3; col++) {
num=readInt("");
mSqr[row][col]=num;
}
}
/*Test array values here to see
* if they were entered correctly.
*/
//println(mSqr[1][2]); //should be 6
//println(mSqr[2][0]); //should be 7
}
//instance variables:
int[][] mSqr= new int[3][3];
List<List<Integer>> new1 = new ArrayList<>();
private int sumRight0;
private int sumRight1;
private int sumRight2;
private int sumBottom0;
private int sumBottom1;
private int sumBottom2;
private int sumDiagonalUp;
private int sumDiagonalDown;
}
Perhaps the only thing is readability. You could take the values and move them into more readable variables:
int topLeft = mSqr[0][0];
int topMid = mSqr[0][1];
...
int sumLeft = topLeft + midLeft + bottomLeft;
int sumRight = topRight = midRight + bottomRight;
...
To address your concern of making it smaller, I would argue that converting the sums into loops, as you mentioned, is certainly not worth it in the case that you are doing 6 sums of 3 values each. Furthermore, each term of each sum is common to either one or two other sums, which does not provide much overlap. If you were performing larger sums (larger in number of terms in the sum, not the total value), then perhaps it would be worth it on a readability/SLOC argument.
Suppose you did want to do a loop still though, you could do something like
sumLeft = 0;
sumRight = 0;
sumTop = 0;
sumBottom = 0;
sumDiagonalUp = 0;
sumDiagonalDown = 0;
for(int i = 0; i < mSqr.length; i++) {
for(int j = 0; j < mSqr[i].length; j++) {
if (i == 0) {
sumLeft += mSqr[i][j];
}
if (i == mSqr.length - 1) {
sumRight += mSqr[i][j];
}
if (j == 0) {
sumTop += mSqr[i][j];
}
if (j == mSqr[i].length) {
sumBottom += mSqr[i][j];
}
if (i == j) {
sumDiagonalDown += mSqr[i][j];
}
if (i + j == mSqr.length - 1) {
sumDiagonalUp += mSqr[i][j];
}
}
}
The loops only provide benefit on large magic squares.
Also, I am confused by your description contrasted with your implementation. It seems you are summing each row and column, and the two diagonals of the square, as opposed to the 4 sides and the diagonals.
I need help rearranging a program I have to use classes constructors methods...so on. It's a game of battleships. I'm not too clear on what classes and constructors and methods I'd need.
import java.util.Scanner;
public class BattleshipLab {
Scanner input = new Scanner(System.in);
public static final boolean DEBUG = false;
public static void breakln() {
System.out.println("_____________________________________");
System.out.println("");
}
public static void createBoard(String[][] board) {
for (String[] board1 : board) {
for (int c = 0; c < board[0].length; c++) {
board1[c] = "~";
}
}
}
public static void showBoard(String[][] board) {
breakln();
for (String[] board1 : board) {
if (DEBUG == true) {
for (int c = 0; c < board[0].length; c++) {
System.out.print(" " + board1[c]);
}
System.out.println("");
} else {
for (int c = 0; c < board[0].length; c++) {
if (board1[c].equals("S")) {
System.out.print(" " + "~");
} else {
System.out.print(" " + board1[c]);
}
}
System.out.println("");
}
}
breakln();
}
public static void createShip(String[][] board, int size) {
if (Math.random() < 0.5) {
int col = (int) (Math.random() * 5);
int row = (int) (Math.random() * 7);
for (int i = 0; i < size; i++) {
board[row][col + i] = "S";
}
} else {
int col = (int) (Math.random() * 7);
int row = (int) (Math.random() * 5);
for (int i = 0; i < size; i++) {
board[row + i][col] = "S";
}
}
}
public static int userFire(String[][] board, int hits, int torps) {
Scanner input = new Scanner(System.in);
int row, col;
System.out.println("You have: " + torps + " torpedos left!");
System.out.println("Select a row to fire in: ");
row = input.nextInt();
while (row > 8 || row < 1) // Error checking for row
{
System.out.println("Enter a valid row (1 -> 8)");
row = input.nextInt();
}
System.out.println("Select a column to fire in: ");
col = input.nextInt();
while (col > 8 || col < 1) // Error checking for column
{
System.out.println("Enter a valid col (1 -> 8)");
col = input.nextInt();
}
if (board[row - 1][col - 1].equals("S")) {
hits++;
System.out.println("~~~~~~~ HIT ~~~~~~~");
board[row - 1][col - 1] = "!";
} else {
System.out.println("~~~~~~~ MISS ~~~~~~~");
board[row - 1][col - 1] = "M";
}
return hits;
}
public static void finall(int hits, int torps) {
if (hits < 4) {
System.out.println("Sorry, but you lost because you didn't sink the ship.");
}
if (torps < 1) {
System.out.println("You have lost all your torpedos");
} else if (hits >= 4) {
System.out.println("You have beaten the game battleship, Thanks for playing!");
}
System.out.println("Good game, well played!");
}
public static void main(String[] arg) {
String[][] board = new String[8][8];
createBoard(board);
createShip(board, 4);
int torps = 15;
int hits = 0;
/// Starting real stuff
while (torps > 0 && hits < 4) {
showBoard(board);
hits = userFire(board, hits, torps);
torps--;
}
finall(hits, torps);
}
}
Welcome to Stack Overflow, Noah!
First a couple of remarks:
This kind of question is usually considered as unclear what you are asking and/or too broad, so expect downvotes and a closing of your question. You should really read up on how to ask a good question.
If you are struggling with your code design, it is often a good idea to take a pen and some paper and draft a rough outline there. For your specific task of turning an existing program into OOP, a class diagram would be a really good starting point.
Now that that's out of the way, I'll give you a bit of a notch in the right direction, seeing that you are new to Stack Overflow.
In your code, we can find two interesting methods:
createBoard
createShip
Notice how they both start with create? This is a very, very strong hint that it would probably a good idea to write classes for those two objects at least:
Board
Ship
When it comes to methods, your current code gives us some pointers again. While I'm not sure about firing torpedos and the like, it looks as if you might want to at least turn showBoard() into a method show of your Board class.
Now, what other classes and methods you need really depends on the rules of that game (I'm not familiar with it), what features you want it to have and, of course, how you want to implement it. Possible other classes could be Torpedo but maybe those will just be a primitive type member of your Ship class. Another candidate could be something like Tile, the basic building block of your Board?
You'll have to take it from here, really. The Java Lessons on Classes and Objects will be useful.
I hope this gets you started.
Okay so when you're doing OOP, before you begin to code you should analyze your problem and break it down. What parts make up the game, what are their functions and attributes, how do these parts interact with each other? I'll help you start, consider making board and cell classes.
In OOP you like Java, you need to create a new instance of the object(class) that you define. So let's say you created a class:
class Shape {
int length, width;
String color ="";
}
To use Shape in main you create a new instance of it
class Driver {
public static void main (String [] args){
//First you specify the type as your object name, then name the variable and lastly, you do new object.
Shape myShape = new Shape ();
}
}
I'm trying to program Minesweeper in Java. I am currently trying to create an x amount of unique Mines, which positions ( as POINTS, where x corresponds to Row and y to column for JavaFX) are saved in a one dimensional Array. So that I can then return the list to the controller.
I could start and:
create all Points, add them to the array, test every Point with every other Point, overwrite the doubles with new Points, test again...
but that seems awfully inelegant.
My problem so far was, that when I test whether or not my just created point is .equal() to every Point in the Mines[] array, it throws an exception since the array is empty.
This new solution is the best I came up with so far, but still buggy. Either some pointers with the current code or a more elegant approach would be great!
Thanks for the help
MineNumber = mines;
Mheight = height;
Mwidth = width;
int row;
int column;
int counter = 0;
Point[] Mines = new Point[MineNumber]; //5
Random Rnd = new Random();
boolean create=true;
no clue why it only works with -1 there, but after some trying this way it at least runs
do {
if (counter < MineNumber - 1) {
row = Rnd.nextInt(Mwidth);
column = Rnd.nextInt(Mheight);
Point p = new Point(row, column);
System.out.println(p); //test
if (counter <= 0) {
Mines[0] = p;
counter++;
} else {
for (int i = 0;i < counter; i++) {
if (Mines[i].equals(p)) {
break;
} else {
Mines[counter] = p;
counter++;
}
}
}
} else {
create = false;
}
} while (create);
System.out.println(Mines[0] + " " + Mines[1] + " " + Mines[2] + " "
+ Mines[3] + " " + Mines[4]);
}
Output:
java.awt.Point[x=3,y=2]
java.awt.Point[x=1,y=8]
java.awt.Point[x=9,y=12]
java.awt.Point[x=3,y=2] java.awt.Point[x=1,y=8] java.awt.Point[x=9,y=12] java.awt.Point[x=9,y=12] null
Store each location of a placed mine in a set:
Set<Point> placedMines = new HashSet<>();
Then you can do your loop from 0 till mine number without the need to change the index and running into issues with accessing an element that was not yet set.
You can check easily:
Point p = Point(row, column);
while (placedMines.contains(p)) {
// there is already a mine at that location, select a different one.
p = Point(Rnd.nextInt(Mwidth), Rnd.nextInt(Mheight));
}
im learning to create a java gameļ¼still new to java. now i want to create a battleshipe game.
But now im stuck here. Now, when i randomly place the shipe as the computer board, sometime it will overlapping the previous ship, so it become not balance for then game. Second, after i get input from player, how do i put the input value into the board.
Here is the code i have:
import javax.swing.JOptionPane;
import java.util.Random;
import java.util.Scanner;
public class Battleship
{
public static void main (String args[]){
String map [][][]=new String [10][10][2];
int row =0,col=0;
//initPlayerMap(map);
//printMap(map,true);// true to printout the map
placeShips(map); // place the shipe at computer map
initMap(map,"~", true);
initMap(map,"#",false);
placeShips(map); // place the shipe at computer map
printMap(map,true);
System.out.println("Now enter your coordinate of the boom");
row = getInput("Please enter row: ");
col = getInput("Please enter col: ");
printMap(map,false); // computer map
hitShip(row,col);
}
private static void hitShip (int row, int col){
if (map[startFrom++][colOrRow][1]== map[row][col][1]){
System.out.println("abc");
}
else
{
System.out.println("darn!");
}
}
private static void initMap(String map[][][] , String initChar, boolean player){
//the 0 in 3rd dimension is representing player map and 1 for computer
int mapNo= (player?0:1);
for (int i = 0 ; i < 10; i ++)
for (int j=0; j<10; j++)
map [i][j][mapNo]= initChar;
}
private static void printMap(String map[][][], boolean player){
int whichMap=0;
if (!player)
whichMap=1;
System.out.println(" 0\t1\t2\t3\t4\t5\t6\t7\t8\t9 ");
for (int i = 0 ; i < 10; i ++){
System.out.print(i+" ");
for (int j=0; j<10; j++){
System.out.print(map [i][j][whichMap]+ "\t");
}
System.out.print("\n");
}
}// end of printMap method
public static int getInput(String message){
Scanner sc = new Scanner (System.in);
System.out.print(message);
return sc.nextInt();
}
private static void placeShips(String[][][] grid)
{
char[] shipType = { 'B' , 'C' , 'F' , 'M' };
int[] shipSize = { 5 , 4 , 3 , 2 };
int[] shipNums = { 1 , 2 , 4 , 4 };
for (int x = 0 ; x < shipType.length ; x++)
for (int y = 1 ; y <= shipNums[x] ; y++)
{
String shipName = shipType[x]+""+y;
placeShip(grid,shipName,shipSize[x]);
}
}
private static void placeShip(String[][][] map, String shipName, int size){
int direction = (int)(Math.random()*2);// 0 or 1
int colOrRow = (int)(Math.random()*map.length); // pick
int startFrom =(int)(Math.random()*(map.length-size)); // which cell?
// placing the ship
for(int i=0; i < size; i++){
// weather is vertical or horizontal
// vertical
if (direction == 0 ){
map[startFrom++][colOrRow][1] = shipName;
}
else {
map[colOrRow][startFrom++][1] = shipName;
}
}
}
}
To start with, you haven't modeled this correctly (IMO)
I would utilize java.awt.Rectangle a lot more. I would start by making the board a Rectangle, then make each ship a Rectangle too. Because Rectangle (comes from Shape in fact) has the method contains(...) you should be able to quickly test whether your rectangles are overlapping.
As far as marking shots on the board, perhaps your Ships need to be defined as more than just rectangles - give them functionality for spots that have been hit. You can use java.awt.Point for hit / miss shots
I think you are asking two questions here, I'll answer them both.
To put a ship on the field and make sure they don't overlap, check if there is a ship in any of the squares you are trying to put your new ship into. Make a 2D array of booleans, in which you save on which square is a ship.
For the user input, what have you tried, and into what problems have you been running? Without anything to hold on to I cannot give you anything to work with. I'd suggest letting the user give two coordinates: the start and the end of the ship. Process that data.
You don't seem to be using a data structure to keep track of your "already filled" positions in your map. That way you can compare or "validate" what positions are not filled in your map.