Optimizing my guessing algorithm for number guesser - java

I'm a relatively new coder learning Java, and my CompSci teacher assigned us something called a number guesser game, where you have to guess a random number. However, in assignment was a section on extra credit, where the user thinks of a number, and the computer has to guess what the number is in as few tries as possible.
Right now, my code for doing so looks something like this:
public static void gamone() {
System.out.println("Think of a number between 1 and anything- I'll try and guess it.");
System.out.println("What is the end of the range?");
double range = s.nextDouble();
int guess, count=0, which = 0;
double base = 0;
String response;
guess = (int) (range / 2.0);
while (count < 15) {
count++;
System.out.println("Is the number " + guess + "?");
response = s.nextLine();
response = response.toLowerCase();
if (response.contains("yes")) {
System.out.println("I'm just that good, huh?");
break;
}
else if (response.contains("no")){
System.out.println("Was is higher or lower?");
response = s.nextLine();
response = response.toLowerCase();
if (response.contains("h")) {
base = guess;
guess = (int) ((range - guess) / 2.0) + guess;
}else if (response.contains("l")) {
range = guess;
guess = guess - (int)((guess - base) / 2.0);
}
}
}
System.out.println(count);
}
I Understand the best way mathematically is to simply do what I did- to divide the difference by 2 and add or subtract that. However, is there a way I could use things like random numbers to actually make it better at guessing numbers?

Related

Java while loop repeats and doesn’t exit when code reaches the end

I'm very inexperienced with coding, and am trying to make a very basic text based rpg combat system using my limited knowledge and the internet. Ideally the program should allow you to choose a type of attack, take the stamina cost away from your max stamina, then tell you how much damage you've done. As of now I am just trying to get the "normal attack" to work, but whenever you run the code and choose an attack it continuously just repeats the instructions on how to attack. I have included both the code and a screenshot of what displays when running. I assume the problem lies with me misusing the while loop, as I don't know much about it.
import java.util.Scanner;
import java.util.Random;
public class RPGv1 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
Random rand = new Random();
System.out.println("What is your name?");
String name = scan.nextLine();
System.out.println("\nWelcome to RPGv1 " + name + "!");
// Max Stats
int MaxHP = rand.nextInt(25) + 1;
int MaxMP = rand.nextInt(20) + 1;
int MaxStam = 15;
// Enemy 1 Stats
int En1HP = rand.nextInt(10) + 1;
int En1Stam = rand.nextInt(5) + 1;
// Combat
System.out.println("You are being approached by the evil Enemy 1!");
while (En1HP > 0) {
System.out.println("Type \"n\" to use your Normal Attack, \"h\" for your Heavy Attack, and \"f\" for your fireball.");
String combat = scan.nextLine();
if (combat == "n")
if (MaxStam >= 2) { //required stamina
int nDam = rand.nextInt(3) + 1; //damage
int nStam = rand.nextInt(5) + 1; //stamina use
MaxStam = MaxStam - nStam; //stamina being taken
System.out.println("You have dealt " + nDam + " damage, and have " + MaxStam + " Stamina remaining.");
} else {
System.out.println("You do not have enough stamina.");
}
}
}
}
enter image description here
You are never updating the value of En1HP variable, so it always remaings greater than 0, and thus loops goes for infinite.
To break the loop, you must need to update En1HP variable and set its value to less than zero on some condition.
Also as a code conventions, you should use camel-case naming convention for naming variable names.

Direct code to loop a text input check until correct?

