Printing randomly fed values from an ArrayList in Java - java

I am processing elements of an ArrayList in random order, generally by printing them out. I would like to detect when the randomly selected index is 0 or 1 so as to perform special handling for those cases, where the handling for index 0 is partially dependent on whether index 1 has previously been processed. Specifically, nothing is immediately printed when index 1 is processed, but if it is processed then when index 0 is subsequently processed, both the index 1 and the index 0 values are printed. In any event, the loop is exited after ten iterations or after processing index 0, whichever comes first.
I tried to implement this using if statements, but there where obvious flaws with that one. I have searched everywhere for any examples but found none. I have begun to consider using sorting algorithms or threads to hold the first value found then continue looping until it sees the second the print it out. I would appreciate any help possible.
Here is my code:
public static void random_sortType(){
types = new ArrayList<String>();
types.add("Start");
types.add("Starting");
types.add("Load");
types.add("Loading");
types.add("End");
ran = new Random();
int listSize = types.size();
String tempEventType;//the temp variable intended to hold temporary values
for(int i = 0; i < 10; i++){ //the loop goes round the ArrayList 10 times
int index = ran.nextInt(listSize);//this produces the random selection of the elements within the list
if(index == 0){
out.println(types.get(index));
out.println();
break;
}
if(index == 1){
tempEventType = types.get(index);
if(index == 0){
tempEventType = types.get(0) + " " + types.get(1);
out.println(tempEventType);
break;
}
}/*if(index == 0){
tempEventType = types.get(0) + " " + types.get(1);
out.println(tempEventType);
break;
}*/
//out.print("Index is " + index + ": ");
//out.println(types.get(index));
}
}

