Exception in thread "main" java.lang.AssertionError. What shall I do? - java

I am trying to make a program which will take a random guess from a range of numbers and checks whether it matches with the given number.
It will run 10times, it the program guesses the correct answer then it will terminate but if not then it will terminate with rejection.
at GuessingTest.main(GuessingTest.java:33)
**current directly** ; /usr/bin/env /Li
brary/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home/bin/java #/var/folders/zl/r96mn6p116125gw39hst2gp40000gn/T/cp_2tq0yp3psptn6qjx3o6su
w328.argfile GuessingTest
Exception in thread "main" java.lang.AssertionError
at org.junit.Assert.fail(Assert.java:87)
at org.junit.Assert.assertTrue(Assert.java:42)
at org.junit.Assert.assertTrue(Assert.java:53)
at GuessingTest.guess(GuessingTest.java:30)
at GuessingTest.main(GuessingTest.java:35)
Below is my code
Guessing.java
public class Guessing {
// Your local variables here
private int low = 0;
private int high = 1000;
int randomNum;
/**
* Implement how your algorithm should make a guess here
*/
public int guess() {
randomNum = (int) ((Math.random() * (low - high)) + low);
return randomNum;
}
/**
* Implement how your algorithm should update its guess here
*/
public void update(int answer) {
if (answer == 1) {
low = randomNum;
} else if (answer == -1) {
high = randomNum;
}
}
}
GuessingTest.java
import org.junit.Test;
import java.util.Random;
import static org.junit.Assert.*;
public class GuessingTest {
#Test
public void guess() {
Random r = new Random();
int hiddenNumber = r.nextInt(1001);
Guessing g = new Guessing();
int remainingGuesses = 10;
while (remainingGuesses >= 0) {
int guess = g.guess();
if (guess == hiddenNumber) {
break;
} else if(guess > hiddenNumber) {
g.update(1);
remainingGuesses--;
} else {
g.update(-1);
remainingGuesses--;
}
}
assertTrue(remainingGuesses >= 0);
}
public static void main(String[] args) {
GuessingTest test = new GuessingTest();
test.guess();
}
}

The exception you're getting is a result of failing the guess() test.
assertTrue(remainingGuesses >= 0);
In other words, you're expecting the hiddenNumber to be found within 11 steps (0..10), but it's not. And there's no reason for it to be. Your code returns negative numbers.
Also it wouldn't work even if it was returning positive numbers, since you could easily guess 0, 1, 2 ... up to 10, ending with 10 as low and 1000 as high.
Also -- how to get random numbers within a specific range: https://stackoverflow.com/a/5887745/684296

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!

Java Program does not give the output for values of n>6, Why?

import java.util.*;
class A{
static int count=0;
static String s;
public static void main(String z[]){
int n;
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
System.out.println(noOfBouncy(n));
}
public static int noOfBouncy(int k){
int limit=(int)Math.pow(10,k);
s=new String("1");
int num=Integer.parseInt(s);
while(num<limit){
if(isIncreasing(s) || isDecreasing(s) ){
}
else{
count++;
}
num++;
s=new String(Integer.toString(Integer.parseInt(s)+1));
}
count=limit-count;
return count;
}
}
public static boolean isIncreasing(String s){
int len=s.length();
for(int i=0;i<len-1;i++){
if(s.charAt(i)>s.charAt(i+1)){
return false;
}
}
return true;
}
public static boolean isDecreasing(String s){
int len=s.length();
for(int i=0;i<len-1;i++){
if(s.charAt(i)<s.charAt(i+1)){
return false;
}
}
return true;
}
I have given the definitions to the two functions used isIncreasing() & isDecresing()
The program runs well for the value of n<7 but does not respond for values above it, Why ?
I accept the programming style is very immature,please ignore.
I've tried to execute it with n=7 and it finishes in 810ms, returning 30817.
However, I recommend to you to optimize the performance of your program by saving unnecessary object instantiation: It will be better if you maintain the counter in num, and convert it to string just once, at the beginning of the loop:
int num=1;
while (num < limit)
{
s=Integer.toString(num);
if (isIncreasing(s) || isDecreasing(s))
{
}
else
{
count++;
}
num++;
}
Like this it takes just 450ms to finish.
The program was not actually stuck but it is taking way too much time to complete its execution when value of 'n' is larger.
So now the question is, I need to optimize the code to take minimum time #Little have an optimization bit that's not enough.
Any hint would be appreciable.
To increase the performance you should avoid the conversation to String and do the check with numbers.
As it doesn't matter for the result if you start the comparison from left to right or from right to left one computational solution could be.
as pseudo code
1) compare the value of the right most digit with the digit on it's left
2) is it lower --> we found a decreasing pair
3) else check if it is bigger --> we found an increasing pair
4) else --> not a bouncy pair
5) if we found already one decreasing and one increasing pair it's bouncy number
6) divide the number by ten if it's bigger then ten repeat with step 1)
The method to check if it's a bouncy number could look like this
static boolean isBouncyNumber(int number) {
boolean increasingNumber = false;
boolean decreasingNumber = false;
int previousUnitPosition = number % 10;
int remainder = number / 10;
while (remainder > 0) {
// step 1
int currentUnitPosition = remainder % 10;
if (currentUnitPosition > previousUnitPosition) {
// step 2
decreasingNumber = true;
} else if (currentUnitPosition < previousUnitPosition) {
// step 3
increasingNumber = true;
}
// step 5
if (decreasingNumber && increasingNumber) {
return true;
}
// step 6
previousUnitPosition = currentUnitPosition;
remainder = remainder / 10;
}
return decreasingNumber && increasingNumber;
}