I'm trying to write a simple little text adventure, DnD-style thing here as practice, but I have run into a problem that I can't for the life of me find a solution for.
I need to create a loop for when the user types the text response incorrectly because I don't want it responding to just anything the user types in and don't want to force the user to restart the entire program. I know about the do/while loop, but I have no idea how to implement it in a text input check because everyone uses it with numbers, not text.
Here's the code:
package drake;
import java.util.*;
public class drake {
public static void main(String[]args) {
Random rand = new Random();
Scanner kb = new Scanner(System.in);
int ini_d = rand.nextInt((17 - 12) + 1) + 12;
int ini_u = rand.nextInt((20 - 1) + 1) + 1;
int cha_d = 16;
int cha_u = 15;
int r_d = rand.nextInt((20 - 11) + 1) + 11;
int r_u = rand.nextInt((20 - 1) + 1) + 1;
int hp_d = 50;
int hp_u = 30;
int dam_d = rand.nextInt((12 - 7) + 1) + 7;
int dam_u = rand.nextInt((17 - 12) + 1) + 12;
System.out.println("A young dragon towers over you, it's reptilian eyes digging into your very soul. It roars at you, posing a challenge.");
System.out.println("Type 'roll' to roll for initiative.");
String u_r1 = kb.next();
while(true)
if (u_r1.equalsIgnoreCase ("roll")) {
System.out.println(ini_d);
System.out.println(ini_u);
break;
}
else {
System.out.println("Your input was invald. Please try again.");
//I need to give the user another chance to input text, and then direct the program to check it again and again until it's typed in correctly.
return;
}
if (ini_d >= ini_u) {
System.out.println("The dragon rushes towards you in an attempt to attack you.");
}
}
}
Move String u_r1 = kb.next(); as the first statement in the while loop should work for you (since you break on encountering the right input).
while(true) {
String u_r1 = kb.next();
if (u_r1.equalsIgnoreCase("roll")) {
System.out.println(ini_d);
System.out.println(ini_u);
break;
} else {
System.out.println("Your input was invald. Please try again.");
}
}
//Rest of the code

How to split a string up and save it to a variable if it is valid?

