Battleship-java games - java

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.

Related

How to prevent string overlap on a 2D array?

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

Play method for TicTacToe java

So we got an excercise and need to write a tictactoe class, we need to work with a 2d int array as the board and 2 players, one has a "1" as the "X" and the other one a "2" as the "O", "0" is for empty field. Now we need to write a method for the players to actually set something on the field, but all I can think about is stuff to do with a string or char board and nothing really with an int board. How do you realize this setting of a problem with a number on an int board? Thanks for any help!
I already got a method which checks if there's any free spot available on the board anyways, which should be correct.
public class TicTacToe extends BasicBoard implements Game {
int PlayerA = 1;
int PlayerB = 2;
int empty = 0;
private int row, column;
private int[][] board = new int[column][row];
public boolean isboardfull(int row, int column) {
for (int i = 0; i <= column; i++)
{
for (int j = 0; j <= row; j++)
{
if (board[i][j] == PlayerA || board[i][j] == PlayerB)
return true;
}
}
return false;
}
public void playerturn(){
if (!isboardfull(row, column))
}
}
Your TicTacToe class extends from the BasicBoard and Game classes but you have not provided them. I assume that these classes give you methods to render the board and control the game evolution but since we don't have them I have included something similar (and simple) in my example (to demonstrate how it works). You can skip the game, printBoard, resetBoard, and endGame methods if these are provided by the BasicBoard and Game classes.
Here is a list of assumptions I have made:
The players are asked for the coordinates where to play
The game ends when the board is full. A more complex version should check every iteration of the game if one of the players has won.
And here a general explanation of my approach:
The mapping between X and O to 1 and 2 is set to static constant since this will never change.
The number of rows and columns may vary between executions and its parametrized in the TicTacToe constructor.
The players fill the information through the standard input when prompted.
The game function asks for the players to move and renders the board (on the standard output) until the board is completely filled.
The isBoardFull function checks if there are empty slots on the board or not. Thus, if we find an empty slot we know it is not full, otherwise we need to keep searching for empty slots. If we search through all the board and there are no empty slots, then it is full. (in my opinion, this part is miss-written in the coded you provided)
The playerTurn function asks for the coordinates where the player wants to play and fills the board. To do so, we scan 2 lines of the standard input, convert them to int and check if the position is empty and within bounds. If so, we mark the position with the player number.
The code:
public class TicTacToe {
private static final int PLAYER_A = 1;
private static final int PLAYER_B = 2;
private static final int EMPTY = 0;
private final int numRows;
private final int numColumns;
private final int[][] board;
private final Scanner inputScanner;
public TicTacToe(int numRows, int numColumns) {
// Retrieve board sizes
this.numRows = numRows;
this.numColumns = numColumns;
// Instantiate board
this.board = new int[numRows][numColumns];
// Initialize board
resetBoard();
// Initialize the input scanner (for player choices)
this.inputScanner = new Scanner(System.in);
}
public void game() {
// Initialize the game
int numMoves = 0;
printBoard(numMoves);
// Play until the game is over
while (!isBoardFull() && !hasPlayerWon()) {
// A or B player should move
int currentPlayer = (numMoves % 2 == 0) ? PLAYER_A : PLAYER_B;
playerTurn(currentPlayer);
// We increase the number of moves
numMoves += 1;
// We render the board
printBoard(numMoves);
}
// Check winner and close game
endGame();
}
private void resetBoard() {
for (int i = 0; i < this.numRows; ++i) {
for (int j = 0; j < this.numColumns; ++j) {
this.board[i][j] = EMPTY;
}
}
}
private void printBoard(int currentMove) {
System.out.println("Move: " + currentMove);
for (int i = 0; i < this.numRows; ++i) {
for (int j = 0; j < this.numColumns; ++j) {
System.out.print(this.board[i][j] + " ");
}
System.out.println();
}
// A new line to split moves
System.out.println();
}
private boolean isBoardFull() {
for (int i = 0; i < this.numRows; ++i) {
for (int j = 0; j < this.numColumns; ++j) {
if (this.board[i][j] == EMPTY) {
// If there is an empty cell, the board is not full
return false;
}
}
}
// If there are no empty cells, the board is full
return true;
}
private boolean hasPlayerWon() {
// TODO: Return whether a player has won the game or not
return false;
}
private void playerTurn(int currentPlayer) {
// Log player information
System.out.println("Turn for player: " + currentPlayer);
// Ask the player to pick a position
boolean validPosition = false;
while (!validPosition) {
// Ask for X position
int posX = askForPosition("row", this.numRows);
// Ask for Y position
int posY = askForPosition("column", this.numColumns);
// Check position
if (posX >= 0 && posX < this.numRows) {
if (posY >= 0 && posY < this.numColumns) {
if (this.board[posX][posY] == EMPTY) {
// Mark as valid
validPosition = true;
// Mark the position
this.board[posX][posY] = currentPlayer;
} else {
System.out.println("Position is not empty. Please choose another one.");
}
} else {
System.out.println("Column position is not within bounds. Please choose another one.");
}
} else {
System.out.println("Row position is not within bounds. Please choose another one.");
}
}
}
private int askForPosition(String rc, int dimensionLimit) {
System.out.println("Select a " + rc + " position between 0 and " + dimensionLimit);
return Integer.valueOf(this.inputScanner.nextLine());
}
private void endGame() {
// Close input scanner
this.inputScanner.close();
// Log game end
System.out.println("GAME ENDED!");
// TODO: Check the board status
System.out.println("Draw");
}
public static void main(String[] args) {
TicTacToe ttt = new TicTacToe(3, 4);
ttt.game();
}
}
Example Output:
Move: 0
0 0 0 0
0 0 0 0
0 0 0 0
Turn for player: 1
Select a row position between 0 and 3
4
Select a column position between 0 and 4
1
Row position is not within bounds. Please choose another one.
Select a row position between 0 and 3
1
Select a column position between 0 and 4
1
Move: 1
0 0 0 0
0 1 0 0
0 0 0 0
Turn for player: 2
.
.
.
Move: 12
2 2 1 2
1 1 2 1
1 2 1 2
GAME ENDED!
Draw

