java close scanner & out of bounds exeption - java

i got two different kind of errors in my code.
one is when someone enters a number that's higher than 8 or lower than 0.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 22
at boter_kaas_en_eiren.Board.placeAttempt(Board.java:37)
at boter_kaas_en_eiren.Game.play(Game.java:28)
at boter_kaas_en_eiren.MainClass.main(MainClass.java:12)
the other error is when a player wins and i want to close the scanner so nobody can play anymore.
Exception in thread "main" java.lang.IllegalStateException: Scanner closed
at java.util.Scanner.ensureOpen(Unknown Source)
at java.util.Scanner.findWithinHorizon(Unknown Source)
at java.util.Scanner.nextLine(Unknown Source)
at boter_kaas_en_eiren.Game.play(Game.java:23)
at boter_kaas_en_eiren.MainClass.main(MainClass.java:12)
if somebody could help me i would appriciate it.
game class
package boter_kaas_en_eiren;
import java.util.Scanner;
public class Game {
private Board board;
private boolean gameFinished;
public Game() {
board = new Board();
gameFinished = false;
}
public void play() {
Scanner scan = new Scanner(System.in);
int x = 0;
String nextSymbol = "x";
board.ShowBoard();
while (gameFinished == false) {
String input = scan.nextLine();
int position = Integer.parseInt(input);
boolean highorlow = board.tohighorlow(position);
boolean succes = board.placeAttempt(position, nextSymbol);
if (highorlow) {
if (succes) {
if (nextSymbol.equals("x")) {
nextSymbol = "o";
} else {
nextSymbol = "x";
}
}
}
board.ShowBoard();
if (board.checkWinner("x") == true) {
System.out.println("x wins");
scan.close();
}
if (board.checkWinner("o") == true) {
System.out.println("x wins");
scan.close();
}
}
}
}
main class
package boter_kaas_en_eiren;
public class MainClass {
public static void main(String[] args) {
Game game = new Game();
game.play();
}
}
board class
package boter_kaas_en_eiren;
import java.util.Scanner;
public class Board {
private String[] board;
public Board() {
board = new String[9];
for (int i = 0; i < board.length; i++) {
board[i] = " ";
}
}
public void ShowBoard() {
System.out.println(board[0] + "|" + board[1] + "|" + board[2]);
System.out.println(board[3] + "|" + board[4] + "|" + board[5]);
System.out.println(board[6] + "|" + board[7] + "|" + board[8]);
System.out.println("");
}
public boolean tohighorlow(int position) {
if (position <= 8 && position >= 0) {
return true;
} else {
System.out.println("Invalid!!");
return false;
}
}
public boolean placeAttempt(int position, String symbol) {
if (board[position].equals(" ")) {
board[position] = symbol;
return true;
} else {
System.out.println("invalid!");
return false;
}
}
public boolean checkWinner(String symbol) {
if (board[0].equals(symbol) && board[1].equals(symbol) && board[2].equals(symbol)) {
return true;
} else if (board[3].equals(symbol) && board[4].equals(symbol) && board[5].equals(symbol)) {
return true;
} else if (board[6].equals(symbol) && board[7].equals(symbol) && board[8].equals(symbol)) {
return true;
} else if (board[0].equals(symbol) && board[3].equals(symbol) && board[6].equals(symbol)) {
return true;
} else if (board[1].equals(symbol) && board[4].equals(symbol) && board[7].equals(symbol)) {
return true;
} else if (board[2].equals(symbol) && board[5].equals(symbol) && board[8].equals(symbol)) {
return true;
} else if (board[0].equals(symbol) && board[4].equals(symbol) && board[8].equals(symbol)) {
return true;
} else if (board[2].equals(symbol) && board[4].equals(symbol) && board[6].equals(symbol)) {
return true;
} else {
return false;
}
}
}