I'm having some problems splitting a string that is read in from an input file, making sure it's valid, then saving it to a variable.
Let's say this is the first string:
12345 5 59.28
I would want to split the 12345, 5, and 59.28.
After verifying that they are the correct format ( 00000-99999, 0-5, 000.00 0 100.00 ), I would then assign it to a variable.
My main two obstacles are that I CANNOT use arrays in this program, so I'm not sure how to split the string. I have tried just pulling each section as an int, but that doesn't seem to work.
My other problem is that I'm not sure how to validate it. Would I be using something like this:
//Assuming I have a scanner set up and a class, method declared
//Declare variables
int numbers;
int studentID;
while(fileInput.hasNext())
{
numbers = fileInput.nextInt(); //Not sure how to pull a part of the string
}
//Used to validate that it is within the range
if(numbers < 00000 || numbers > 99999)
{
studentID = numbers;
}
I am a beginner at Java so please do excuse my confusion.
If you know what the structure of the file is, for example if it's always formatted like this:
int int double
Then you can simply callnextInt(), nextInt(), and then nextDouble() to parse the data from it that way.
Maybe something like this
do
{
num1 = scanner.nextInt();
num2 = scanner.nextInt();
num3 = scanner.nextDouble();
} while (scanner.hasNextInt());
And do that in order to collect all of your data, but you'll likely need lots of variables if you have any substantial amount of data you're reading in
Or if there's bad data sometimes with it's correct data immediately after it you could so something like this to skip over the bad one, even though it's not very pretty
do
{
if (scanner.hasNextInt())
{
num1 = scanner.nextInt();
}
else
{
scanner.next() // move past whatever bad data there was
num1 = scanner.nextInt();
}
if (scanner.hasNextInt())
{
num2 = scanner.nextInt();
}
else
{
scanner.next() // move past whatever bad data there was
num2 = scanner.nextInt();
}
if (scanner.hasNextDouble())
{
num3 = scanner.nextDouble();
}
else
{
scanner.next() // move past whatever bad data there was
num3 = scanner.nextDouble();
}
} while (scanner.hasNext());
I think your teachers give this assignment to practice your if-else condition or switch statement and for loop(fundamental) skills.
Here what I did, this may be not completely match with your assignment question but using this you can get complete idea and think of a way to reduce this. Hey! because of we are not here to do your assignment. you have to tackle with your problem and get familiar with those.
Try to understand these, do changes look what happen:
public static void main(String[] args) {
Scanner fileInput = new Scanner(System.in);
//Declare variables
String numbers = "";
String firstNum = "";
String secondNum = "";
String thirdNum = "";
int studentID = 0;
int secondDigit = 0;
double thirdDigit = 0;
System.out.print("Input: ");
numbers = fileInput.nextLine();
int firstIndex = 0;
int secondIndex = 0;
int thirdIndex = 0;
firstIndex = numbers.indexOf(" ");
if(firstIndex <= 4){
System.out.println("Number should be 5");
}else{
firstNum = numbers.substring(0, firstIndex);
numbers = numbers.substring(firstIndex+1);
studentID = Integer.parseInt(firstNum);
if(studentID > 0 && studentID < 99999){
System.out.println("First num: " +firstNum);
}else{
System.out.println("first digits not in a range ");
}
}
secondIndex = numbers.indexOf(" ");
if(secondIndex == 0){
System.out.println("no number");
}else{
secondNum = numbers.substring(0, secondIndex);
numbers = numbers.substring(secondIndex+1);
secondDigit = Integer.parseInt(secondNum);
if(secondDigit >= 0 && secondDigit <= 5){
System.out.println("Second num: " +secondNum);
}else{
System.out.println("second digit not in a range ");
}
}
thirdIndex = numbers.length();
if(thirdIndex < 3){
System.out.println("3 numbers should be there");
}else{
thirdNum = numbers.substring(0, thirdIndex);
thirdDigit = Double.parseDouble(thirdNum);
if(thirdDigit >= 0 && thirdDigit <= 100){
System.out.println("third num: " +thirdNum);
}else{
System.out.println("third digit not in a range ");
}
}
}
I'm not going to explain this also. You have to try, if you have any problem after tackling with this code. ask any question in comment.
Hope this will help!
Try this. Invalid formats will throw an exception during the next method call.
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner in = new Scanner("12345 5 59.28");
in.useDelimiter(" "); // reads per space
String next = in.next("\\d{5}"); // reads next 5 digits
int numbers = Integer.valueOf(next);
System.out.println(numbers);
next = in.next("\\d{1}"); // reads next 1 digit
int studentId = Integer.valueOf(next);
System.out.println(studentId);
next = in.next("\\d{2}\\.\\d{2}"); // reads next a decimal with two digits before and after point
float floatingNumbers = Float.valueOf(next);
System.out.println(floatingNumbers);
}
}
<script src="//repl.it/embed/IWzC/0.js"></script>

Storing input data