How would I store the health values and run again until either player health == 0 or enemy health == 0

What would be the best way for me to code the the actual attack / defend between the two characters and how would I store the health value so that re attacks could be stored until either player health or enemy health reached 0, and then declare the victor. This is my first ever attempt at any kind programming after self teaching from various sources, please also give me feed back on any improvement I could make, I'm sure there will be many.
Thank you in advance.
:-)
package test;
public class BattleClass {
public static void main(String[] args) {
PlayerStats ps = new PlayerStats();
EnemyStats es = new EnemyStats();
int eh = es.getEnemyHealth();
int ph = ps.getPlayerHealth();
ps.PlayerAttackDefend();
es.AttackDefend();
System.out.println("You chose to " + ps.getpInput() + " and rolled "
+ ps.getPlayerRoll());
System.out.println("The enemy chose to " + es.getEaod()
+ " and rolled " + es.getEnemyRoll() + ".");
if (ps.getpInput().equals("Attack")) {
if (es.getEaod().equals("Attack")) {
System.out
.println("YOUR SWORDS BOUNCE OFF EACHOUTHERS... TRY AGAIN!");
System.exit(0);
}
if (es.getEaod().equals("Defend")) {
if (ps.getPlayerRoll() > es.getEnemyRoll())
eh -= ps.getPlayerRoll() - es.getEnemyRoll();
System.out.println("Enemy Health is " + eh);
}
}
if (ps.getpInput().equals("Defend")) {
if (es.getEaod().equals("Defend")) {
System.out
.println("YOUR SHIELDS BOUNCE OFF EACHOTHERS... TRY AGAIN!");
System.exit(0);
}
}
if (es.getEaod().equals("Attack")) {
if (es.getEnemyRoll() > ps.getPlayerRoll())
ph -= es.getEnemyRoll() - ps.getPlayerRoll();
System.out.println("Your Health is " + ph);
}
}
}
package test;
import java.util.Random;
import java.util.Scanner;
public class PlayerStats {
static Scanner paod = new Scanner(System.in);
//Players initial health value.
private int playerHealth = 10;
//RNG for attack value / defence value using dice as object.
private int playerRoll = new Random().nextInt(6) + 1;
private String pInput;
//Method for selecting Attack or Defence.
public void PlayerAttackDefend() {
System.out.println("Do you want to Attack or Defend?");
System.out.println("a = Attack / d = Defend");
//Player selects attack or defend.
String userInput = paod.nextLine();
if (userInput.equals("a")) {
pInput = "Attack";
}
if (userInput.equals("d")) {
pInput = "Defend";
}
}
public static Scanner getPaod() {
return paod;
}
public int getPlayerHealth() {
return playerHealth;
}
public int getPlayerRoll() {
return playerRoll;
}
public String getpInput() {
return pInput;
}
public static void setPaod(Scanner paod) {
PlayerStats.paod = paod;
}
public void setPlayerHealth(int playerHealth) {
this.playerHealth = playerHealth;
}
public void setPlayerRoll(int playerRoll) {
this.playerRoll = playerRoll;
}
public void setpInput(String pInput) {
this.pInput = pInput;
}
}
package test;
import java.util.Random;
public class EnemyStats {
//Enemy initial health value.
private int enemyHealth = 10;
//RNG for attack value / defence value using dice as object.
private static int enemyRoll = new Random().nextInt(6) + 1;
//RNG for enemy decision to Attack or Defend.
private static int eAttackDefend = new Random().nextInt(2) + 1;
//Used for returning attack or defend string.
private static String eaod;
//Attack or Defend method.
public void AttackDefend() {
if (eAttackDefend == 1) {
eaod = "Attack";
} else {
eaod = "Defend";
}
}
public int getEnemyHealth() {
return enemyHealth;
}
public int getEnemyRoll() {
return enemyRoll;
}
public int geteAttackDefend() {
return eAttackDefend;
}
public String getEaod() {
return eaod;
}
public void setEnemyHealth(int enemyHealth) {
this.enemyHealth = enemyHealth;
}
public void setEnemyRoll(int enemyRoll) {
EnemyStats.enemyRoll = enemyRoll;
}
public void seteAttackDefend(int eAttackDefend) {
EnemyStats.eAttackDefend = eAttackDefend;
}
public void setEaod(String eaod) {
EnemyStats.eaod = eaod;
}
}
An easy way would to be to set maxHp and actualHp values, if you want to be able to "heal".
If you just decrease until one is dead, you can just decrease the actual health variable you already have.
You might wanna take a look at Inheritance in general, as you have a lot of duplicate code.
In general, just make a loop
while(ps.getHealth() > 0 && es.getHealth() > 0) {
// your battle code
}
you might want to remove the System.exit(0) calls, as they terminate the program.
Add to the player/enemy a dealDamage(int damage) method to actually be able to reduce their health
The health values should be in the objects, and you should not need to store them in your BattleClass.
I could give you the short answer but I guess you get more out of a detailed explanation :-)
You want to run your code "until either player health or enemy health reached 0" so you need a loop.
In java you have 3 kinds of loops:
The for loop
for(int i=1;i<=3;i++) System.out.println("Hello Musketeer Nr. "+i);
The most elaborate loop, the for loop consists of three parts, the initialization, the condition, and the afterthought. While the for loop can be used differently, it is mostly is used in the fashion shown here, that is, you have a counter variable whose value you need somehow.
If you don't need the counter variable value, you can use the short form with collections and arrays:
for(Person p: persons) System.out.println("Hello, "+person.getName()+"!");
The while loop
The second most commonly used (at least by me) loop, it has an initial condition and iterates, as long as it is true.
while(ph>0&&eh>0)
{
...
}
As you see, it fits your problem very well. For completeness, I will however describe the third loop which is the
do-while loop
do
{
...
}
while(ph>0&&eh>0)
You use this loop like the while loop but if you want to have at least one run through.
Other Remarks
Why have two classes PlayerStats and EnemyStats in combat system (they both seem to have the same actions and values) ? You could just have:
Stats playerStats=new Stats();
Stats enemyStats=new Stats();