If you would thoroughly check the source code lines given in the exceptions, you could probably find the issues yourself. But let's go through it together this time:
ArrayIndexOutOfBoundsException
This means you are trying to access an array element that is simply not there.
In your Game class, you have these two lines:
boolean highorlow = board.tohighorlow(position);
boolean succes = board.placeAttempt(position, nextSymbol);
Looking at tohighorlow(), we find this line:
if (position <= 8 && position >= 0) {
return true;
}
However, this will return true if the number is in the range [0..8]. In other words, the method returns true when your number is neither too high nor too low. Easiest fix is to change the condition like this:
if (position > 8 || position < 0)
Now numbers greater than 8 or lower than 0 will yield true, which seems to be what the method is supposed to do. Alternatively, you could swap the bodies of the if and else.
Regardless of that, you are ignoring the result of this method when you call placeAttempt() in your Game class. That's not good, because looking at placeAttempt() we find this line:
if (board[position].equals(" ")) { /* ... */
This is where your exception originates. You are accessing the board array without checking the position value. Or rather, you did check the position value but did not respect the result of that check here. Hence, if position is -2 or 12, for example, you will run into trouble as those elements do not exist (are out of bounds).
IllegalStateException: Scanner closed
Let's simplify the play() method of your Game class for a second:
public void play() {
Scanner scan = new Scanner(System.in);
/* ... */
while (gameFinished == false) {
String input = scan.nextLine();
/* ... */
boolean highorlow = board.tohighorlow(position);
boolean succes = board.placeAttempt(position, nextSymbol);
/* ... */
if (board.checkWinner("x") == true) {
System.out.println("x wins");
scan.close();
}
if (board.checkWinner("o") == true) {
System.out.println("x wins");
scan.close();
}
}
}
The first thing you do is to create the Scanner. Now, under certain circumstances (the two if at the end), you close the scanner. However, you do that within a loop. After you close the scanner, the loops starts over with its first line:
String input = scan.nextLine();
But you can't get the next line of a closed scanner.
Additional notes
I noticed that you are quite inconsistent in your style. For example, see these three method names: ShowBoard, placeAttempt and tohighorlow. You use different capitalization for each. I strongly suggest to stick to the recommended naming convention, which means camelCase with lower first letter: showBoard, placeAttempt and tooHighOrLow (also notice to vs too).
Hope this helps.

Your array board has the size 9. So if someone enters a number not between 0 and 8 you get an Exception.
You pass the input from the user directly to your function:
board.placeAttempt(position, nextSymbol);
There you do:
if (board[position].equals(" ")) {
So you try to access an invalid position of the array

Related

Head First Java book battleship game

I am reading "Head First Java" book and I came across the problem in chapter 5 with the battleship game (with simple version). I knew that the book's code doesn't work and I tried my self fixing it, but it still didn't work.
So tried to google it and I found some post on this website but I still have a problem. The game isn't working properly as it should.
If a player enters any random number, the output is always "hit"...
This is the last version of the code:
DotCom class:
public class DotCom {
private ArrayList<String> locationCells = new ArrayList<>();
public void setlocationCells(int[] loc) {
if (loc != null)
for (int val : loc)
locationCells.add(String.valueOf(val));
}
public String checkYourself(String userInput) {
String result = "miss";
int index = locationCells.indexOf(userInput);
if (index >= 0) {
locationCells.remove(index);
}
if (locationCells.isEmpty()) {
result = "kill";
} else {
result = "hit";
}
System.out.println(result);
return result;
}
}
DotComGame class:
public class DotComGame {
public static void main(String[] args) {
int guessingTimes = 0;
DotCom dot = new DotCom();
GameHelperrr helper = new GameHelperrr();
int randomNum = (int) (Math.random() * 5);
int[] locations = { randomNum, randomNum + 1, randomNum + 2 };
dot.setlocationCells(locations);
boolean isAlive = true;
while (isAlive == true) {
String guess = helper.getUserInput("Enter a number");
String result = dot.checkYourself(guess);
guessingTimes++;
if (result.equals("kill")) {
isAlive = false;
System.out.println("You took " + guessingTimes + " guesses");
}
}
}
}
I would really appreciate to get a detailed and understandable answer, because I'm stuck and I couldn't move on with the book for a few days now.
int index = locationCells.indexOf(userInput);
This method will return -1 if the element doesn't exist in the collection.
So if you miss, it won't hit this condition:
if (index >= 0) {
locationCells.remove(index);
}
There are still elements in this collection because you didn't remove anything...
if (locationCells.isEmpty()) {
result = "kill";
} else {
result = "hit";
}
So on a miss, the result still shows "hit."
Try this instead:
if (locationCells.isEmpty()) {
result = "kill";
} else {
result = index == -1 ? "miss" : "hit";
}
If you haven't killed the opponents ships, then you either miss all ships or you hit a single ship.
I would guess the checkYourself-Method must be like this:
public String checkYourself(String userInput) {
String result = "miss";
int index = locationCells.indexOf(userInput);
if(index >= 0) {
locationCells.remove(index);
if (locationCells.isEmpty()) {
result = "kill";
}else {
result = "hit";
}
}
System.out.println(result);
return result;
}
In it's current form the ArrayList is never empty because you insert 3 Values but only remove 1 if the user-input is in the list so .isEmpty() is never TRUE.

Error using linked list remove function. after advanced for loop breaks

I am trying to get my bet system to detect if the input numbers are duplicates. When you run the program, press 2 on the "for box" bet and follow instructions from there. The issue lies in the winlose duplicate and also for the non duplicate. I don't know how I am supposed to fix the issue.
Error stacktrace :
at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:966)
at java.util.LinkedList$ListItr.next(LinkedList.java:888)
at numbersgame.Test.winLoseBetDuplicate(NumbersGame.java:190)
at numbersgame.Test.checkDuplicate(NumbersGame.java:167)
at numbersgame.Test.WinLoseBox(NumbersGame.java:134)
at numbersgame.Test.getValues(NumbersGame.java:117)
at numbersgame.NumbersGame.main(NumbersGame.java:24)
C:\Users\cymmm1\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 6 seconds)
Code :
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package numbersgame;
import java.lang.reflect.Array;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JOptionPane;
/**
*
* #author cymmm1
*/
public class NumbersGame {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Test numbers = new Test();
numbers.getValues();
boolean win = numbers.win; //this checks if you won, either as a duplicate or not.
if (win) {
System.out.println("You won");
switch (numbers.bet_Type) {
case 1:
System.out.println("You waged " + numbers.bet_Amount
+ "dollars and you will get "
+ numbers.bet_Amount * 600 + " back.");
break;
case 2:
if (numbers.dupwin) {
System.out.println("You waged " + numbers.bet_Amount
+ "dollars and you will get "
+ numbers.bet_Amount * 200 + " back.");
} else {
System.out.println("You waged " + numbers.bet_Amount
+ "dollars and you will get "
+ numbers.bet_Amount * 100 + " back.");
}
break;
}
} else {
System.out.println("Sorry, you lost $" + numbers.bet_Amount + " dollars");
}
System.exit(0);
}
}
class Test {
public int bet_Type;
public int bet_Amount;
public int player_Number;
public int winning_Number;
private JOptionPane panel;
public boolean win;
public List<Integer> digits = new LinkedList<>();
List<Integer> digits2 = new LinkedList<>();
public void getValues() {
panel = new JOptionPane();
this.bet_Type = (Integer.parseInt(panel.showInputDialog("What is the bet type. 1 for straight, 2 for box")));
this.bet_Amount = (Integer.parseInt(panel.showInputDialog("How much is the bet")));
boolean bad = true;
while (bad) {
this.player_Number = (Integer.parseInt(panel.showInputDialog("What is the player's Number. 3 numbers must be inputted")));
int playerNumCopy = this.player_Number;
while (playerNumCopy > 0) {
digits.add(0, playerNumCopy % 10);
playerNumCopy = playerNumCopy / 10;
}
int lengthOfNum = digits.size();
if (lengthOfNum != 3) {
bad = true;
} else {
bad = false;
}
}
bad = true;
while (bad) {
this.winning_Number = (Integer.parseInt(panel.showInputDialog("What is the winning Number")));
int winningnumbercopy = this.winning_Number;
while (winningnumbercopy > 0) {
digits2.add(0, winningnumbercopy % 10);
winningnumbercopy = winningnumbercopy / 10;
}
int lengthOfNum = digits2.size();
if (lengthOfNum != 3) {
bad = true;
} else {
bad = false;
}
}
//========END OF CHECK FOR PROPER NUMBERS=================================
//Now to check for type of bet and se the method appropriate
if (this.bet_Type == 1) {
win = WinLoseStraight();
} else {
win = WinLoseBox();
}
}
private boolean WinLoseStraight() {
if (this.player_Number == this.winning_Number) {
return true;
} else {
return false;
}
// this goes back to getValues
}
private boolean WinLoseBox() {
//this checks for duplicates. if it isnt a duplicate then check for a box non-dup
boolean duplicatewin = checkDuplicate();
if (duplicatewin) { //you either won with a duplicate number or nonduplicate. check Duplicate does to things at once
return true;
} else {
return false;
}
}
public boolean duplicate;
public boolean dupwin;
//this checks for duplicated numbers
public boolean checkDuplicate() {
duplicate = false;
int[] array = new int[digits.size()];
int i = 0;
for (int numbers : digits) {
array[i] = numbers;
System.out.println(array[i]);
i++;
}
for (int j = 0; j < array.length; j++) {
for (int k = j + 1; k < array.length; k++) {
if (array[k] == array[j]) {
duplicate = true;
System.out.println(array[k] + " equals " + array[j]);
break; //if duplicated found, it will exit out of the for loop
}
}
if (duplicate) {
System.out.println("we found duplicate.");
dupwin = winLoseBetDuplicate(); //if it has duplicated numbers, it will check if your numbers match up
break;
} else {
dupwin = winLostBetNonDuplicate();
}
}
return dupwin; //this will return if you have won the prize with a duplicated number. goes back to getValues
}
private boolean winLoseBetDuplicate() {
/*how this method works is we make a linked list.
use a advanced for loop and when we encounter
a hit, we remove the number from it.
if there is still a number in the linkedlist of
player number it is a lose. we still have digits as a linked list. */
//
boolean won = false;
boolean match;
for (int digitsnumbers : digits) {
System.out.println("Checking the number: " + digitsnumbers);
for (int digits2numbers : digits2) {
if (digitsnumbers == digits2numbers) {
digits.remove(digits.indexOf(digitsnumbers));
digits2.remove(digits2.indexOf(digits2numbers));
System.out.println("we found a duplicated numer match. Removing from choosing. ");
System.out.println(digits);
System.out.println(digits2);
match = true;
} else {
match = false;
}
}
}
if (digits.size() > 0) {
won = false;
} else {
won = true;
}
return won;
}
private boolean winLostBetNonDuplicate() {
boolean won;
for (int digitsnumbers : digits) {
for (int digits2numbers : digits2) {
if (digitsnumbers == digits2numbers) {
digits2.remove(digits.indexOf(digits2numbers));
digits.remove(digits.indexOf(digitsnumbers));
break;
}
}
}
if (digits.size() > 0) {
won = false;
} else {
won = true;
}
return won;
}
}