Can anyone help me here?? I have compiled and successfully run a program using Java which takes user inputs from an "inputdialog" box and displays this information back in the console along with a simple mathematical formula. The problem I cannot seem to overcome is when the data is input the user has an option to enter another set of the same data type but I need the console to register this as a second input. This is how far I am currently with the section of code and my ideas on how to make this work using an array but I have been informed that saving/storing the data as an object might be a better option?
private void enterCar()
{
String carInfo;
int carHours;
int i = 0;
int[] carNumb = new int[20];
double fee = Double.parseDouble("7.50");
double sum = 0;
final int MAX = 12;
{
carInfo = JOptionPane.showInputDialog("Please enter the license plate of the car");
carHours = Integer.parseInt(JOptionPane.showInputDialog("Enter the number of hours the car was parked (1-12):"));
System.out.printf("\n");
System.out.printf("Details for car "+carNumb+" entered:\n");
System.out.printf("License plate Hours Fee:\n");
System.out.printf(""+carInfo+" "+carHours+" $");
if (carHours == 1)
System.out.printf("%3.2f",fee*(carHours));
else if (carNum == 2)
System.out.printf("%3.2f",fee+4.50);
else if (carHours >= 3)
System.out.printf("%3.2f",3+(carHours*4.50));
System.out.printf("\n\n");
}
}
When I compile and run the console I get the line "Details for car [I#6659c656 entered". This line does change to something like "[I#7665c575" the next time I activate the option so I can assume that I may need to assign a value to the number differently?
I have tried the option that is show in the code provided as well as trying to activate a list using (1, 2, 3, ect) but this also just outputs that random line of numbers and letters.
I guess to simplify my question. I need to store 20 individual inputs from an 'InputDialog' box and store it for later access in a console.
I need to store 20 individual inputs from an InputDialog box and store it for later access in a console.
Use a loop such as for.
That information then gets stored as "Details for car 1 entered:" and then the information displayed.
As I said before, you should use index of array instead of array. And because array is zero-based index, so I use carNumb[i] + 1 to print out the order.
Then calculate fee and store to carNumb array.
Note that, your fee is double type => carNumb should be double type to store correct value.
Full code:
public void enterCar() {
String carInfo;
int carHours;
int i = 0;
double[] carNumb = new double[20];
double fee = Double.parseDouble("7.50");
double sum = 0;
final int MAX = 12;
for (; i < carNumb.length; i++) {
carInfo = JOptionPane.showInputDialog("Please enter the license plate of the car");
carHours = Integer.parseInt(JOptionPane.showInputDialog("Enter the number of hours the car was parked (1-12):"));
System.out.printf("\n");
System.out.printf("Details for car " + (carNumb[i] + 1) + " entered:\n");
System.out.printf("License plate Hours Fee:\n");
System.out.printf("" + carInfo + " " + carHours + " $");
carNumb[i] = getFee(fee, carHours);
System.out.printf("%3.2f", carNumb[i]);
System.out.printf("\n\n");
}
}
private double getFee(double fee, int hours) {
if (hours == 1) {
return fee;
}
if (hours == 2) {
return fee + 4.5;
}
if (hours >= 3) {
return 3 + hours * 4.5;
}
return 0;
}
Did I get your idea?

Cmputer not following rules

I'm trying to come up with a reverse guessing game. Computer to guess my selected number with a range of 1-100. I do have the binary search algorithm, but when I tell the computer it's first guess is Too High, it will give me another High guess instead of going lower.
import java.util.Random;
import java.util.Scanner;
public class ComputersGuessGame {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Random value = new Random();
int computerGuess;
int highValue = 100;
int lowValue = 1;
String myAnswer;
do {
computerGuess = value.nextInt(highValue - lowValue +1)/2;
/*
*Above line should use the binary algorithm so the computer can
*make guesses and not just guess my number by going one number at a time
*/
System.out.println("I'm guessing that your number is " + computerGuess);
myAnswer = in.nextLine();
if (myAnswer.equals("tl")){
highValue = computerGuess + 1;//Too Low Answer
}
else if (myAnswer.equals ("th")){
lowValue = computerGuess - 1;//To High Answer
}
} while (!myAnswer.equals("y")); //Answer is correct
in.close();
System.out.println("Thank you, Good Game.");
}
}//Comptuer keeps making random guesses, but if I say too high, it will guess another high number instead of going low.
I think your logic to guess the next number was wrong. You should have interchange the setting the lower & high value,and change the logic to generate next guess.
here is the working solution of your problem
import java.util.Random;
import java.util.Scanner;
public class Guess {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Random value = new Random();
int computerGuess;
int highValue = 100;
int lowValue = 1;
String myAnswer;
do {
computerGuess = value.nextInt(highValue - lowValue)+lowValue;
System.out.println("I'm guessing that your number is " + computerGuess);
myAnswer = in.nextLine();
if (myAnswer.equals("tl")){
lowValue = computerGuess + 1;
} else if (myAnswer.equals ("th")){
highValue = computerGuess - 1;
}
} while (!myAnswer.equals("y"));
in.close();
System.out.println("Thank you, Good Game.");
}
}
you should try to approximate to your guess. you should try nested intervals. your working with class random, of course your computer could guess another high number again, when only lowering the range by one.
you should work with at least 2 new variables, rangeLow and rangeHigh. when to high, your new rangeHigh is your last guess. when to low, your new rangeLow is your last guess.
computerGuess = value.nextInt(rangeLow,rangeHigh);

Categories