Math.random called from for loop produces continous "random" numbers

im pretty new to java stuff. At the moment i am trying to write a programm dealing with the birthday problem(wikipedia). I want to know how many people have to be asked for their day and month of birth until one is duplicate.
I wrote a class doing the "asking" with the following code:
public class Starter {
static ArrayList<Integer> peeps = new ArrayList<Integer>();
static boolean match = false;
static int counter = 0;
public static int doRand() {
int rand = (1 + (int) (Math.random() * ((365 - 1) + 1)));
return rand;
}
public static int start() {
do {
int buffer = 0;
buffer = doRand();
if (peeps.isEmpty()) {
peeps.add(doRand());
}
counter++;
for (int i = 0; i < peeps.size(); i++) {
if (peeps.get(i) == buffer) {
match = true;
}
}
peeps.add(buffer);
} while (match == false);
return counter;
}
}
This seems to work and produces numbers somewhat between 10 and 50.
But if I run this function from the following for-loop, I get really strange result:
public class BirtdayProblem {
public static void main(String[] args) {
for (int i=0;i< 1000;i++) {
System.out.println(Starter.start());
}
}
}
It produces an output of 1000 continous numbers...why?
If I run the function multiple times manually, i have never gotten any continous number...
Can someone explain that to me?
Example Output:
25
26
27
...
...
1016
1017
1018
1019
1020
1021
1022
1023
1024
Does not look ver yRandom to me...?
Starter.start() returns the static "counter" value which is incremented by 1 after every iteration in the for loop , hence the output shows the output in increments of 1 .
You are using static member variables for counter and match. That means they belong to the class and will not be reset between calls to start().
Since these variables are used only inside the start() method I suggest you put their declarations there as well.
public static int start() {
boolean match = false;
int counter = 0;
And remove the old declarations at the top.

Making change recursively: How do I modify my algorithm to print all combinations?

I have an algorithm that recursively makes change in the following manner:
public static int makeChange(int amount, int currentCoin) {
//if amount = zero, we are at the bottom of a successful recursion
if (amount == 0){
//return 1 to add this successful solution
return 1;
//check to see if we went too far
}else if(amount < 0){
//don't count this try if we went too far
return 0;
//if we have exhausted our list of coin values
}else if(currentCoin < 0){
return 0;
}else{
int firstWay = makeChange(amount, currentCoin-1);
int secondWay = makeChange(amount - availableCoins[currentCoin], currentCoin);
return firstWay + secondWay;
}
}
However, I'd like to add the capability to store or print each combination as they successfully return. I'm having a bit of a hard time wrapping my head around how to do this. The original algorithm was pretty easy, but now I am frustrated. Any suggestions?
CB
Without getting into the specifics of your code, one pattern is to carry a mutable container for your results in the arguments
public static int makeChange(int amount, int currentCoin, List<Integer>results) {
// ....
if (valid_result) {
results.add(result);
makeChange(...);
}
// ....
}
And call the function like this
List<Integer> results = new LinkedList<Integer>();
makeChange(amount, currentCoin, results);
// after makeChange has executed your results are saved in the variable "results"
I don't understand logic or purpose of above code but this is how you can have each combination stored and then printed.
public class MakeChange {
private static int[] availableCoins = {
1, 2, 5, 10, 20, 25, 50, 100 };
public static void main(String[] args) {
Collection<CombinationResult> results = makeChange(5, 7);
for (CombinationResult r : results) {
System.out.println(
"firstWay=" + r.getFirstWay() + " : secondWay="
+ r.getSecondWay() + " --- Sum=" + r.getSum());
}
}
public static class CombinationResult {
int firstWay;
int secondWay;
CombinationResult(int firstWay, int secondWay) {
this.firstWay = firstWay;
this.secondWay = secondWay;
}
public int getFirstWay() {
return this.firstWay;
}
public int getSecondWay() {
return this.secondWay;
}
public int getSum() {
return this.firstWay + this.secondWay;
}
public boolean equals(Object o) {
boolean flag = false;
if (o instanceof CombinationResult) {
CombinationResult r = (CombinationResult) o;
flag = this.firstWay == r.firstWay
&& this.secondWay == r.secondWay;
}
return flag;
}
public int hashCode() {
return this.firstWay + this.secondWay;
}
}
public static Collection<CombinationResult> makeChange(
int amount, int currentCoin) {
Collection<CombinationResult> results =
new ArrayList<CombinationResult>();
makeChange(amount, currentCoin, results);
return results;
}
public static int makeChange(int amount, int currentCoin,
Collection<CombinationResult> results) {
// if amount = zero, we are at the bottom of a successful recursion
if (amount == 0) {
// return 1 to add this successful solution
return 1;
// check to see if we went too far
} else if (amount < 0) {
// don't count this try if we went too far
return 0;
// if we have exhausted our list of coin values
} else if (currentCoin < 0) {
return 0;
} else {
int firstWay = makeChange(
amount, currentCoin - 1, results);
int secondWay = makeChange(
amount - availableCoins[currentCoin],
currentCoin, results);
CombinationResult resultEntry = new CombinationResult(
firstWay, secondWay);
results.add(resultEntry);
return firstWay + secondWay;
}
}
}
I used the following:
/**
* This is a recursive method that calculates and displays the combinations of the coins included in
* coinAmounts that sum to amountToBeChanged.
*
* #param coinsUsed is a list of each coin used so far in the total. If this branch is successful, we will add another coin on it.
* #param largestCoinUsed is used in the recursion to indicate at which coin we should start trying to add additional ones.
* #param amountSoFar is used in the recursion to indicate what sum we are currently at.
* #param amountToChange is the original amount that we are making change for.
* #return the number of successful attempts that this branch has calculated.
*/private static int change(List<Integer> coinsUsed, Integer currentCoin, Integer amountSoFar, Integer amountToChange)
{
//if last added coin took us to the correct sum, we have a winner!
if (amountSoFar == amountToChange)
{
//output
System.out.print("Change for "+amountToChange+" = ");
//run through the list of coins that we have and display each.
for(Integer count: coinsUsed){
System.out.print(count + " ");
}
System.out.println();
//pass this back to be tallied
return 1;
}
/*
* Check to see if we overshot the amountToBeChanged
*/
if (amountSoFar > amountToChange)
{
//this branch was unsuccessful
return 0;
}
//this holds the sum of the branches that we send below it
int successes=0;
// Pass through each coin to be used
for (Integer coin:coinAmounts)
{
//we only want to work on currentCoin and the coins after it
if (coin >= currentCoin)
{
//copy the list so we can branch from it
List<Integer> copyOfCoinsUsed = new ArrayList<Integer>(coinsUsed);
//add on one of our current coins
copyOfCoinsUsed.add(coin);
//branch and then collect successful attempts
successes += change(copyOfCoinsUsed, coin, amountSoFar + coin, amountToChange);
}
}
//pass back the current
return successes;
}

Categories

Resources