Compiler giving me an 'unreachable statment' error

This is a method from my code and it's throwing me an 'unreachable statement' error when I attempt to compile it.
public static boolean whoareyou(String player)
{
boolean playerwhat;
if (player.equalsIgnoreCase("Player 1"))
{
return true;
}
else
{
return false;
}
return playerwhat;
}
The exact error is:
java:82: error: unreachable statement
return playerwhat;
^
I then attempt to use this boolean I return in the following code:
public static int questions(int diceroll, int[] scorep1)
{
String wanttocont = " ";
boolean playerwhat;
for (int i = 0; i <= 6; i++)
{
while (!wanttocont.equalsIgnoreCase("No"))
{
wanttocont = input("Do you wish to continue?");
// boolean playerwhat; wasn't sure to declare here or outside loop
if (diceroll == 1)
{
String textinput = input("What's 9+10?");
int ans1 = Integer.parseInt(textinput);
output("That's certainly an interesting answer.");
if (ans1 == 19)
{
if (playerwhat = true)
{
output("Fantastic answer player 1, that's correct!");
diceroll = dicethrow(diceroll);
scorep1[0] = scorep1[0] + diceroll;
output("Move forward " + diceroll + " squares. You are on square " + scorep1[0]);
}
else if (playerwhat = false)
{
output("Fantastic answer player 2, that's correct!");
diceroll = dicethrow(diceroll);
scorep1[1] = scorep1[1] + diceroll;
output("Move forward " + diceroll + " squares. You are on square " + scorep1[1]);
}
} // END if diceroll is 1
} // END while wanttocont
} // END for loop
} // END questions
I'm not sure if the above code is relevant to the question but I just wanted to show what I'm attempting to do with the boolean that is throwing me the error. Thank you.
return playerwhat; can never be reached, since either the if or else clause will return true or false. Therefore you should remove this statement. The playerwhat variable is not required.
BTW, your method can be replaced with a one liner method :
public static boolean whoareyou(String player)
{
return player.equalsIgnoreCase("Player 1");
}
I would rename this method to something more descriptive, such as isFirstPlayer.
EDIT :
You never call whoareyou is your questions method. You should call it :
Replace
if (playerwhat = true) // this is assigning true to that variable, not comparing it to true
with
if (whoareyou(whateverStringContainsTheCurrentPlayer)) {
..
} else {
...
}
Just update your code this way
public static boolean whoareyou(String player)
{
boolean playerwhat;
if (player.equalsIgnoreCase("Player 1"))
{
playerwhat = true;
}
else
{
playerwhat = false;
}
return playerwhat;
}
Try this:
public static boolean whoareyou(String player)
{
return player.equalsIgnoreCase("Player 1");
}
You have the issue, because:
return player what;
is never reached. You exit the your function either through the "if"- or through the "else"-part.

How to prevent my program from crashing due to a user's input

I am trying to implement an algorithm "recongnizng strings in a language "
L = {'w$w' : w is a possible empty string of characters other than $,
w' = reverse(w)}
my problem is whenever i input anything without having $, it crashes on the while loop. what will be the best way to prevent it from crashing?
public boolean isInLanguage(String inputString)
{
StackReferenceBased stack1 = new StackReferenceBased();
StackReferenceBased stack2 = new StackReferenceBased();
Object qItem;
Object sItem;
int index = 0;
if (inputString.length() == 0)
{
return false; // empty string not in L
}
else if (inputString.length() == 1)
{
return true;
}
**while (inputString.charAt(index) != '$')**
{
// save the first half of the string
stack1.push(inputString.charAt(index));
++index;
}
// index points to '$' or its value > than inputString.length()
while (index < inputString.length()-1)
{
// save the second half of the string
++index;
stack2.push(inputString.charAt(index));
}
do
{
// match the first half of the string with the second half
if ((stack1.isEmpty() && !stack2.isEmpty()) ||(!stack1.isEmpty() && stack2.isEmpty()))
{
return false;
}
qItem = stack1.peek();
sItem = stack2.peek();
if (qItem != sItem)
{
return false;
}
if (!stack1.isEmpty())
{
stack1.pop();
}
if (!stack2.isEmpty())
{
stack2.pop();
}
}while (!stack1.isEmpty() || !stack2.isEmpty());
if (stack1.isEmpty() && stack2.isEmpty())
{
return true;
}
else
{
return false;
}
}
Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
String index out of range: 4 at java.lang.String.charAt(Unknown
Source) at
assignmnet5.StackReferenceBased.isInLanguage(StackReferenceBased.java:87)
at assignmnet5.Question3.main(Question3.java:19)
this is my main:
public static void main(String[]args)
{
StackReferenceBased stack = new StackReferenceBased();
String str;
boolean bool;
Scanner kb = new Scanner(System.in);
System.out.println( "Enter a string to be checked by the algorithm : ");
str = kb.next();
**bool = stack.isInLanguage(str);**
if (bool == true)
System.out.println( "The string is in language");
else
System.out.println("The string is not in language");
}
It sounds like this might suffice:
if (inputString == null || !inputString.contains("$")) {
return false; // empty string not in L
}
possible issue is a null pointer exception, try to add this line in the top of your function
public boolean isInLanguage(String inputString)
{
if(inputString == null){
return false;
}
...
...
complete your code
if you still have crashes, you will need to provide the error you've got when you run the code.

While Loops and Reverse Fibonacci

I've come across a problem. I'm trying to make a class which takes the maximum number that a user puts in and adds the integer before it until it gets to 0, however, when I run it, the numbers get larger and larger until it crashes. What seems to be throwing this into an infinite loop?
public class Summation {
public static void main(String[] args) {
EasyReader console = new EasyReader();
System.out.print("Debug? (Y/N): ");
char debug = console.readChar();
if ((debug!='Y')&&(debug!='N')){
System.out.println("Please enter Y or N");
main(null);
}
else{
System.out.print("Enter max range:");
int max = console.readInt();
int s = sum(max,debug);
System.out.print(s);
}
}
public static int sum(int m, char d){
int sm = 1;
boolean isRunning = true;
while ((isRunning == true)&&(d=='Y')){
if ((--m)==0) {
isRunning = false;
}
else{
sm = m+(--m);
System.out.println("sm is"+sm);
}
while ((isRunning == true)&&(d=='N')){
if ((--m)==0) {
isRunning = false;
}
else{
sm = m+(--m);
}
}
}return sm;
}
}
There's a scenario where your condition for exit
if ((--m)==0)
will never again be reached, because m is already less than 0, and it's never going back.
that scenario is whenever m is an even number.
while ((isRunning == true)&&(d=='Y'))
{
// this condition decriments `m` every time it runs, regardless of whether it evaluates to true
if ((--m)==0)
{
// if `m` was set to 0 on your last iteration, it will be set to -1
isRunning = false;
}
else
{
// if m is 1 before this line it will be 0 after it.
sm = m+(--m);
System.out.println("sm is"+sm);
}
while ((isRunning == true)&&(d=='N'))
{
// this code will never get executed
}
}
return sm;
Answer to your problem is very simple
Just modify the condition
if (m==0) {
isRunning = false;
}
When you are checking --m == 0, it is very much possible that m will be jumping over 0 and will enter negative territory without even setting this condition to be true.
Everything you are doing is wrong :).
First - FORMATTING. You maybe even dont know that, but the second while is INSIDE the first while cycle. If you use netbeans, its ALT+SHIFT+F.
The using of --m is not good for your example, cause it firsts decrease the "m" value and then it compares. So even when you asking at
(--m)==0
you decrease a value. And because you are using it again at
sm = m+(--m)
you can even skip the "0" value and get into negative numbers.
However if you want only "add numbers in reverse order from given number to 0 in while loop" it is not fibonacci and you can use this code (it could be done better, but this is using your code) :
public class Summation {
public static void main(String[] args) {
System.out.println(sum(10, 'Y'));
}
public static int sum(int m, char d) {
int sm = 0;
boolean isRunning = true;
while ((isRunning == true) && (d == 'Y')) {
sm += m;
if (m == 0) {
isRunning = false;
} else {
m--;
System.out.println("sm is" + sm);
}
while ((isRunning == true) && (d == 'N')) {
if ((--m) == 0) {
isRunning = false;
} else {
sm = m + (--m);
}
}
}
return sm;
}
}
Note that second while cycle couldnt be reached - it passes only when "d == Y" and then it starts only when "d == N"

Categories

Resources