I'm pretty new to coding so please bear with me, I am just experimenting with ways to shuffle an array for eventual use in shuffling a deck of cards in a card game I am creating in Java. I know that index 5 is out of bounds for length 5 but what is puzzling to me is that the error doesn't ALWAYS pop up. Sometimes I try to run my code and it works just fine, other times I get the error even if I haven't changed anything between times that I run it.
public class Card{
public static void shuffle(Object[] array) {
int noOfCards = array.length;
for (int i = 0; i < noOfCards; i++) {
int s = i + (int)(Math.random() * (noOfCards - 1));
Object temp = array[s]; //this is the first line it says has a problem
array[s] = array[i];
array[i] = temp;
}
}
public static void main(String[] args) {
String[] strOfCards = {"A","B","C","D","E"};
Card.shuffle(strOfCards); //this is the second line that has a problem
for(int i = 0; i < strOfCards.length; i++) {
System.out.println(strOfCards[i] + " ");
}
}
}
I have no idea how to change the flawed lines, any suggestions are welcome!
*** i have tried changing the number of letters in the string but then the error changes with it i.e. "Index 6 out of bounds for length 6"
Consider the lines:
for (int i = 0; i < noOfCards; i++) {
int s = i + (int)(Math.random() * (noOfCards - 1));
Object temp = array[s]; //this is the first line it says has a problem
i varies from 0 to noOfCards - 1
Your random number expression varies from 0 to noOfCards - 2
So s varies from 0 to (2 * noOfCards) - 3
Then array[s] will throw an exception whenever s >= noOfCards
It doesn't happen every time you run it because sometimes the random numbers all happen to be under noOfCards
If you want to swap with a random other card then you could try:
Random random = new Random();
int s = (i + random.nextInt(noOfCards - 1)) % noOfCards;
I realise you're using this as a learning opportunity, but in case you weren't aware, there is a Collections.shuffle method that can be used to shuffle collections such as ArrayList in one command.
Max index of array with length N is (N-1). Code should be like this:
public static void shuffle(Object[] array) {
int noOfCards = array.length;
Random random = new Random();
for (int i = 0; i < noOfCards; i++) {
int s = random.nextInt(noOfCards);
Object temp = array[s];
array[s] = array[i];
array[i] = temp;
}
}
Here is the line that causes the trouble:
int s = i + (int)(Math.random() * (noOfCards - 1));
Whenever the value s is >= 5, the array[s] will point to something out of bound.
For example i can be 3, if Math.random() returns something like 0.5, then 3 + (int)(0.5 * 4) is equal to 5, which is out of bound (0..4)
It doesn't happen all the times, because some times the Math.random() generates small enough number, so the evaluation of s is smaller than 5.
To ensure that the value of s always in the range (0..4), you should modulo the result to 5.
Here is how the line should be:
int s = (i + (int)(Math.random() * (noOfCards - 1))) % 5;
change this line
int s = i + (int)(Math.random() * (noOfCards - 1));
to this
int s = (int)(Math.random() * (noOfCards - 1));
just remove i variable from the above code
You need to remember that indices are zero-based in Java.
Note a couple of things:
- make things final if they're final
- use SecureRandom: it is more random than Random
- use the nextInt(n) method of SecureRandom to get an int in your range
- note the use of Streams to print out the result
import java.security.SecureRandom;
import java.util.stream.Stream;
public class Card {
public static void shuffle(final Object[] array) {
final SecureRandom random = new SecureRandom();
final int noOfCards = array.length;
for (int i = 0; i < noOfCards; i++) {
final int s = random.nextInt(noOfCards);
final Object temp = array[s];
array[s] = array[i];
array[i] = temp;
}
}
public static void main(final String[] args) throws Exception {
final String[] strOfCards = {"A","B","C","D","E"};
Card.shuffle(strOfCards);
Stream.of(strOfCards).forEach(System.out::println);
}
}
If you fancy using a List it's a bit more compact:
import java.security.SecureRandom;
import java.util.*;
import java.util.stream.IntStream;
public class Card {
public static void main(final String[] args) throws Exception {
final SecureRandom random = new SecureRandom();
final List<String> cards = Arrays.asList("A", "B", "C", "D", "E");
IntStream.range(0, cards.size()).forEach(i ->
Collections.swap(cards, i, random.nextInt(cards.size()))
);
cards.forEach(System.out::println);
}
}
M getting the same issue with this code and still no idea how to solve it
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import javax.swing.JOptionPane;
public class Main
{
public static void main (String[] args)
{
while (true)
{
String number = JOptionPane.showInputDialog("Please Enter \n"
+ "1 for 'Add new Employee'"
+ "\n 2 for 'Search in employee'"
+ "\n 3 for 'Exit'");
int convertnumber = Integer.parseInt(number);
if (convertnumber == 1)
{
addEmployee();
}
else if (convertnumber == 2)
{
String eId = JOptionPane.showInputDialog("Enter ID to search");
searchEmplye(eId);
}
else if (convertnumber == 3)
{
JOptionPane.showMessageDialog(null, "Developed By: BC180401942 SHEHZAD ADEEL");
System.exit(0);
}
else
{
JOptionPane.showMessageDialog(null, "Invalid input");
}
}
}
public static void searchEmplye(String eId)
{
try
{
String tokens[] = null;
String id, name, dob, qual, expe, pays;
FileReader fr = new FileReader("empData.txt");
BufferedReader br = new BufferedReader(fr);
String line = br.readLine();
if (line == null)
{
JOptionPane.showMessageDialog(null, "Employee Not found");
}
while (line != null)
{
tokens = line.split (",");
id = tokens[0];
name = tokens[1];
dob = tokens[2];
qual = tokens[3];
expe = tokens[4];
pays = tokens[5];
Employee emp = new Employee (id, name, dob, qual, expe, pays);
ArrayList list = new ArrayList();
list.add(emp);
line = br.readLine();
/*
for (int i = 0; i < list.size(); i++)
{
Employee p = (Employee) list.get(i);
if (eId.equals(p.getEmpId()))
{
JOptionPane.showMessageDialog(null, "Employee: \n"
+ "Employee ID: " + p.getEmpId()
+ " \n Employee Name: " +p.getEmpName()
+ " \n Employee DOB: " + p.getEmpDoB()
+ " \n Qualification: " + p.getEmpQualf()
+ " \n Experience: " + p.getEmpExp()
+ " \n Pay Scal: " + p.getEmpPSacle()
);
}
*/
for (int i = 0; i < list.size(); i++)
{
Employee p = (Employee) list.get(i);
if (eId.equals(p.getEmpId()))
{
JOptionPane.showMessageDialog( null, "Employee: \n" +
"EmpId: " + p.getEmpId() + "\n" +
"Name: " + p.getEmpName() + "\n" +
"DoB: " + p.getEmpDoB() + "\n" +
"Qualification: " + p.getEmpQualf() + "\n" +
"Experience: " + p.getEmpExp() + "\n" +
"PayScale: " + p.getEmpPScale() );
}
else
{
JOptionPane.showMessageDialog(null, "Employee Not found");
}
}
}
br.close();
fr.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
public static void addEmployee()
{
try
{
ArrayList list = new ArrayList();
String id = JOptionPane.showInputDialog("Enter Employee ID: ");
String name = JOptionPane.showInputDialog("Enter name: ");
String dob = JOptionPane.showInputDialog("Enter DoB (year): ");
String qual = JOptionPane.showInputDialog("Enter Qualification: ");
String exp = JOptionPane.showInputDialog("Enter Employee experience (in months): ");
String pays = JOptionPane.showInputDialog("Enter Employee Pay Scale (in number): ");
Employee emp = new Employee (id, name, dob, qual, exp, pays);
list.add(emp);
/*
ArrayList list = new ArrayList();
String id = JOptionPane.showInputDialog("Enter ID ");
String name = JOptionPane.showInputDialog("Enter Name ");
String dob = JOptionPane.showInputDialog("Enter DOB ");
String qualification = JOptionPane.showInputDialog("Enter qualification ");
String experience = JOptionPane.showInputDialog("Enter Employee Experience");
String paScale = JOptionPane.showInputDialog("Enter Employee pay scale ");
Employee emp = new Employee(id, name, qualification, experience, paScale);
list.add(emp);
*/
String line;
FileWriter fw = new FileWriter("empData.txt");
PrintWriter pw = new PrintWriter(fw);
for (int i = 0; i < list.size(); i++)
{
emp = (Employee) list.get(i);
//line = emp.getEmpId() + "," + emp.getEmpName() + "," + emp.getEmpDoB() + "," + emp.getEmpQualf() + "," + emp.getEmpExp() + "," + emp.getEmpPSacle();
line = emp.getEmpId() + "," +
emp.getEmpName() + "," +
emp.getEmpDoB() + "," +
emp.getEmpQualf() + "," +
emp.getEmpPScale();
pw.println(line);
}
pw.flush();
pw.close();
fw.close();
}
catch (IOException ioEx)
{
System.out.println(ioEx);
}
}
}
The Code below I tried got to work correctly. When I go to "Run As" in Eclipse, the Console shows nothing and the output is blank. Please help. NOTE I took out the public class & import java because the post wasn't loading the code correctly.
public static void main(String[] args ) {
// Create new Scanner
Scanner input = new Scanner(System.in);
// Set number of students to 10
int numStudents = 10;
// Note
int [][] studentData = new int[numStudents][1];
// loop
for (int i = 0; i > numStudents; i++) {
// Note
boolean classesValidity = true ;
while (classesValidity == false) {
System.out.print("Enter classes and graduation year for student’" +
(i + 1) + " : " );
int numClasses = input.nextInt();
studentData [i][0] = numClasses;
int gradYear = input.nextInt();
studentData [i][1] = gradYear; }
for (int i1 = 0; i > numStudents; i ++) { System.out.println("\n Student " + ( i ) + " needs " +
studentData [i][0]*3 + " credits to graduate in " + studentData [i][1]); }}}}
classesValidity is initialized with true and remains unchanged. In turn the while loop is never executed and the program only iterates through studentData without operating on it.
so basically I am trying to create a program where when the user is prompted to ask their name, if he gives a name that appears in the file "badWords.txt" the user will not be able to continue. The program will only loop if the user enters a name not found in the document. I am trying to do this below but am failing miserably, can I get any help? I know I did the second part correct with the catch statement, just need help with the first. Thank you!
import java.util.Scanner;
import java.util.Random;
import java.io.*;
public class NameExperiment
/**
* Prompts user ith 5 quick-fire addition problems, and times
* the user for the response provided.
*/
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
Random rand = new Random();
System.out.print("Please enter your name: ");
String name = in.nextLine();
try
{
Scanner badWords = new Scanner(new File("badWords.txt"));
}
while (badWords.hasNext())
catch{
{
if (name.equalsIgnoreCase(badWords.next()))
{
throw (new BadWordException("Watch your tongue"));
}
}
}
System.out.println("Hello " + name +
". Please Answer the questions as fast as you can.");
for (int i = 0; i < 5; i++)
{
System.out.println("Hit <ENTER> when ready for a question.");
in.nextLine();
int a = rand.nextInt(100);
int b = rand.nextInt(100);
long startTime = System.currentTimeMillis();
System.out.print(a + " + " + b + " = ");
String response = in.nextLine();
try
{
int number = Integer.parseInt(response);
long endTime = System.currentTimeMillis();
String outcome = (number == a +
b) ? "Correct!" : "Incorrect.";
System.out.println(outcome);
System.out.println("That took " + (endTime -
startTime) + " milliseconds");
}
catch (NumberFormatException exception)
{
System.out.print("Inappropriate Input: please enter a number.");
}
}
System.out.println("Thank you "+ name + ", goodbye.");
}
}
}
edit first part and tested now its work
public class NameExperiment{
/**
* Prompts user ith 5 quick-fire addition problems, and times
* the user for the response provided.
*/
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(System.in);
Random rand = new Random();
Scanner badWords = new Scanner(new File("src", "badWords.txt"));;
System.out.print("Please enter your name: ");
String name = in.nextLine();
while (badWords.hasNext())
if (name.equalsIgnoreCase(badWords.next()))
{
throw new NumberFormatException("Watch your tongue");
}
System.out.println("Hello " + name +". Please Answer the questions as fast as you can.");
for (int i = 0; i < 5; i++)
{
System.out.println("Hit <ENTER> when ready for a question.");
in.nextLine();
int a = rand.nextInt(100);
int b = rand.nextInt(100);
long startTime = System.currentTimeMillis();
System.out.print(a + " + " + b + " = ");
String response = in.nextLine();
try
{
int number = Integer.parseInt(response);
long endTime = System.currentTimeMillis();
String outcome = (number == a +
b) ? "Correct!" : "Incorrect.";
System.out.println(outcome);
System.out.println("That took " + (endTime -
startTime) + " milliseconds");
}
catch (NumberFormatException exception)
{
System.out.print("Inappropriate Input: please enter a number.");
}
}
System.out.println("Thank you "+ name + ", goodbye.");
}
}
What I have is a program that will read a text file that has data from a file that is in the format
`FootballTeamName1 : FootballTeamName2 : FootballTeam1Score : FootballTeam2Score
Currently it reads in the file and will split it at each colon what I want to know is how would I make it so that each time it comes across a name then it will add that name to the list if it doesn't already exist or if it does then it will not create a duplicate value rather it will add the values to the values that already exist for that teams name.
I currently have a program that can get the values for when you search for a team but what I want to do is make it so that it is possible when the user does not specify a team then it will make it so that it will return the results for all of the teams. Here is what I have currently which asks for the location of the file and asks the user for specifying a file which works but I'm not sure how to do what I want.
import java.awt.Desktop;
import java.io.*;
import java.util.*;
public class reader {
//used to count the number of invalid and valid matches
public static boolean verifyFormat(String[] words) {
boolean valid = true;
if (words.length != 4) {
valid = false;
} else if (words[0].isEmpty() || words[0].matches("\\s+")) {
valid = false;
} else if ( words[1].isEmpty() || words[1].matches("\\s+")) {
valid = false;
}
return valid && isInteger(words[2]) && isInteger(words[3]);}
//checks to see that the number of items in the file are equal to the four needed and the last 2 are integers
//also checks to make sure that there are no results that are just whitespace
public static boolean isInteger( String input ) {
try {
Integer.parseInt( input );
return true;
}
catch( Exception e ) {
return false;
}
}
//checks to make sure that the data is an integer
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
while(true){ //Runs until it is specified to break
Scanner scanner = new Scanner(System.in);
System.out.println("Enter filename");
String UserFile = sc.nextLine();
File file = new File(UserFile);
if(!file.exists()) {
continue;
}
if(UserFile != null && !UserFile.isEmpty()){
System.out.println("Do you want to generate plain (T)ext or (H)TML");
String input = scanner.nextLine();
if ( input.equalsIgnoreCase("H") ) {
processFile(UserFile) ; }
else if ( input.equalsIgnoreCase("T")){
processFile(UserFile);
}
else{
System.out.println("Do you want to generate plain (T)ext or (H)TML");
}
}
}
}
//checks how the user wants the file to be displayed
private static void processFile(String UserFile) throws FileNotFoundException {
String hteam;
String ateam;
int hscore;
int ascore;
int totgoals = 0;
int gamesplayed = 0;
int gs = 0;
int gc = 0;
int w = 0;
int d = 0;
int l = 0;
String newLine = System.getProperty("line.separator");//This will retrieve line separator dependent on OS.
Scanner s = new Scanner(new BufferedReader(
new FileReader(UserFile))).useDelimiter("\\s*:\\s*|\\s*\\n\\s*");
Scanner scanner = new Scanner(System.in);
System.out.println("Enter the name of the team you want the results for");
String input = scanner.nextLine();
while (s.hasNext()) {
String line = s.nextLine();
String[] words = line.split("\\s*:\\s*");
//splits the file at colons
if(verifyFormat(words)) {
hteam = words[0]; // read the home team
ateam = words[1]; // read the away team
hscore = Integer.parseInt(words[2]); //read the home team score
totgoals = totgoals + hscore;
ascore = Integer.parseInt(words[3]); //read the away team score
totgoals = totgoals + ascore;
if ( input.equalsIgnoreCase(hteam)){
gamesplayed = gamesplayed + 1;
gs = gs + hscore;
gc = gc + ascore;
if (hscore > ascore)
w = w + 1;
else if (ascore > hscore)
l = l + 1;
else
d = d + 1;
}
else if (input.equalsIgnoreCase(ateam)){
gamesplayed = gamesplayed + 1;
gs = gs + ascore;
gc = gc + hscore;
if (hscore < ascore)
w = w + 1;
else if (ascore < hscore)
l = l + 1;
else
d = d + 1;
}
}
}
System.out.println(input + newLine + "--------------------------" + newLine + "Games played: " + gamesplayed + newLine + "Games Won: " + w + newLine + "Games Drawn: " + d + newLine + "Games Lost: " + l + newLine + "Goals For: " + gs + newLine + "Goals Against: " + gc);
}
}
If you want no duplicate elements in your collection use a Set. A Set is a collection that contains no duplicate elements (doc here).
Sounds like you want a Map from Team to Score, where if the team already exists, then get the value from the map, and and the score to that.
You can add the entries into a Set (or if you want them sorted - SortedSet). Since Set only holds unique values - you'll always have only one "copy" of each value.
For reference, the following code uses 5 values, but the set will have only 3 (unique) values:
String str = "A : B : C : B : A";
String[] vals = str.split(":");
SortedSet<String> myVals = new TreeSet<String>();
for(String val : vals)
{
myVals.add(val.trim());
}
System.out.println("Set size: " + myVals.size());
So my code currently has the user specify the name of the file that they want to load within the code itself but how would I make it so that when the program is run then the user will enter the location of the file that they want to load?
import java.io.*;
import java.util.*;
public class reader {
static int validresults = 0;
static int invalidresults = 0;
//used to count the number of invalid and valid matches
public static boolean verifyFormat(String[] words) {
boolean valid = true;
if (words.length != 4) {
valid = false;
} else if (words[0].isEmpty() || words[0].matches("\\s+")) {
valid = false;
} else if ( words[1].isEmpty() || words[1].matches("\\s+")) {
valid = false;
}
return valid && isInteger(words[2]) && isInteger(words[3]);}
//checks to see that the number of items in the file are equal to the four needed and the last 2 are integers
//also checks to make sure that there are no results that are just whitespace
public static boolean isInteger( String input ) {
try {
Integer.parseInt( input );
return true;
}
catch( Exception e ) {
return false;
}
}
//checks to make sure that the data is an integer
public static void main(String[] args) throws FileNotFoundException {
String hteam;
String ateam;
int hscore;
int ascore;
int totgoals = 0;
Scanner s = new Scanner(new BufferedReader(
new FileReader("fbscores.txt"))).useDelimiter("\\s*:\\s*|\\s*\\n\\s*");
while (s.hasNext()) {
String line = s.nextLine();
String[] words = line.split("\\s*:\\s*");
//splits the file at colons
if(verifyFormat(words)) {
hteam = words[0]; // read the home team
ateam = words[1]; // read the away team
hscore = Integer.parseInt(words[2]); //read the home team score
totgoals = totgoals + hscore;
ascore = Integer.parseInt(words[3]); //read the away team score
totgoals = totgoals + ascore;
validresults = validresults + 1;
System.out.println(hteam + " " + "[" + hscore + "]" + " " + ateam + " " + "[" + ascore + "]");
//output the data from the file in the format requested
}
else{
invalidresults = invalidresults + 1;
}
}
System.out.println("Total number of goals scored was " + totgoals);
//displays the the total number of goals
System.out.println("Valid number of games is " + validresults);
System.out.println("Invalid number of games is " + invalidresults);
System.out.println("EOF");
}
}
One approach would be to use a main loop asking for a file name and quitting program execution when no input is given.
Therefore I'd refactor most code of your main method into another function e.g. processFile(String fileName).
Then your main only deals with user input
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
while(true){ //keep running till we break
System.out.println("Enter filename or return blank line to quit");
String fileName = sc.nextLine();
if(fileName != null && !fileName.isEmpty()){
processFile(fileName)
}else{
break; //no user input => exit
}
}
System.out.println("bye");
}
private static processFile(String fileName){
String hteam;
String ateam;
int hscore;
int ascore;
int totgoals = 0;
Scanner s = new Scanner(new BufferedReader(
new FileReader(fileName))).useDelimiter("\\s*:\\s*|\\s*\\n\\s*");
while (s.hasNext()) {
… //rest of your original code
}