Dynamic variables

I'm tring to assign variables dynamically, but I don't have a clue how to do that.
What my program should do:
"Write a program to have the user enter three lengths of sides and determine whether the figure is a triangle or not."
This is what I have so far:
package triangle;
import javax.swing.JOptionPane;
public class Triangle {
public static void main(String[] args) {
String x = JOptionPane.showInputDialog("Please enter the side lengths of a triangle with each side \nseparated with a ',' and without spaces. (eg. 1,2,3)");
x += ",";
int y = -1, a = 0;
double z;
for(int i = 0; i < x.length(); i++)
{
if(x.charAt(i) == ',')
{
z = Double.parseDouble(x.substring((y + 1), i));
y = i;
a += z;
}
}
}
}
What I would love to do would be to have this in the if statement:
int a++;
z(a) = Double.parseDouble(x.substring((y + 1), i));
But as I have found out this will not work and I need some kind of array. Sadly, my online class has not started arrays yet and I haven't gotten a grasp of them yet in my own learning.
I would like to make 3 variables (z1, z2, z3) and assign an integer to each one within the if statement.
Edit:
Here's some revised code that now works how I wanted now. Hope this helps someone else in the future!
package triangle;
import javax.swing.JOptionPane;
public class Triangle {
public static void main(String[] args) {
String x = JOptionPane.showInputDialog("Please enter the side lengths of a triangle with each side \nseparated with a ',' and without spaces. (eg. 1,2,3)");
x += ",";
int y = -1, a = 0;
Double[] z = new Double[3];
for(int i = 0; i < x.length(); i++)
{
if(x.charAt(i) == ',')
{
z[a] = Double.parseDouble(x.substring((y + 1), i));
y = i;
a++;
}
}
//Some test code to see if it was working
System.out.println(z[0]);
System.out.println(z[1]);
System.out.println(z[2]);
}
}
You don't need to use arrays, especially that you haven't been introduced to them. You can simply use a Scanner class, and do something similar to
Scanner in = new Scanner(System.in); // this will read from the standard system input
System.out.println("Please enter three lengths of sides: ");
int a = in.nextInt();
int b = in.nextInt();
int c = in.nextInt();
And write some logic (I guess that's the point of your homework) checking if this figure is a triangle.
In case you would like to use arrays , you could declare one by doing:
int[] sidesLenghtsArray = new int[3];
And then instead of refering to three different int variables, you could simply refer to your array elements:
int[0] = in.nextInt();
int[1] = in.nextInt();
int[2] = in.nextInt();
Just remember - the number in the brackets is the number of elements that your array will have, but refering to that elements, you start counting from 0. That's why we start with int[0] (1st element) and end with int[2] (3rd element).
Java does not support tuple assignment like
def (a,b,c) = "1,2,3".split(",")
It is possible to do this in Java 8 with a following code:
int[] abc = Arrays.stream("1,2,3".split(",")).mapToInt(Integer::parseInt).toArray();
Here, a would be abc[0], b is abc[1].
Similar code in Java 7 could be this:
String[] abc = "1,2,3".split(",");
int a = Integer.parseInt(a[0]);
int b = Integer.parseInt(a[1]);
int c = Integer.parseInt(a[2]);
The very basic idea is that in every triangle when you add the lengths of two sides, the resulting length should be greater than the length of the remaining sides. Let's say a, b, c are the sides of the triangle.
public static void main(String[] args){
int a=3, b=4, c=5;
if(a+b > c && a+c>b && c+b>a){
System.out.println("This is a valid trianlge");
}
else{
System.out.println("This is not a valid triangle");
}
}
make sure you replace the values of a,b, and c with the values you gain from user input.

Creating Multiple Rectangle Objects at Once (Java)

First off, thanks for just clicking this :) I'm an amateur student coder, and I'm creating a (horrible) version of Pacman. I'm trying to create rectangles for each of my dots on my 1000x650 applet screen, so I can create an if statement when Packages hit box touches them, they disappear.
My problem is, I want to create a class so I can create the rectangles easily and have only 1 if statement, and not one for each dot rectangle (trying to learn to be efficient :P)
If I didn't elaborate enough, I'll be wary to bring edits based on your responses, and thanks!!!
(Edit 1: Fixed a run on sentence xD)
If you need to fill rectangles on both X and Y (Matrix), you most probably need nested loops.
Let's consider you want to a 5 * 5 rectangle every 100 pixels in the width with a 50 pixels spacing in the height:
for(int x = 0;x<1000;x+= 100)
{
for(int y=0;y<650; y+= 50)
{
drawRectangle(x, y, 5, 5); // Considering drawRectangle(x, y, width, height)
}
}
Try this code, it will return true when it collides with the dot.
Object pacman = new Object();
pacman.xcoord = null;
pacman.ycoord = null;
final int dotsInStage = 50;
// add other properties
int xcoords[] = new int[dotsInStage];
int ycoords[] = new int[dotsInStage];
Call this Boolean:
public boolean dotCollison (int xcoords[], int ycoords[], Object pacman) {
loop = 0;
while (loop <= dotsInStage) {
if (pacman.xcoord = xcoords[loop] && pacman.ycoord = ycoords[loop]) {
return true;
break;
}
}
}
To add the rectangles, try:
int loop = 0;
while (loop <= dotsInStage) {
Graphics.drawRectangle (xcoord[loop] , ycoord[loop] , xcoord[loop] + 10 , ycoord[loop] + 10);
}
Hope it works and happy coding!
I'm not totally comprehending your question. But
Couldn't you just create a 2 d array use a nested for loop
For( int I = 0; I<array.length;i++){
For (int j = 0; j <array[0].length;I++){
//fill w/ rectangles
array[I][j]= ;
}}
You can use a for statement which repeadly loops untill a condition is met.
This is the general structure:
for (counterInitialization; terminatingCondition; incrementLoopsCount) {
statement(s);
}
And this is an example in which the loop continue for as long as the counter i<n):
int n = 50;
for(int i = 0;i<n;i++){
//code for creating a rectangle
...
}
I suggest you give this a read.

simple maze game in java

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;
}

Categories