Input only working once in Android - java

A question (ID 1606993) like this was posted, but didn't really answer mine, so here goes:
In an app for Android that I am creating, the user must input numbers from the keypad for the app to continue. When they are done entering their numbers, they can either press the return key or the main button. Problem is, its only working once.
Here is my listening method:
public boolean onKeyDown(int key, KeyEvent event)//Listens for key events
{
if(key==KeyEvent.KEYCODE_0)
add(0);
else if(key==KeyEvent.KEYCODE_1)
add(1);
else if(key==KeyEvent.KEYCODE_2)
add(2);
else if(key==KeyEvent.KEYCODE_3)
add(3);
else if(key==KeyEvent.KEYCODE_4)
add(4);
else if(key==KeyEvent.KEYCODE_5)
add(5);
else if(key==KeyEvent.KEYCODE_6)
add(6);
else if(key==KeyEvent.KEYCODE_7)
add(7);
else if(key==KeyEvent.KEYCODE_8)
add(8);
else if(key==KeyEvent.KEYCODE_9)
add(9);
else if(key==KeyEvent.KEYCODE_ENTER)
setNum();
else if(key==KeyEvent.KEYCODE_DPAD_CENTER)
setNum();
return true;
}
The add(int numb) method adds num to the text field that takes up the screen, its not causing any problems.
Here is setNum() :
protected void setNum()//Sets the number and tells the Runner it is set.
{
if(ray.size()==1)
num=ray.get(0);
else if(ray.size()==0)
num=0;
else
num=(ray.get(0)*10)+ray.get(1);
ray=new ArrayList<Integer>();//or ray.clear(), I've tried both
ready=true;
}
ArryayList ray is where the numbers are stored. The computation is working fine.
Int num is the number that the code uses. Boolean ready is there because in the runner class there is a while loop waiting for ready to be true to continue the code.
while(!a.ready)
{
for(int x=0;x<100;x++);
}
Any ideas?
Edit: Here is the method in Runner that is called:
while(!go)
{
addText("It is White's move");
addText("Possible pieces to move");
for(int x=0;x<b.getWhite().getPiecesWithMoves(b).size();x++)//Loop to print White's pieces that can move
{
addText(""+(x+1)+") "+b.getWhite().getPiecesWithMoves(b).get(x));
}
got=false;
p=0;
while(!got)//Loop to enter number
{
addText("Input the number of the piece you want to move");
while(!a.ready)
{
for(int x=0;x<100;x++);
}
p=a.num-1;
if(p<b.getWhite().getPiecesWithMoves(b).size()&&p>=0)//Checks to make sure that p is valid
got=true;
a.num=0;
a.ready=false;
}
gl=b.getWhite().getPiecesWithMoves(b).get(p).getLocation();//Makes a location that is where the piece currently is
addText("Possible moves");
for(int x=0;x<b.getPiece(gl).getMoves(b).size();x++)//Loop to print where the piece can go
{
addText(""+(x+1)+") "+b.genL(b.getPiece(gl).getMoves(b).get(x)));
}
got=false;//reset
while(!got)//Loop to enter number
{
addText("Input the number of one of these moves.");
addText("If you wish to change, enter 0.");
while(!a.ready)
{
for(int x=0;x<100;x++);
}
p=a.num-1;
if(p==-1)
got=true;
else if(p<b.getPiece(gl).getMoves(b).size()&&p>=0)//Checks to make sure that p is valid
{
got=true;
go=true;
}
a.num=0;
a.ready=false;
}
}
gk=b.getPiece(gl).getMoves(b).get(p);//The location that the piece is going to
b.move(gk, b.getPiece(gl),gk.isTaken(),gk.isCastle());//Moves the piece

