Array will not update but rather print out the wrong array - java

I managed to figure out how to print the array for my connect four program but I cannot get the board to update with my code, I looked at it and ran it the code works in theory but however the array won't take the new inputs
Ive tried running it through with a for loop but that turned out wrong and I was thinking about putting the drop method in the print board method but I feel that that would result in an error
public class Connect4 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// DON'T MODIFY THE MAIN METHOD UNLESS FOR DEBUGGING
//MAKE SURE YOU GET RID OF YOUR MODIFICATIONS HERE BEFORE
SUBMISSION
String[][] board = createEmptyBoard();
Scanner input = new Scanner(System.in);
boolean bl = true;
printPattern(board);
while(bl) {
int player1 = 1 , player2 = 2 , userInput;
System.out.println("Please drop a RED disk at the column between 0
and 6:");
userInput = input.nextInt();
dropDisk(board, userInput , player1);
printPattern(board);
System.out.println("Please drop a YELLOW disk at the column
between 0 and 6:");
userInput = input.nextInt();
dropDisk(board, userInput , player2);
printPattern(board);
String win = checkWinner(board);
/*
Write code to announce if there is winner and end the game
*/
}
}
public static String[][] createEmptyBoard() {
/* This method prints the first empty pattern for the game
DON'T MODIFY THIS METHOD
*/
String[][] f = new String[7][15];
for (int i =0;i<f.length;i++) {
for (int j =0;j<f[i].length;j++) {
if (j% 2 == 0) f[i][j] ="|";
else f[i][j] = " ";
if (i==6) f[i][j]= "-";
}
}
return f;
} // end of createEmptyBoard
public static void printPattern(String[][] brd) {
for (int i = 0; i < 7; i++){
System.out.println(brd[i][0] + brd[i][1]+ brd[i][2]+ brd[i][3]+
brd[i][4]+ brd[i][5]+ brd[i][6]+ brd[i][7]+ brd[i][8]+ brd[i][9]+
brd[i][10]+ brd[i][11]+ brd[i][12]+ brd[i][13]+ brd[i][14]);
}
} // end of printPattern
public static void dropDisk(String[][] brd, int position, int
player) {
if (player == 1){
brd[6][position] = "R";
if(brd[6][position] == "R"){
brd[6][position] = brd[6 - 1][position];
}
}
else if (player == 2){
brd[6][position] = "Y";
if(brd[6][position] == "Y"){
brd[6][position] = brd[6 - 1][position];
}
}
/*Write your code to drop the disk at the position the user entered
depending on which player*/
} // end of dropDisk

The logic of dropDisk seems to be not finished yet.
It sets the brd[6][position] to R or Y, just to immediately after that set it to the current value of brd[5][position].
And this should always be null.

In Java, objects are passed into methods by value. This means that when you pass a parameter into a function, the JVM makes a copy of that object which can be modified in the method.
In this case, when you pass brd into dropDisk, it is copied, and you make changes to the copy inside dropDisk. But once dropDisk ends, that copy is discarded. No changes are made to the board from your main method. This is because your board is an array of Strings, and Strings are immutable, meaning that they cannot be changed after instantiation.
If you wanted the board from your main method to update, consider returning brd in dropDisk.

Related

It says 1 of 2 branches missed in java

I have 3 classes. I am trying to set a variable in the main method through an object called "main" and reuse that value by writing super.getnumberofsets(); in the for loop but it says "1 of 2 branches missed".
public static void main(){
//in the main method
//Main class maintain the private variables with their setters and getters.
Main main = new Main();
Sets sets = new Sets();
System.out.print("Enter how many sets you want to create: ");
newnumberofsets = in.nextInt();
main.set_numberofsets(newnumberofsets);
sets.setgroups();
sets.getgroups();
}
// in Sets class
protected void setgroups()
{
//In this loop it says "1 of 2 branches missed".
for(int x = 0; x<super.getnumberofsets();x++) {
main_zeroarray[x] = new Main0();
}
}
protected void getgroups() {
count = 1;
for(int x = 0 ;x < super.getnumberofsets();x++) {
System.out.println(count + ". Set " + setnames[x]);
count++;
}
}
I expected that the super keyword would read the same value from the object main.set_newnumberofsets(newnumberofsets);
The most likely explanation of there being a missed branch in the lopp is that that super.getnumberofsets() returns 0, so the loop terminating condition x < super.getnumberofsets() is false, thus the loop increment x++ is never executed, making it a "missed branch".

Controlling a linked list queue from my user/main class, not working

Okay so I need to create queue(contains enqueue, dequeue, and isEmpty methods), queueNode(stores names, setters and getters), and queueUser(Main) classes. User enters one name at a time. Once 3 names have been entered, each new name entered will kick the front of the queue to the screen. This process will continue until the user enters "quit" as the name. Once this happens, all the remaining names will be displayed. I have everything but my user/main class. I can't seem to get it to work properly. It accepts 3 names, and after the third name is entered, displays the first name that was entered. Problem is, it stops there. I need it to keep going. I have a feeling I need a different loop, but I am just stuck right now. No help from my instructor, nothing in my textbook, and I have hit a brick wall. Any help or suggestions is greatly appreciated. I am still fairly new to Java and totally new to data structures.
queueUser
import java.util.Scanner;
public class queueUser {
public static void main(String[] args){
queue qName = new queue();
Scanner input = new Scanner(System.in);
int limit = 3;
String name;
String stop = "quit";
boolean flag = false;
do{
for(int i = 0; i < limit; i++){
System.out.println("Please enter one name: ");
name = input.nextLine();
if(!name.equalsIgnoreCase(stop)){
qName.enqueue(name);
flag = true;
}else{
flag = false;
while(!qName.isEmpty()){
System.out.println(qName.dequeue());
}
}
}
System.out.println(qName.dequeue());
}while(!flag);
}
}
queue
public class queue{
queueNode front, rear;
int count = 0;
public queue(){
front = null;
rear = null;
}
public boolean isEmpty(){
boolean empty = false;
if(front == null){
empty = true;
}else{
empty = false;
}
return empty;
}
public void enqueue(String pName){
queueNode node = new queueNode(pName);
if(isEmpty()){
front = node;
}else{
rear.setNext(node);
}
rear = node;
}
public String dequeue(){
String firstName = null;
if(isEmpty()){
System.out.println("Queue is empty!");
}else{
firstName = front.getName();
front = front.getNext();
}
return firstName;
}
}
queueNode
public class queueNode {
private String name;
private queueNode next;
public queueNode(String pName){
name = pName;
}
public void setNext(queueNode pNext){
next = pNext;
}
public queueNode getNext(){
return next;
}
public void setName(String pName){
name = pName;
}
public String getName(){
return name;
}
}
(Edit: your professor)
In your loop code you are saying this:
Give me three names, but I'll stop if any the most recent name given was "quit".
After you give me these three names, I will tell you whats on top of the queue.
Now do it all over again.
You are not removing from the queue when you repeat the loop until you have put in an additional 3 names. Even then, you will only dequeue the top, leaving 4 in the queue.
First and foremost, you have a variable int count in your queue class that is never used. If you use that, it will GREATLY improve the solution here. When something is enqueued, increment the count variable. Decrement when dequeued. Add a method that will return the count variable. Then just do this:
boolean flag = false;
do {
System.out.println("Please enter one name: ");
name = input.nextLine();
if(name.equalsIgnoreCase("stop")) flag = true;
if (!flag) qName.enqueue(name);
if (qName.getCount() > 3) System.out.println(qName.dequeue());
} while (!flag);
for (int x = 0; x < 3; x++) System.out.println(qName.dequeue());
If your instructor wants it otherwise, then your code should be as follows:
boolean flag = false;
int count = 0;
do {
System.out.println("Please enter one name: ");
name = input.nextLine();
if (name.equalsIgnoreCase("stop")) flag = true;
if (!flag) {
count++;
qName.enqueue(name);
}
if (count > 3) {
count--;
System.out.println(qName.dequeue());
}
} while (!flag);
for (int x = 0; x < 3; x++) System.out.println(qName.dequeue());
EDIT: All of these apply to your QueueUser class.
Make sure you CamelCase your class names.
The do-while loop is redundant since the flag starting value is false. You can accomplish the same thing by just making it a while loop (unless that was a requirement by your professor to have one).
while(!flag) {
//do your stuff
}
Completely get rid of the for loop.
The problem with your original code is that the flag values are switched around, the flag is already false so there is no need to declare that in the do-while loop. If you wanted to leave this redundant portion in it would need to be flag = false.
if(!name.equalsIgnoreCase(stop)){
qName.enqueue(name);
flag = true; //<-----SHOULD BE FALSE if you don't want to break the loop (is redundant)
}else {
flag = false //<-------CHANGE TO TRUE
Set the limit variable to 0 (or rename it count and set it to 0) to satisfy the count functionality your professor wants and add an if statement in your while loop to dequeue when it reaches 3.
count++
if(count >= 3) {
System.out.println(qName.dequeue());
}

JLabel updating problems

I am creating a hangman game and I was having trouble getting the jlabel that contained each character of the word to update after the right letter button has been clicked. I have been having trouble with this as I am relatively new to working with Java Guis. Below is the action listener for the letter buttons.
private class LetterHandler implements ActionListener{
private char letterVal;
public LetterHandler(char lv){
letterVal = lv;
}
//checks if clicked button has the correct value as word char
public void actionPerformed(ActionEvent e){
for(int x = 1; x <= selectedWord.wordLength; x++){
if(selectedWord.wordValue.charAt(x - 1) == letterVal){
// JLabel letterValLabel = new JLabel(String.valueOf(letterVal));
wordSpacesArray.get(x-1).setName(String.valueOf(letterVal));
wordSpacesArray.get(x-1).revalidate();
continue;
}
else{
continue;
}
}
checkWin();
triesLeft--;
triesLeftLabel.revalidate();
}
//finds if all jlabels are complete or not
public void checkWin(){
for(int x = 1; x <= wordSpacesArray.size(); x++){
String charVal;
charVal = String.valueOf(wordSpacesArray.get(x-1));
if(charVal != "?"){
System.out.println("youWon");
System.exit(0);
}
else{
break;
}
charVal = null;
}
}
}
Any help is appreciated. Let me know if you need for of the programs code Thanks :)
There are some issues with the code. However, I'll first try to focus on your current problem:
I assume that wordSpacesArray is a list that contains the JLabels of individual letters of the word.
When this ActionListener will be notified, you try to update the labels in wordSpacesArray with the letter that corresponds to this button. However, in order to update the text that is shown on a JLabel, you have to call JLabel#setText(String) and not JLabel#setName(String). So the line should be
wordSpacesArray.get(x-1).setText(String.valueOf(letterVal));
// ^ Use setText here!
Now, concerning the other issues:
As pointed out in the comments, you should use 0-based indexing
The calls to revalidate are not necessary
The use of continue in its current for is not necessary
You should not compare strings with ==, but with equals
// if(charVal != "?") { ... } // Don't do this!
if(!charVal.equals("?")){ ... } // Use this instead
But the charVal in this case will be wrong anyhow: It will be the string representation of the label, and not its contents. So you should instead obtain the text from the label like this:
// String charVal = String.valueOf(wordSpacesArray.get(x-1)); // NO!
String charVal = wordSpacesArray.get(x-1).getText(); // Yes!
The triesLeftLabel will not be updated as long as you don't call setText on it
I think the logic of the checkWin method is flawed. You print "You won" when you find the first letter that is not a question mark. I think it should print "You won" when no letter is a question mark.
You should not call System.exit(0). That's a bad practice. Let your application end normally. (In this case, maybe by just disposing the main frame, although that would also be questionable for a game...)
So in summary, the class could probably look like this:
private class LetterHandler implements ActionListener
{
private char letterVal;
public LetterHandler(char lv)
{
letterVal = lv;
}
// checks if clicked button has the correct value as word char
#Override
public void actionPerformed(ActionEvent e)
{
for (int x = 0; x < selectedWord.wordLength; x++)
{
if (selectedWord.wordValue.charAt(x) == letterVal)
{
wordSpacesArray.get(x).setText(String.valueOf(letterVal));
}
}
checkWin();
triesLeft--;
triesLeftLabel.setText(String.valueOf(triesLeft));
}
// finds if all jlabels are complete or not
public void checkWin()
{
for (int x = 0; x < wordSpacesArray.size(); x++)
{
String charVal = wordSpacesArray.get(x).getText();
if (charVal.equals("?"))
{
// There is still an incomplete label
return;
}
}
// When it reaches this line, no incomplete label was found
System.out.println("You won");
}
}

Chat Bot, last part

Just one last part remaining in the ChatBot. I need to figure out a way to modify the chatbot class so
that it occasionally (say, 30% of the time) returns a randomly-­‐generated standard reply to user input one of at least five possible replies, like “LOL”, “OMG”, “You don’t say”, “Really?”, or “I see”.
Edit: Applied recommended changes:
import java.util.Random;
import java.util.Scanner;
public class ChatBot
{
private int responseCount = 0;
public String getResponse(String value)
{
String X = longestWord(value);
this.responseCount++;
if (responseCount == 10)
{
return "Sorry, but our time is up. I can't talk with you any longer.";
}
if (value.contains("you"))
{
return "I'm not important. Let's talk about you instead.";
}
else if (X.length() <= 3)
{
return "Maybe we should move on. Is there anything else you would like to talk about?";
}
else if (X.length() == 4)
{
return "Tell me more about " + X;
}
else if (X.length() == 5)
{
return "Why do you think " + X + " is important?";
}
else if (X.length() <=9)
{
return "Now we are getting somewhere. How does " + X + " affect you the most?";
}
return getRandomResponse();
}
public String longestWord(String value){
Scanner input = new Scanner (value);
String longest = new String();
longest = "";
while (input.hasNext())
{
String temp = input.next();
if(temp.length() > longest.length())
{
longest = temp;
}
}
return longest;
}
private String getRandomResponse()
{
String [] responses = {"OMG", "LOL", "You don't say", "Really?", "I See"};
return responses [(int)(Math.random() * responses.length)];
}
}
The problem is, it keeps returning the same response, instead of one of the five responses given. Any help would me much appreciated, thank you!
Edit:It's now giving only the random responses, and overriding every other response in the getResponse() method.
Given your logic, your getRandomResponse method should always return "OMG". This is because on the first run of the loop in that method, counter = 1. Thus the first if statement will run and will return "OMG" exitting the method. A nicer equivalent might putting all teh responses into an array and returning a random value from it, rather than doing somehting strange with iteration:
String[] responses = {"OMG", "LOL", "You don't say", "Really?", "I See"};
return responses[(int)(Math.random() * responses.length)];
In getRandomResponse, you make a random number generator using Random(), but you never use it. Then in your for loop, you execute your decision-making tree but use a variable counter that always begins at 0. Then on the first time through your loop, the first if statement will execute because 0 < 5, so "OMG" is returned.
Edit: I just noticed something else that is not going to work in your code:
Random randomNumber = new Random();
for (int counter =0; counter<10; counter++)
{
counter = randomNumber.nextInt();
You're trying to use counter to do two different things: you are trying to run this loop 10 times, but you're also using it to store random values.

I stuck with get out from while loop in method

I am writing program that asks user to type seven names of product.
what I try to do is if there is duplicate, then repeat the method.
I used while loop but I stuck.
If I put a,b,c,d,e,f,g at the first time, method ends and moves on to next method.
But if I typed a,a,b,c,d,e,f, program repeats same method and even if I type a,b,c,d,e,f,g, it gets in infinite loop.
here is my codes.
in main....
purchasedList.setShopList();
in purchasedList class...
public void setShopList() {
Scanner keyboard = new Scanner(System.in);
// print out description.
System.out.println("\n- Only have one entry of any type in the item list.");
System.out.println("- The name of items cannot be longer than 16 characters.");
System.out.println("\nType seven products.");
boolean sameNames = true;
while (sameNames == true) {
for (int i=0; i<7; i++) {
String n = keyboard.nextLine();
name.add(n);
name.set(i,name.get(i).toUpperCase());
}
sameNames = checkName();
}
}
// accessor.
public ArrayList<String> getShopList () {
return name;
}
// check duplicate.
public boolean checkName() {
Set<String> uniqueName = new HashSet<String>();
boolean foundName = false;
for (int i=0; i<7; i++) {
if (!uniqueName.add(name.get(i))) { // check duplicate
foundName = true;
}
}
if (foundName == true) {
System.out.println("※ There is a duplicate. Try it again.");
return true;
} else {
return false;
}
}
my checkName() method is fine because in my last project it worked.
in my last project, I put while loop in main like this
public static void main(String[] args) {
PurchasedList purchasedList = new PurchasedList();
.
.
.
boolean sameNames = true;
boolean tooLong = true;
while (sameNames == true || tooLong == true) {
System.out.println("\nType seven products.");
purchasedList.setShopList();
sameNames = purchasedList.checkName();
tooLong = purchasedList.checkLength();
}
but this time, because my professor wants me to make all operations are done within a method, so I try to fix.
I tried to solve it by myself in last 8 hours, but I could not get the solution.
Please help me.
Thank you.
add this line.
if (foundName == true) {
System.out.println("※ There is a duplicate. Try it again.");
-> name = new ArrayList<String>();
return true;
right now you are adding new names to the end of the array, and then setting them to upper case in the start of the array.
for (int i=0; i<7; i++) {
String n = keyboard.nextLine(); //Say I type in g on my second try
name.add(n); //This add g to the end of the array
name.set(i,name.get(i).toUpperCase()); //And this sets name[0] to G.
}
this means your name array is getting longer, instead of resetting.
Do you ever clean name? It appears you just keep adding to it, so the previous entrances are still there in loop's next round. And therefore there will always be a duplicate if you use same input as before (the order will not matter).
This change should do it:
while (sameNames == true) {
name = newArrayList <String>();
for (int i=0; i<7; i++) {
String n = keyboard.nextLine();
name.add(n);
name.set(i,name.get(i).toUpperCase());
}
sameNames = checkName();
}
So new name ArrayList is created every time. (Garbage collector will take care of the old ones, if necessary.) If name is already created somewhere else, then think if you really need it there - as far as I see you use it to gather input, and this happens in the method setShopList() so it appears you do not need it earlier than this.

Categories