You need to store the random generated index into a global variable and update it everytime a random number is generated. It should be something like this.
public static void random_sortType(){
types = new ArrayList<String>();
types.add("Start");
types.add("Starting");
types.add("Load");
types.add("Loading");
types.add("End");
` int previousIndex;
ran = new Random();
int listSize = types.size();
String tempEventType;//the temp variable intended to hold temporary values
for(int i = 0; i < 10; i++){ //the loop goes round the ArrayList 10 times
int index = ran.nextInt(listSize);//this produces the random selection of the elements within the list
previous_index =index;
if(index == 0){
out.println(types.get(index));
out.println();
break;
}
if(index == 1){
tempEventType = types.get(index);
if(previousIndex == 0){
temp EventType = types.get(0) + " " + types.get(1);
out.println(tempEventType);
break;
}

According to your description, these are the basic requirements for your application:
Process ArrayList in random order
Processing = printing value at randomly selected index
Make 10 attempts to process items in the list.
Detect when random index is 1 or 0.
if 1
don't process, but flag it was selected.
if 0 && 1 is flagged
process 0 and 1
exit
If these requirements are correct, here is the implementation I came up with:
import java.util.ArrayList;
import java.util.Random;
import static java.lang.System.*;
public class RandomSort {
private static final int MAX_ATTEMPTS = 10;
private static boolean wasOneSelected = false;
public static void main(String[] args) {
ArrayList<String> types = new ArrayList<>(5);
types.add("Start");
types.add("Starting");
types.add("Load");
types.add("Loading");
types.add("End");
random_sortType(types);
}
public static void random_sortType(ArrayList<String> types) {
Random ran = new Random();
int lastIndex = types.size() - 1; // index range is from 0 to 4
for (int i = 0; i < MAX_ATTEMPTS; i++) {
int index = ran.nextInt(lastIndex);
if ( (index == 0) && wasOneSelected) {
process(types.get(index) + " " + types.get(index + 1));
break;
} else if (index == 1) {
wasOneSelected = true;
} else {
process(types.get(index));
}
}
}
public static void process(String str) {
out.println("Processing: " + str);
}
}
The key here is the inclusion of the boolean wasOneSelected initialized to false. Once it is set to true, it will never be false again for the duration of the application. The if-else block handles all branching within the loop, and I favored wrapping the println call into a method called "process" for readability purposes to align it more closely with your description.
Feedback appreciated :)

Related

Dice roller Java returns less random results

i'm trying to make a little program thar throws "reservaDados" number of dice and compare the "dado" (who is a number between 1-10) to a specified dificulty. Then i want to print the count of the number of exits, fails and ultrafails, but i seem to have a problem with the number of times the loop works, it only prints 9 results and i don't seem to find why, i supose that it has to do something with the counter i?
import java.util.*;
public class ProgramTUI {
public static void main(String[] args) {
Scanner var = new Scanner(System.in).useLocale(Locale.ENGLISH);
System.out.print("Cuantos dados lanzas?");
int reservaDados = var.nextInt();
System.out.print("Cual es la dificultad?");
int dificultad = var.nextInt();
int i = 0;
int numero_exitos = 0;
int numero_fracasos = 0;
int numero_pifias = 0;
while (i < reservaDados) {
i++;
int dado = (int) (Math.random() * 10) + 1;
if (reservaDados == i) {
System.out.println("Has sacado " + numero_exitos + " exitos, " + numero_fracasos
+ " fracasos, " + numero_pifias + " pifias");
} else if (dado == 1) {
numero_pifias++;
} else if (dado < dificultad) {
numero_fracasos++;
} else {
numero_exitos++;
}
}
}
}
In the last iteration, no more counting is done, only the result is printed. So you effectively miss one iteration.
Could be fixed by removing the first else, or by doing one extra iteration.
But just take the whole result printing out of the loop and place it directly after the loop. That will make the intent of the code much clearer.
Thilo is right, in the last pass of the loop it dosn't count the dice because ther is a print first, i just taked out the print, and pasted at the end like this:
import java.util.*;
public class ProgramTUI {
public static void main(String[] args) {
Scanner var = new Scanner(System.in).useLocale(Locale.ENGLISH);
System.out.print("Cuantos dados lanzas?");
int reservaDados= var.nextInt();
System.out.print("Cual es la dificultad?");
int dificultad= var.nextInt();
int i=0;
int numero_exitos=0;
int numero_fracasos=0;
int numero_pifias=0;
while (i < reservaDados){
i++;
int dado= (int) (Math.random() * 10) + 1;
if (dado == 1) {numero_pifias++;}
else if (dado < dificultad) {numero_fracasos++;}
else {numero_exitos++;}
if (reservaDados == i){System.out.println("Has sacado "+numero_exitos+" exitos, "+numero_fracasos+" fracasos, "+numero_pifias+" pifias");}
}
}
}
And it was fixed, thanks!

How can I find Histogram using arrays?

Build/Output Histograms using Arrays Where i'm wrong?
This code takes 5 inputs from user in array and show the number of stars for example if user enter 3 then *** would be shown and so on .Where i'm wrong ?
public class P20 {
public static void main(String[] args) {
int[] anArray;
int Number;
//setup variable value
anArray = new int [10];
System.out.println("Enter some numbers between 1 and 100.");
for (int i = 0; i < 10; i++) {
System.out.println(i);
anArray[0] = 1-9;
anArray[1] = 10-19;
anArray[2] = 20-29;
anArray[3] = 30-39;
anArray[4] = 40-49;
anArray[5] = 50-59;
anArray[6] = 60-69;
anArray[7] = 70-79;
anArray[8] = 80-89;
anArray[9] = 90-100;
if(anArray > 0) {
System.out.println("*"+Number );
else if(anArray > 20)
{
System.out.println("**"+Number );
}
else if (anArray > 30)
{
System.out.println("***"+Number );
}
else if (anArray > 40)
{
System.out.println("****"+Number );
}
else if (anArray > 50)
{
System.out.println("*****"+Number ); }
}}
This code takes 5 inputs from user in array and show the number of stars for example if user enter 3 then *** would be shown and so on .Where i'm wrong ?
This code doesn't take inputs from the user.
You want the user to input a value and then you print the number of stars he/she wrote. You could do this like that:
public class P20 //Why don't you try giving names that are easier to remember
{
public static void main(String[] args)
{
for (int i=0; i<args[0]; i++)
{
System.out.print("*");
}
}
Where args[0] is the first argument given to the program when called:
java P20 3
Anyway, let me try to point out what some of the mistakes of your code are:
When you wrote:
anArray[0] = 1-9;
Did you really want to write that wich means "Let the 0th element of the array be the number 1 minus 9" (=-8)?
Or did you intent to input an interval? (Meaning the numbers from 1 to 9).
Then later on you say
if(anArray > 0)
Which doesn't make sense to me since anArray is an int[] variable and not an int variable. This means that anArray is not a variable which points directly to a number, but one pointing to an array object which holds several int values.
if(anArray > 0) {
you always will be > 0 so you always get only 1 x *
you hve to modify your if clause like that:
if (anArray > 0 && anArray < 20){
and so on...
edit:-----------------------------------------------------------
like you requested:
public String stars(int n) {
if (n == 1){
return "*";
}else{
return "*" + stars(n-1);
}
}

Randomize String Array and display all of the values

I'm making a card game, and I've arrived at the shufflin' time.
I've to shuffle a few cards (that are chosen before from the user, so they're not always the same amount) and then display them to the user one by one.
As I'm still developing the game's logic I'm displaying cards' name by changing a button text.
But I get stuck when I try to get the cards' name and set them as the button's text.
What happens is me gettin' a blank button or just with "Masons" or "Villager" String. Infact if I check the log I see that all the others cards(characters) get displayed as "null".
This is how I tried to achieve the goal (Yes I'm a newbie):
This is the head:
int demoniac;
int guard;
int masons;
int medium;
int mythomaniac;
int owl;
int villager;
int werehamster;
int all;
int i;
int t;
String[] characters = new String[24];
Button randomButton;
My method to addAll the cards(characters):
public void addAll(){
for(i = 0; i < all; i++){
add(demoniac, "Demoniac");
add(guard, "Guard");
add(medium, "Medium");
add(mythomaniac, "Mythomaniac");
add(owl, "Owl");
add(werehamster, "Werehamster");
add(villager, "Villager");
add(masons, "Masons");
}
}
My method to add and manage the various types of cards(characters):
public int add(int character, String name){
if(character != 0 && name == "Villager"){
for(t = 0; t < character; t++){
i+=t;
characters[i] = name;}
}
else if(character == 2 && name == "Masons"){
characters[i] = name;
i++;
characters[i] = name;
Toast.makeText(randomSelection.this, "works", Toast.LENGTH_SHORT).show();
}else if(character != 0){
characters[i] = name;
}
return i;
}
To randomize:
public void randomize(){
Collections.shuffle(Arrays.asList(characters));
for (int s = 1; s < characters.length; s++)
{
System.out.println(characters[s]);
}
}
The method to display a different card(character) each time the user clicks the button:
public void show(View view){
for (int s = 1; s < characters.length; s++)
{
randomButton.setText(characters[s]);
}
}
EDIT:
I've noticed the no sense for loop I've done, by the way you should know although most of the characters are only 1 of their kind (demoniac, guard, etc..) there are 2 Masons and from 5 to 12 Villagers, so We need to retrieve these ints and add as much Strings to the Array as much we're told from those ints.
Example: If I get 6 Villagers, I've to add the String "Villager" 6 times into the String Array.
Then I've set that s value to 1 'cause I've to display the first
String ([0]) as soon as the Activity gets started, so on the OnCreate() method.
Maybe I'm wrong, if so I please you to correct me!
Getting a blank button or just with "Masons" or "Villager" String
That is because you only set the Button's text with the last element of the list. Which is either null or "Masons" (not seeing how it could be "Villager").
for (int s = 1; s < characters.length; s++)
{
randomButton.setText(characters[s]);
}
If I check the log I see that all the others cards(characters) get displayed as "null"
You only set position 0 of your array. For example, you don't initialize the positions, so these int values default to 0.
int demoniac;
int guard;
int all;
Then
for(i = 0; i < all; i++){
add(demoniac, "Demoniac");
add(guard, "Guard");
Really, that loop shouldn't be entered because all equals 0.
Additionally
Collections are zero-indexed, so this doesn't print element 0. You need to set int s = 0;.
for (int s = 1; s < characters.length; s++)
It isn't clear to me what the add(int character, String name) method is returning, but if you explain it, I will update this answer.
I believe this code fulfills most of what you are trying to achieve
// Where the characters are stored
private ArrayList<String> characters;
public void initDeck() {
if (characters == null)
characters = new ArrayList<String>();
// Extract the numbers if you actually need them, otherwise, they just are constants
addCharacter("Demoniac", 1, characters);
addCharacter("Guard", 1, characters);
addCharacter("Medium", 1, characters);
addCharacter("Mythomaniac", 1, characters);
addCharacter("Owl", 1, characters);
addCharacter("Werehamster", 1, characters);
addCharacter("Villager", 5, characters);
addCharacter("Masons", 1, characters);
}
public void addCharacter(String name, int amount, ArrayList<String> cards) {
if (amount < 0) {
throw new IllegalArgumentException("Must add a non-negative number of characters for " + name);
}
// Don't use '==' for Strings
if (name.equals("Villager")) {
if (amount != 5 || amount != 12) {
throw new IllegalArgumentException("There can only be 5 or 12 " + name);
}
}
for (int i = 0; i < amount; i++) {
cards.add(name);
}
}
public int searchCharacters(String character, ArrayList<String> cards) {
return cards.indexOf(character);
}
public Map<String, Integer> getAllCharacterPositions() {
Map<String, Integer> allPositions = new LinkedHashMap<String, Integer>();
for (int i = 0; i < characters.size(); i++) {
allPositions.put(characters.get(i), i);
}
return allPositions;
}
void run() {
// initialize the characters
initDeck();
// shuffle them
Collections.shuffle(characters);
// print them all out
for (int i = 0; i < characters.size(); i++) {
System.out.printf("%d: %s\n", i, characters.get(i));
}
// Find the position of a character
System.out.println();
String findCharacter = "Owl";
// Option 1 -- always linear search lookup
System.out.printf("%d: %s\n", searchCharacters(findCharacter, characters), findCharacter);
// Option 2 -- one-time linear scan, constant lookup
Map<String, Integer> positions = getAllCharacterPositions();
System.out.printf("%d: %s\n", positions.get(findCharacter), findCharacter);
// Get a random character
System.out.println();
Random rand = new Random(System.currentTimeMillis());
int randPos = rand.nextInt(characters.size());
System.out.printf("%d: %s\n", randPos, characters.get(randPos));
// randomButton.setText(characters.get(randPos));
}
Given the array is already shuffled, just look at the first card:
public void show(View view){
randomButton.setText(characters[0]);
}
If you want to navigate that deck I suggest you put the shuffled list in to a Queue, where you can look at the next card (peek) or take the next card (poll):
private static Queue<string> buildNewShuffledDeck(String[] characters){
List<String> shuffledCharacterList = new ArrayList<String>(characters);
Collections.shuffle(shuffledCharacterList);
Queue<string> deck = new ArrayDeque(shuffledCharacterList);
return deck;
}
public void show(View view){
String nextCard = deck.peek();
if (nextCard != null)
randomButton.setText(nextCard);
else
//deck is empty...
}
Then to take from the deck, say on the random button click:
String nextCard = deck.poll();
General advice on arrays: Stop using them in favor of other data types that are far more useful and interchangeable.
Then next step advice, make a class that represents a Card and stop using Strings, the string you currently have is just one property of a card.
You are just displaying the last character name that you add
Replace with this
public void show(View view){
Random r = new Random(System.currentTimeMillis());
randomButton.setText(characters[r.nexInt(characters.length)])
}

Some issue with an enhanced for loop-SimpleDotCom

This is a modified example from the book, Head First Java. It's a kind of Battleship game where a 3 element array is being used as the battleship. The user has to guess these 3 locations. Currently, I've hard-coded the values of the ship location to 2,3,4. When the user guesses the correct location "Hit" is printed. If not then "Miss" is printed. If a user guesses all 3 locations then "Kill" is printed. But I have a problem. Currently if the user enters the same location multiple times, it still gives a hit. I tried to fix this by changing the value of a variable that has already been hit (int cell) to "-1". But for some reason this didn't fix it too. Please tell me what I am doing wrong.
public class Game {
public static void main(String[] args) {
// TODO Auto-generated method stub
int [] location = {2,3,4};
SimpleDotCom firstGame = new SimpleDotCom();
firstGame.setLocation(location);
firstGame.checkYourself("2");
firstGame.checkYourself("2");
//firstGame.checkYourself("2");
}
}
public class SimpleDotCom {
int [] loc = null;
int numOfHits = 0;
void setLocation (int [] cellLocation){
loc = cellLocation;
}
void checkYourself(String userGuess){
int guess = Integer.parseInt(userGuess);
String result = "Miss";
for(int cell:loc){
if (guess == cell){
result = "Hit";
numOfHits++;
cell = -1;
break;
}
if (numOfHits==loc.length){
result = "Kill";
}
}
System.out.print("Result: " + result);
System.out.println(" ** Num of Hits: " + numOfHits);
}
}
When you loop over loc, you get an int cell for each location. The problem is that that variable doesn't have any connection to the array, it's only a copy. If you change it, nothing's going to happen to the original array. I suggest looping over loc with a traditional for(;;) and using the current array index within the loop's logic to set the right "cells" to -1.
because you are assigning -1 to local variable. not updating in array actually
for(int cell:loc){ // cell is local copy of element in array is you have array of primitive int
if (guess == cell){
result = "Hit";
numOfHits++;
cell = -1;
break;
}
if (numOfHits==loc.length){
result = "Kill";
}
}
You can use traditional for loop for this or use List which has methods for adding removing elements.
You need to update the array at the correct index, not simply change the value of the cell variable, which only references the array element at the current iteration state.
You should probably use a traditionnal for loop for that, since you cannot get the index for free from an enhanced for loop.
for (int i = 0; i < loc.length; i++) {
//code...
loc[i] = -1; //instead of cell = -1;
}

Odd HashMap Counter Behavior

I have this code which applies a counter to each item on the list. When the item reaches a certain number it is moved from jList3 to jList 1.
public Map<Object, Integer> buttonMap = new HashMap<Object, Integer>();
private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {
Integer counter = null;
int[] selection = jList3.getSelectedIndices();
for (int i = 0; i < selection.length; i++){
Object selString = jList3.getModel().getElementAt(selection[i]);
counter = buttonMap.get(selString);
if(counter == null ) {
buttonMap.put(selString, new Integer(1));
}
else {
buttonMap.put(selString, new Integer(counter.intValue() + 1));
}
System.out.println(selString + " has been clicked " + buttonMap.get(selString) + " times.");
try{
if (counter == 4){
listModel2.removeElement(selString);
listModel.addElement(selString);
}
}
catch (NullPointerException npe1) {
npe1.getMessage();
}
}
}
The behavior comes in the if counter == 4 section.
It works fine but here is the weird part that I need help understanding
If I am counting up two items at the same time and they both reach the number that moves them on the same button click.
-It moves 1 of the items
-It does not count up on the other
-Instead it adds +1 to the counter of a non highlighted item
Example:
I am counting on list item 1 and 2, they both reach the max number, 1 gets moved 2 stays put(no increase in count) and item 3 gets +1 to counter
When you remove an element from jList3, the elements that follow are shifted.
I would sort the selection array and scan it in reverse order.
...
int[] selection = jList3.getSelectedIndices();
Arrays.sort(selection);
for (int i = selection.length; --i >= 0; ){
...
UPDATE: the sorting is not required, because the array returned by getSelectedIndices() already is
The problem is that you are modifying one of your model lists in the same loop as in which you are querying it. If you were using an iterator you would actually get a concurrent modification exception, but as it is you are using specific indexing. In either case your logic is now wrong because the indexes you were relying on to query the list have changed. You can sort your selection array in descending order and keep your code the way it is, but I think it will be cleaner and more maintainable to modify your source array after the loop is done, like so:
...
System.out.println(selString + " has been clicked " + buttonMap.get(selString) + " times.");
if (counter == 4) {
listModel.addElement(selString);
}
}
for(Object o : listModel) {
listModel2.removeElement(o);
}

Categories

Resources