public class MyView {
int num;
int currentState = 1; //much, much more pretty if you'd use Enum,
//but I'll keep it simple now.
public boolean onKeyDown(int key, KeyEvent event) {
//no changes here
}
protected void setNum(){
if(ray.size()==1)
num=ray.get(0);
else if(ray.size()==0)
num=0;
else
num=(ray.get(0)*10)+ray.get(1);
ray=new ArrayList<Integer>();
if (currentState == 1) //(TODO:should really use Enum here....)
part1();
else if (currentState == 2)
part2();
else if (...
}
void part1() {
addText("It is White's move");
addText("Possible pieces to move");
for(int x=0;x<b.getWhite().getPiecesWithMoves(b).size();x++)
{
addText(""+(x+1)+") "+b.getWhite().getPiecesWithMoves(b).get(x));
}
addText("Input the number of the piece you want to move");
currentState = 2;//now we do nothing, we wait untill user finishes input
}
void part2()
{//will be called after part1 finishes and a number has been entered
p=a.num-1;
if(p<b.getWhite().getPiecesWithMoves(b).size()&&p>=0) {
gl=b.getWhite().getPiecesWithMoves(b).get(p).getLocation();
addText("Possible moves");
//and more code
//Need input? stop and set next entry point
currentState = 3;//continue to part 3
}
else
{
addText("Input the number of the piece you want to move");
currentState = 2;//oops, stay at part2, we didn't get a good number!
}
}
}
The idea is to do nothing when the user has to input. There is no code running at that moment, for example after part1() finishes. When the user finishes input and presses a key, you have to make sure the correct code then executes, part2 gets called then. And then just stop running code when you need input again.
Good luck!

Related

Not able to store multiple records in an array

I am trying to make a Book Database GUI which inserts the title,author and price of each book in the array created.
There is a search function to search a particular book in the database by its title.
However my code only seems to work for only one book and not for multiple books.
I am trying to enter 10 book details here for instance.
I am only able to search the book which was created the last.
My Code is as follows:
class Book{
public String title,author;
public int price;
Book(String t,String a,int p){
this.title=t;
this.author=a;
this.price=p;
}
}
class Swingdemo implements ActionListener{
Book B[]=new Book[10];
JLabel jl1;
JTextField a1,a2,a3,a4;
JButton j1,j2,j3;
Swingdemo() {
JFrame jfrm = new JFrame("Welcome");
jfrm.setSize(180,300);
jfrm.setLayout(new FlowLayout());
jfrm.setDefaultCloseOperation(jfrm.EXIT_ON_CLOSE);
a1 = new JTextField(8);
a2 = new JTextField(8);
a3 = new JTextField(8);
j1 = new JButton("Create");
a4 = new JTextField(8);
j2 = new JButton("Search");
jl1 = new JLabel("Press a Button");
j1.setActionCommand("1");
j2.setActionCommand("2");
j1.addActionListener(this);
j2.addActionListener(this);
jfrm.add(a1);
jfrm.add(a2);
jfrm.add(a3);
jfrm.add(j1);
jfrm.add(a4);
jfrm.add(j2);
jfrm.add(jl1);
jfrm.setVisible(true);
}
int num=0;
public void actionPerformed(ActionEvent ae){
if(ae.getActionCommand().equals("1")){
B[num]=new Book(a1.getText(),a2.getText(),Integer.parseInt(a3.getText()));
jl1.setText("Book has been added");
num++;
}
else{
int i;
for(i=0;i<B.length;i++){
if(B[i].title.equals(a4.getText()))
jl1.setText("Book has been found");
}
if(i==B.length)
jl1.setText("Book was not found");
}
}
public static void main(String []args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new Swingdemo();
}
});
}
}
I prefer use Optional wrapper instead of local variable such as found
Optional<Book> mbyBook = Optional.empty();
for (Book b : B) {
if (b.title.equals(a4.getText())) {
mbyBook = Optional.of(b);
break;
}
}
if (mbyBook.isPresent()) {
jl1.setText(String.format("Book has been found %s", mbyBook));
} else {
jl1.setText("Book was not found");
}
The way to solve a problem like this is to separate it from all the irrelevant Swing stuff, into a method of its own:
public String findBook(String title) {
int i;
for(i=0;i<B.length;i++){
if(B[i].title.equals(title))
return("Book has been found");
}
if(i==B.length)
return("Book was not found");
}
}
All I have done here is copy/paste your code from int i onward, and put it in a method, passing title instead of looking directly at the Swing text fields. Then I replaced the setTexts with return.
You can call this by replacing the whole chunk in your main code with:
jl1.setText(findBook(a4.getText());
Now the method is independent of Swing, and you can test it on its own.
The first problem is that it won't compile. Now that we've returned the setTexts with return the compiler can noticed that there's a route through the code that doesn't return anything -- where all the ifs are false.
So let's make it compile, by adding a return at the end. We'll also add braces {} so that the ifs are visually consistent. Never leave out braces, even though the compiler lets you.
public String findBook(String title) {
for(int i=0;i<books.length;i++){
if(books[i].title.equals(title))
return("Book has been found");
}
if(i==books.length) {
return("Book was not found");
}
}
return null;
}
I also moved the declaration of i into its initialiser. It's a familiar form.
And I renamed B to books. In Java we tend towards descriptive variable names, and variables always start with a lower-case letter.
Now we have something that compiles. One good approach is to run tests in a debugger (your IDE has one). But we can eyeball this code, and work out what it would do when the book is not found.
Let's say B[] is just 3 items long. i starts at 0.
Is 0 < 3 ? Yes. Continue with loop.
Does B[0] match on title? No. Skip if.
Does 0 == 3? No. Skip if.
i++ -- i == 1
Is 1 < 3 ? Yes. Continue with loop.
Does B[1] match on title? No. Skip if.
Does 1 == 3? No. Skip if.
i++ -- i == 2
Is 2 < 3 ? Yes. Continue with loop.
Does B[2] match on title? No. Skip if.
Does 2 == 3? No. Skip if.
i++ -- i == 3
Is 3 < 3 ? No. Exit loop.
return null
We never pass the if(i==B.length) test, because we only ever enter that block when i<B.length.
But that return null gets hit. So you can make it do what you want by putting the not found response after the loop:
public String findBook(String title) {
for(int i=0;i<Books.length;i++){
if(Books[i].title.equals(title))
return("Book has been found");
}
}
return("Book was not found");
}
boolean found = false;
for(i=0;i<B.length;i++) {
if(B[i].title.equalsIgnoreCase(a4.getText().trim())) {
found = true;
break;
}
}
if(!found)
jl1.setText("Book was not found");
else
jl1.setText("Book has been found");
Or you could also do,
for(i=0;i<B.length;i++) {
if(B[i].title.equalsIgnoreCase(a4.getText().trim())) {
break;
}
}
if(B.length > 0 && i < B.length)
jl1.setText("Book has been found");
else
jl1.setText("Book was not found");

Why does nothing happen when a "if ... <=0" criteria is met?

I have a player controlled object which is set to 100 health. With each hit from an enemy it goes down. The problem is, after it reaches 0 health, it still keeps going further into the negatives. I have a popup set
private void playerHealth(){
if (player.health <= 0)
JOptionPane.showMessageDialog(null, "you lose");
System.exit(0);
}
so that in theory, it should pop up after health is <=0. However, when I try to run it, it just opens and closes immediately. I can see the window for a split second. If I delete the
JOptionPane.showMessageDialog(null, "you lose");
System.exit(0);
and replace it with say,
player.isAlive = false;
(isAlive is set true for player, enemies and all bullets), the health will continue to decrease past the negatives.
This part might help as well: Its the code to delete the dead enemies and bullets, there is nothing similar for player, so that may be the problem.
private void removeDead(){
for (int i = 0; i <bullets.size(); i++){
if (bullets.get(i).isAlive == false )
bullets.remove(i);
}
for (int i = 0; i <mobs.size(); i++){
if (mobs.get(i).isAlive == false )
mobs.remove(i);
}
for (int i = 0; i <mobBullets.size(); i++){
if (mobBullets.get(i).isAlive == false )
mobBullets.remove(i);
}
bullets.trimToSize();
mobs.trimToSize();
mobBullets.trimToSize();
}
So any help is appreciated. Thank you. (all the code is from an online tutorial, which is why I dont know anything.)
If you want both statements to be executed, surround them in a block :
private void playerHealth() {
if (player.health <= 0) {
JOptionPane.showMessageDialog(null, "you lose");
System.exit(0);
}
}
Without the curly braces, System.exit(0); is not part of the if statement and will always be executed, which explains the it just opens and closes immediately.
I agree with the previous answer.
However, you need to know how to avoid such problems in the future. Use an IDE or other editor that will automatically indent your code for you. Here is what one did to the failing if-statement:
private void playerHealth() {
if (player.health <= 0)
JOptionPane.showMessageDialog(null, "you lose");
System.exit(0);
}
The problem becomes much more obvious.
It looks like you missed a { on your if statement, if you want to execute a block of code in an if statement you need to do
if(something){
response;
}
So it should be this:
private void playerHealth() {
if (player.health <= 0) {
JOptionPane.showMessageDialog(null, "you lose");
System.exit(0);
}
}

Simple Binary Search Program....Please tell me what is wrong in this specific code

Im a beginner.
Here is a binary search code.Its showing array out of bounds error for main method.
please look into the program and kindly tell me my mistake.ill be grateful for ur service.
i have to write all this crap cause i cant post it as its asking for more details.
public class BinaryS
{
int n;
public BinaryS(int z)
{
n=z;
}
static int pos;
static boolean flag=false;
public void disp()
{
int arr[]={0,1,2,3,4};
int len=arr.length;
int first=0;
int last=len;
int mid=(int)(first+last/2);
//boolean flag=false;
while(mid>=0 && mid<=len)
{
if(n<arr[mid])
{
last=mid;
}
if(n>arr[mid])
{
first=mid;
}
if(n==arr[mid])
{
flag=true;
pos=mid+1;
}
}
if(flag==true){
System.out.println("the no."+n+"is found at"+pos);
}
else{
System.out.println("the no."+n+"is not found ");
}
}
public static void main(String args[])
{
BinaryS obj=new BinaryS(2);
obj.disp();
}
}
Currently your code does compile, and runs forever - because of this loop:
while(mid>=0 && mid<=len)
{
// Code which doesn't modify mid or len
}
Assuming it gets into that loop at all (which it does), the condition is never going to become false - so unless you return or break from within the loop (you don't) or an exception is thrown (it isn't) you're just going to keep going round the loop.
This is where you should:
Use a debugger to observe what's happening
Think about what the condition should actually be and how you want it to become false
Adjust your code to either change the condition, or change the loop body so that it modifies mid or len

Java TicTacToe - comparing lots of values

I am writing this TicTacToe game. We all know how TicTacToe works, either somebody wins or nobody wins and the board gets full.
board.playable() checks to see if somebody has won the game or if the board is full. This code runs fine but I'm just wondering if there is a tidier way to write my while loop. It just seems a bit redundant to have the same condition twice. But I need to run the board.playable() check before the computer makes his move.
public void runGame()
{
while(board.playable()==true)
{
// Outputs a visual representation to console window
this.displayBoard();
// Asks player to enter a valid number
this.playerMove();
// Check if it still playable for the next
if(board.playable() == true)
{
computerMove()
}
}
this.displayBoard();
// Outputs the final status of the game and the winner if any
if(board.wonBoard()==true) {
System.out.println(board.whoWon() + " has won the game");
} else {
System.out.println("The board is full. Nobody has won the game");
}
}
Your program doesn't seem to have a "turn" state. If it had such an entity, then it could play a turn and check for winner after each turn. Also, get rid of == true in all of your code.
while (gameNotOver) {
// assuming an enum called Turn
if (turn == Turn.PLAYER) {
doPlayersTurn();
} else {
doComputerTurn();
}
checkForWin();
turn = turn.nextTurn();
}
while(board.playable())
{
// Outputs a visual representation to console window
this.displayBoard();
// Asks player to enter a valid number
this.playerMove();
// Check if it still playable for the next
if(board.playable())
{
computerMove();
}
}
remove ==true
You can use the flag to know whose move is : Like this
boolean playerTurn = Boolean.TRUE;
while(board.playable()==true)
{
// Outputs a visual representation to console window
this.displayBoard();
// Asks player to enter a valid number
if(playerTurn){
this.playerMove();
playerTurn=Boolean.FALSE;
}
else{
computerMove();
playerTurn = Boolean.TRUE;
}
}

Can I manipulate the way that variables change in Java?

If the die shows a 6, the player doesn't move at all on this turn and also forfeits the next turn.
To accomplish this, I have tried an integer type warning marker variable for the player and an integer type time counter variable.
If the die shows 6, I want to increment the warning marker variable by 1 during the first run(and have the while loop do nothing), then keep the value at 1 during the second run (while loop will not work), then lower it back down to 0 for the third run of the while loop (so the while loop will work). The marker will stay at zero unless the die shows a 6 again, after which the same process will repeat.
I have a while loop like this:
while the warning marker is equal to 0 {
Do Stuff
if the die shows a 6, the warning marker increases by 1.
the time counter also increases by 1.
}
How do I manipulate the variables to get the result that I need? Or is my partially complete method absolutely off in terms of logic?
Thanks.
Can u tell me if this works for you?
flag=true;
while condition{
if flag==true{
if die == 6
{
flag=false;
continue;}
}
else { Do STUFF }
} else
{
flag==true;
}
}
I think you want to reword this problem.
This is what I understood. You have a warning marker.
You have a loop that checks whether the marker is 0, if it is then you do something.
If the die is a six, you will increase the warning marker. If its new value is 3, then you will reset it to 0. Meanwhile, the time counter is always increasing.
If this is correct, I think you want something like:
int warningMarker = 0;
int timeMarker = 0;
while (true) {
if (die == 6) {
++warningMarker;
if (warningMarker == 3) {
warningMarker = 0;
}
}
if (warningMarker == 0) {
doSomething();
}
++timeMarker;
}
Java is Object-Oriented Pragramming language. Use this feature.
See following pseudocode and let me know if you have problem in undestanding it.
Create a class Player as following:
class Player
{
boolean skipChance = false;
... // Other fields
... //
}
Change your while as following:
while(isGameOn())
{
Player p = getCurrentPlayer();
if( ! p.skipChance)
{
int val = p.throwDice();
if(val == 6)
{
p.skipChance = true;
continue; // control moves to while.
}
// Do stuff
}
else
{
p.skipChance = false;
}
}

Categories

Resources