Breadth-First Search with obstacles - javafx

I'm currently making a game as a school project and I'm trying to figure out the pathfinding of enemies. I've made a basic BFS which works pretty well but does not take in account obstacles, so enemies are stuck by an obstacle is there's one when trying to reach the player. I've tried different things but all I got was null pointer (which I kind of understand, but I don't know how to make this works).
public class BFS {
private Player player;
private Field field;
private Queue<Tile> queue;
private HashMap<Tile, Tile> parents;
private ArrayList<Tile> adjTiles;
public BFS(Player player, Field field) {
this.player = player;
this.field = field;
this.queue = new LinkedList<>();
this.parents = new HashMap<Tile, Tile>();
this.adjTiles = new ArrayList<>();
}
public void lancerBFS() {
int x = player.getIndiceX();
int y = player.getIndiceY();
Tile player = field.getNextTile(y, x);
this.parents.clear();
this.queue.clear();
this.adjTiles.clear();
this.queue.add(field.getNextTile(y, x));
this.parents.put(field.getNextTile(y, x), field.getNextTile(y, x));
while (!queue.isEmpty()) {
Tile temp = queue.remove();
y = temp.getI();
x = temp.getJ();
if (x > 0) {
this.adjTiles.add(field.getNextTile(y, x-1));
}
if (y > 0) {
this.adjTiles.add(field.getNextTile(y-1, x));
}
if (x < 24) {
this.adjTiles.add(field.getNextTile(y, x+1));
}
if (y < 24) {
this.adjTiles.add(field.getNextTile(y+1, x));
}
for (int i = 0 ; i < adjTiles.size() ; i++) {
if (!this.parents.containsKey(adjTiles.get(i))) {
this.parents.put(this.adjTiles.get(i), temp);
this.queue.add(this.adjTiles.get(i));
}
}
this.adjTiles.clear();
}
}
public Tile searchWay(AnimatedEntity entity) {
int x = entity.getIndiceX();
int y = entity.getIndiceY();
Tile t = this.field.getNextTile(y, x);
return this.parents.get(t);
}
public HashMap<Tile, Tile> getParents() {
return parents;
}
}
How I use it (my tiles are 32x32 on a 25x25 map, and enemies move 4 pixels by 4 pixels)
public void moveEnemy(AnimatedEntity e) {
Tile nextTile = this.bfs.searchWay(e);
Tile enemyAt = this.map.getNextTile(e.getIndiceY(), e.getIndiceX());
if (nextTile.getI() == enemyAt.getI() && nextTile.getJ() < enemyAt.getJ()) {
e.moveLeft(entities, inanimatedEntities);
}
if (nextTile.getI() < enemyAt.getI() && nextTile.getJ() == enemyAt.getJ()) {
e.moveUp(entities, inanimatedEntities);
}
if (nextTile.getI() == enemyAt.getI() && nextTile.getJ() > enemyAt.getJ()) {
e.moveRight(entities, inanimatedEntities);
}
if (nextTile.getI() > enemyAt.getI() && nextTile.getJ() == enemyAt.getJ()) {
e.moveDown(entities, inanimatedEntities);
}
}
How enemies get stuck in game:
How enemies get stuck after trying to include isObstacle notion

Related

Bukkit/Spigot - Projectile locations on hit detection completely wrong

I am making a custom 'gun' plugin for a minecraft server. My problem is that when attempting to detect where a projectile has landed, the locational difference between the projectile and the player being hit is too large to be detected by my headshot method. The only reason I am using a projectile trace for 'isHeadshot' is due to debugging trials.
This is my shoot method
public void shootGun(Player p) {
if (getFirearmAction().isDelayed(p))
return;
double shiftYaw = (p.getLocation().getYaw() + 180) * (Math.PI/180);
Vector shiftVec = new Vector(Math.cos(shiftYaw), 0.0D, Math.sin(shiftYaw)); //TODO: add bullet_spread
for (int i = 0; i < projectileInfo.getAmount(); i++) {
Projectile proj = (Projectile)p.getWorld().spawn(p.getEyeLocation().toVector().add(shiftVec.multiply(0.2D)).toLocation(p.getWorld()), getProjectileInfo().getProjectileClass());
proj.setVelocity(UtilMethods.getBulletVelocity(p).multiply(projectileInfo.getSpeed()));
proj.setShooter(p);
}
projectileInfo.playShootGunSound(p);
getFirearmAction().performAction(p);
}
This is the listener for a 'hit'
#EventHandler
public void onEntDamage(EntityDamageByEntityEvent event) {
if (event.getDamager() instanceof Projectile) {
Projectile p = (Projectile)event.getDamager();
if (p.getShooter() instanceof Player) {
Player player = (Player)p.getShooter();
Gun gun = UtilMethods.getGun(player);
if (gun != null) {
int damage = gun.getProjectileInfo().getDamage();
if (event.getEntity() instanceof Player) {
Player ent = (Player)event.getEntity();
if (UtilMethods.isHeadShot(ent, p))
damage *= 2;
}
event.setDamage(damage);
}
}
}
}
And finally, this is [isHeadshot, isInCuboid, and bulletVelocity] methods. The first two are substitute methods for trying to figure out a failed headshot detection... The getBulletVelocity method sets the correct velocity and direction of the projectile. (In this case I am working with Snowball.class)
public static boolean isHeadShot(Player victim, Projectile projectile) {
Location locA = new Location(victim.getWorld(), victim.getEyeLocation().getX() -0.5, victim.getEyeLocation().getY() - 0.5, victim.getEyeLocation().getZ() - 0.5);
Location locB = new Location(victim.getWorld(), victim.getEyeLocation().getX() +0.5, victim.getEyeLocation().getY() + 0.5, victim.getEyeLocation().getZ() + 0.5);
for (double i = 0; i < 256; i+=0.8D) {
System.out.println(projectile.getLocation() + " | " + victim.getLocation());
projectile.getLocation().add(projectile.getVelocity().normalize().multiply(i));
if (isInCuboid(locA, locB, projectile.getLocation())) {
System.out.println(i);
return true;
}
}
return false;
}
public static boolean isInCuboid(Location min, Location max, Location varying) {
double[] locs = new double[2];
locs[0] = min.getX();
locs[1] = max.getX();
Arrays.sort(locs);
if (varying.getX() > locs[1] || varying.getX() < locs[0])
return false;
locs[0] = min.getY();
locs[1] = max.getY();
Arrays.sort(locs);
if (varying.getY() > locs[1] || varying.getY() < locs[0])
return false;
locs[0] = min.getZ();
locs[1] = max.getZ();
Arrays.sort(locs);
if (varying.getZ() > locs[1] || varying.getZ() < locs[0])
return false;
return true;
}
public static Vector getBulletVelocity(Player shooter) {
double yaw = Math.toRadians((-shooter.getLocation().getYaw() - 90.0f));
double pitch = Math.toRadians(-shooter.getLocation().getPitch());
double x = Math.cos(pitch) * Math.cos(yaw);
double y = Math.sin(pitch);
double z = -Math.sin(yaw) * Math.cos(pitch);
Vector dirVec = new Vector(x, y, z).normalize();
return dirVec;
}
I would like some help since it seems that when the bullet causes damage, the bullet is already through the player's hitbox and can not be detected as a headshot anylonger. Any advice?
This is the locational difference. First location is projectile, second location is victim. However, for there to be a hit, the bullet must pass through the player at one point..
[08:53:22] [Server thread/INFO]: Location{world=CraftWorld{name=San_Andreas},x=2501.8249706725665,y=73.62000000476837,z=1681.0750064188326,pitch=0.0,yaw=0.0} | Location{world=CraftWorld{name=San_Andreas},x=2508.7144181513295,y=72.0,z=1671.9424013003206,pitch=0.3,yaw=-8.100003}
Listen for the ProjectileHitEvent and check if the projectile's y-coord is within a certain distance of the y-coord of the hit player's eye location (the x and z coords are irrelevant for determining a headshot on a player).

In Javafx how to set the size cells of a gridpane a fraction of the parent pane?

I try to create a gridPane in JavaFx with a circle in it.I want the gridPane cells to use all the available space in the gridPane.(The GridPane is in the Center of a BorderPane) but the cells keep resizing to the dimensions of the inner objects.How do I get the cells to use all space available? (and how do I set the radius of the circle to a fraction of the space available in the Center of the BorderPane.
I am quite new to JavaFx but I tried to use Columnconstraints and RowConstraints to match my need. It didn't work.I tried also to bind the size of my objects in the GridPane to use a fraction of the stage size but it does not work properly as it does not correspond to the plane in the BorderPane.
public void start(Stage primaryStage) throws Exception{
BorderPane applicationLayout = new BorderPane();
primaryStage.setTitle("Multi-level feedback simulator");
Scene scene = new Scene(applicationLayout, 600, 600);
primaryStage.setScene(scene);
//Add the menu Bar
//MainMenuBar menuBar = new MainMenuBar(primaryStage);
//applicationLayout.setTop(menuBar);
//Add the main zone of drawing
TreeDrawingZone treeDrawingZone = new TreeDrawingZone(primaryStage,applicationLayout,3,3);
applicationLayout.setCenter(treeDrawingZone);
primaryStage.show();
primaryStage.setMaximized(true);
}
The GridPane code with the constraints.
The biggest part of the constructor creates lines dans circles to display a tree.
The drawings functions are createLine() and createCircle()
public class TreeDrawingZone extends Parent {
private GridPane drawingZoneLayout;
private Stage stage;
private int columnNumber;
private int rowNumber;
private Pane rootPane;
private List<Pair<Integer,Integer>> circlePositions;
public TreeDrawingZone(Stage stage,Pane rootPane, int treeHeight, int childrenPerNode){
this.stage = stage;
drawingZoneLayout = new GridPane();
columnNumber = 2*(int)Math.pow(childrenPerNode,treeHeight-1)-1;
rowNumber = 2*treeHeight-1;
circlePositions = new ArrayList<>();
this.rootPane = rootPane;
//TODO Use the correct height of the borderLayout (maybe with a upper level layout)
System.out.println(columnNumber);
System.out.println(rowNumber);
//column Constraints
for(int i = 1 ; i <= columnNumber ; i++){
ColumnConstraints columnConstraints = new ColumnConstraints();
columnConstraints.setPercentWidth((double) 100/columnNumber);
columnConstraints.setFillWidth(true);
drawingZoneLayout.getColumnConstraints().add(columnConstraints);
}
//row Constraints
for(int i = 1 ; i <= rowNumber ; i++){
RowConstraints rowConstraints = new RowConstraints();
rowConstraints.setPercentHeight((double) 100/rowNumber);
rowConstraints.setFillHeight(true);
drawingZoneLayout.getRowConstraints().add(rowConstraints);
}
//Tree Representation
//Base Line
List<Integer> circleLineRepartition = new ArrayList<>();
for(int i = 0 ; i < columnNumber; i ++){
if(i % 2 == 0){
circleLineRepartition.add(i);
}
}
System.out.println(circleLineRepartition);
//Creation of the grid line per line
for(int i = rowNumber-1 ; i >=0 ; i-=2){
if(i % 2 == 0) {
//Case of the line with circles
for (Integer circlePosition : circleLineRepartition) {
Pane circlePane;
if (i == 0) {
circlePane = createCircle(true, false);
} else if (i == rowNumber - 1) {
circlePane = createCircle(false, true);
} else {
circlePane = createCircle();
}
drawingZoneLayout.add(circlePane, circlePosition, i);
circlePositions.add(new Pair<>(circlePosition, i));
}
List<Integer> upperCircleLineRepartition;
//Create the lines
//The following block enumerates the different cases to create the lines between the dotes
try {
upperCircleLineRepartition = getoddlyRepartedCenters(childrenPerNode, circleLineRepartition);
if (i > 0) {
int minPosition = circleLineRepartition.get(0);
int maxPosition = circleLineRepartition.get(circleLineRepartition.size() - 1);
int position = 0;
boolean drawHorizontal = true;
int linkedNodeCount = 0;
for (int j = minPosition; j <= maxPosition; j++) {
Pane linesPane;
if (j == circleLineRepartition.get(position) && minPosition != maxPosition) {
//Update the number of linked Nodes
if(drawHorizontal) {
linkedNodeCount += 1;
if(linkedNodeCount == childrenPerNode)
drawHorizontal = false;
}else{
linkedNodeCount = 1;
drawHorizontal = true;
}
//First element
if (linkedNodeCount == 1) {
if(upperCircleLineRepartition.contains(j)){
linesPane = createLines(LineDirection.NORTH,LineDirection.SOUTH,LineDirection.EAST);
}else {
linesPane = createLines(LineDirection.SOUTH, LineDirection.EAST);
}
}
//Last element
else if (linkedNodeCount == childrenPerNode) {
if(upperCircleLineRepartition.contains(j)){
linesPane = createLines(LineDirection.NORTH,LineDirection.SOUTH,LineDirection.WEST);
}else {
linesPane = createLines(LineDirection.WEST, LineDirection.SOUTH);
}
}//bridge with under and upper level
else if(upperCircleLineRepartition.contains(j)) {
linesPane = createLines(LineDirection.SOUTH, LineDirection.NORTH, LineDirection.EAST, LineDirection.WEST);
}
//other children
else{
linesPane = createLines(LineDirection.SOUTH, LineDirection.EAST, LineDirection.WEST);
}
position++;
}
//Only one child
else if (minPosition == maxPosition) {
linesPane = createLines(LineDirection.SOUTH, LineDirection.NORTH);
}
//Bridge between children
else {
if(drawHorizontal) {
if (upperCircleLineRepartition.contains(j)) {
linesPane = createLines(LineDirection.NORTH, LineDirection.EAST, LineDirection.WEST);
} else {
linesPane = createLines(LineDirection.WEST, LineDirection.EAST);
}
}else{
linesPane = createLines();
}
}
drawingZoneLayout.add(linesPane, j, i - 1);
}
}
circleLineRepartition = new ArrayList<>(upperCircleLineRepartition);
} catch (Exception e) {
System.out.println("Invalid line given");
}
}
}
drawingZoneLayout.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE);
//TODO remove GridLines after debug
drawingZoneLayout.setGridLinesVisible(true);
this.getChildren().add(drawingZoneLayout);
}
private Pane createCircle(){
return createCircle(false,false);
}
private Pane createCircle(boolean isRoot, boolean isLeaf){
Pane circlePane = new Pane();
Circle circle = new Circle();
circle.centerXProperty().bind(stage.widthProperty().divide(columnNumber).divide(2));
circle.centerYProperty().bind(stage.heightProperty().divide(rowNumber).divide(2));
circle.radiusProperty().bind(Bindings.min(stage.widthProperty().divide(columnNumber).divide(2),stage.heightProperty().divide(rowNumber).divide(2)));
circlePane.getChildren().add(circle);
if(!isLeaf) {
circlePane.getChildren().add(createLines(LineDirection.SOUTH));
}
if(!isRoot){
circlePane.getChildren().add(createLines(LineDirection.NORTH));
}
return circlePane;
}
private Pane createLines(LineDirection ... directions){
Pane linesGroup = new Pane();
for(LineDirection direction : directions){
linesGroup.getChildren().add(createLine(direction));
}
return linesGroup;
}
private Line createLine(LineDirection direction){
Line line = new Line();
if(direction == LineDirection.EAST || direction == LineDirection.WEST){
line.startYProperty().bind(stage.heightProperty().divide(rowNumber).divide(2));
line.endYProperty().bind(stage.heightProperty().divide(rowNumber).divide(2));
line.startXProperty().bind(stage.widthProperty().divide(columnNumber).divide(2));
if(direction == LineDirection.EAST){
line.endXProperty().bind(stage.widthProperty().divide(columnNumber));
}
else{
line.setEndX(0);
}
}
else{
line.startXProperty().bind(stage.widthProperty().divide(columnNumber).divide(2));
line.endXProperty().bind(stage.widthProperty().divide(columnNumber).divide(2));
line.startYProperty().bind(stage.heightProperty().divide(rowNumber).divide(2));
if(direction == LineDirection.NORTH){
line.setEndY(0);
}else{
line.endYProperty().bind(stage.heightProperty().divide(rowNumber));
}
}
line.setStrokeWidth(1);
line.setFill(null);
line.setStroke(Color.BLACK);
return line;
}
private int getCenter(List<Integer> childrenNodesPosition) throws Exception {
if (childrenNodesPosition.size() == 0){
throw new Exception("Tried to get the center of an empty list");
}else{
int sum = 0;
for(int childNodePosition : childrenNodesPosition){
sum += childNodePosition;
}
return sum/childrenNodesPosition.size();
}
}
private List<Integer> getoddlyRepartedCenters(int nodeNumberPerParent, List<Integer> childrenNodesPosition) throws Exception {
int parentNumber = childrenNodesPosition.size()/nodeNumberPerParent;
int nextPosition = 0;
List<Integer> regularParentCenters = new ArrayList<>(parentNumber);
for(int i = 0 ; i < parentNumber ; i++){
regularParentCenters.add(getCenter(childrenNodesPosition.subList(nextPosition,nextPosition + nodeNumberPerParent)));
nextPosition = nextPosition + nodeNumberPerParent;
}
return regularParentCenters;
}
}
The result that I want to correct

Binary coded GA with NSGA-II in R

I have a multiobjective minimization function. I want to use NSGA-II in R. There are packages for this: nsga2R and mco. But these packages do not support binary coded chromosomes. In my fitness function I need binary chromosomes to achive best solution because of my problem's structure. Is there any way to use binary coded chromosome in nsga2 (or maybe with different algorithm) for R? Thanks.
I got the same problem so I decided to fix it on my own. But no guarentee if it's the right way.
The following part is for the package 'mco'
I copied parts out of the offical nsga2 implementation into the 'mco' package.
This workaround is only for binary (0-1) variables.
1. In /src/nsga2.c rewrite the functions as follows:
static void mutate_ind (nsga2_ctx *ctx, individual *ind) {
int j;
double prob;
GetRNGstate();
for (j = 0; j < ctx->input_dim; j++)
{
//for (k=0; k < ctx[j]->input_dim; k++)
//{
//prob = randomperc();
prob = unif_rand();
if (prob <= ctx->mutation_probability) {
if (ind->input[j] == 0)
{
ind->input[j] = 1;
}
else
{
ind->input[j] = 0;
}
ctx->input_mutations+=1;
}
//}
}
PutRNGstate();
then
static void crossover (nsga2_ctx *ctx,
individual *parent1, individual *parent2,
individual *child1, individual *child2) {
int i;
int nbits=1;
double rand;
int temp, site1, site2, temp2, temp3;
GetRNGstate();
rand=unif_rand();
if (rand <= ctx->crossing_probability)
{
ctx->input_crossings++;
//site1 = rnd(0,ctx->input_dim);
//site2 = rnd(0,ctx->input_dim);
if(unif_rand()<=0.5){
temp2=0;
}else{
temp2=1;
}
if(unif_rand()<=0.5){
temp3=0;
}else{
temp3=1;
}
site1=temp2;
site2=temp3;
if (site1 > site2)
{
temp = site1;
site1 = site2;
site2 = temp;
}
for (i=0; i<site1; i++)
{
child1->input[i] = parent1->input[i];
child2->input[i] = parent2->input[i];
}
for (i=site1; i<site2; i++)
{
child1->input[i] = parent2->input[i];
child2->input[i] = parent1->input[i];
}
for (i=site2; i<nbits; i++)
{
child1->input[i] = parent1->input[i];
child2->input[i] = parent2->input[i];
}
}
else
{
for (i=0; i<nbits; i++)
{
child1->input[i] = parent1->input[i];
child2->input[i] = parent2->input[i];
}
}
PutRNGstate();
}
and
static void population_initialize(nsga2_ctx *ctx, population *pop) {
GetRNGstate();
int i, j;
for (i = 0; i < pop->size; ++i) {
for (j=0; j<ctx->input_dim; ++j) {
/* Generate random value between lower and upper bound */
//double delta = ctx->upper_input_bound[j] - ctx->lower_input_bound[j];
//pop->ind[i].input[j] = ctx->lower_input_bound[j] + delta*unif_rand();
if(unif_rand() <= 0.5){
pop->ind[i].input[j] = 0;
}
else{
pop->ind[i].input[j] = 1;
}
}
}
PutRNGstate();
}
2. define the function randomperc() as follows
double seed;
double oldrand[55];
int jrand;
/* Create next batch of 55 random numbers */
void advance_random ()
{
int j1;
double new_random;
for(j1=0; j1<24; j1++)
{
new_random = oldrand[j1]-oldrand[j1+31];
if(new_random<0.0)
{
new_random = new_random+1.0;
}
oldrand[j1] = new_random;
}
for(j1=24; j1<55; j1++)
{
new_random = oldrand[j1]-oldrand[j1-24];
if(new_random<0.0)
{
new_random = new_random+1.0;
}
oldrand[j1] = new_random;
}
}
/* Fetch a single random number between 0.0 and 1.0 */
double randomperc()
{
jrand++;
if(jrand>=55)
{
jrand = 1;
advance_random();
}
return((double)oldrand[jrand]);
}
3. replace every unif_rand() with randomperc() in 'nsga2.c'
4. build the package in R

Heapsort Error during runtime

Here is a heapsort program I've created in Java, but I'm having an issue where it won't run.
I'm not getting any errors during compilation, which made the error hard to identify, but if I comment out the size decrement in my extract maximum function the program will run, so I assume that's where the error is. Unfortunately, that line is crucial to the program functioning properly.
If there's anything simple causing this problem, or if major adjustments need to be made to the program, I'd like to know either way.
All input is welcome.
Update
added main function.
Code can now be copy-and-pasted to run.
public class Heap
{
private int [] data;
private int [] fin;
private int size;
private int tmp = 0;
/**
* Constructor for objects of class Heap
*/
public Heap(int[] A)
{
data = A;
size = data.length;
fin = new int [size];
this.buildHeap(0);
for(int n = size - 1; n >= 0; n--)
{
fin[n] = this.extractMax();
}
}
public int getSize()
{
return size;
}
private void setSize(int i)
{
size = i;
}
public void print()
{
for(int i = 0; i < this.getSize(); i++)
System.out.printf("%d\n", fin[i]);
}
/**
* build heap using top down method
*
* #param i the index of the node being built upon
*/
private void buildHeap(int i)
{
if(i <= (size - 2)/2)
{
buildHeap(2*i + 1);
buildHeap(2*i + 2);
heapify(i);
}
}
/**
* Extract maximum number
*
* #return maximum number of heap
*/
private int extractMax()
{
int n = size;
int store = 0;
store = data[0];
data[0] = data[n - 1];
size--;
this.heapify(0);
return store;
}
/**
* Heapify array
*
* #param i the index to heapify upon
*/
private void heapify(int i)
{
if(2*i + 1 < size && data[2*i + 1] > data[i])
{
if(2*i + 2 < size && data[2*i + 2] > data[2*i + 1])
{
this.exchange(i, 2*i + 2);
heapify(2*i + 2);
}
else
{
this.exchange(i, 2*i + 1);
heapify(2*i + 1);
}
}
if(2*i + 2 < size && data[2*i + 2] > data[i])
{
this.exchange(i, 2*i + 2);
heapify(2*i + 2);
}
}
private boolean exchange(int i, int k)
{
tmp = data[i];
data[i] = data[k];
data[k] = tmp;
return true;
}
public static void main(String [] args)
{
int [] arr = {5,13,2,25,7,17,20,8,4};
Heap heapsort = new Heap(arr);
heapsort.print();
}
}

Recursively searching a tree to get the binary coding for a character

Hi im trying to figure out how to recursively search a tree to find a character and the binary code to get to that character. basically the goal is to go find the code for the character and then write it to a file. the file writer part i can do no problem but the real problem is putting the binary code into a string. while im searching for the character. please help!
this is the code for the recursive method:
public String biNum(Frequency root, String temp, String letter)
{
//String temp = "";
boolean wentLeft = false;
if(root.getString() == null && !wentLeft)
{
if(root.left.getString() == null)
{
temp = temp + "0";
return biNum(root.left, temp, letter);
}
if(root.left.getString().equals(letter))
{
return temp = temp + "0";
}
else
{
wentLeft = true;
temp = temp.substring(0, temp.length() - 1);
return temp;
}
}
if(root.getString() == null && wentLeft)
{
if(root.right.getString() == null)
{
temp = temp + "1";
return (biNum(root.right, temp, letter));
}
if(root.right.getString().equals(letter))
{
return temp = temp + "1";
}
else
{
wentLeft = false;
temp = temp.substring(0, temp.length() - 1);
return temp;
}
}
return temp;
}
and this is the Frequency class:
package huffman;
public class Frequency implements Comparable {
private String s;
private int n;
public Frequency left;
public Frequency right;
private String biNum;
private String leaf;
Frequency(String s, int n, String biNum)
{
this.s = s;
this.n = n;
this.biNum = biNum;
}
public String getString()
{
return s;
}
public int getFreq()
{
return n;
}
public void setFreq(int n)
{
this.n = n;
}
public String getLeaf()
{
return leaf;
}
public void setLeaf()
{
this.leaf = "leaf";
}
#Override
public int compareTo(Object arg0) {
Frequency other = (Frequency)arg0;
return n < other.n ? -1 : (n == other.n ? 0 : 1);
}
}
In your updated version, I think you should re-examine return biNum(root.left, temp, letter);. Specifically, what happens if the root node of the entire tree has a left child which is not a leaf (and thus root.left.getString() == null) but the value you seek descends from the right child of the root node of the entire tree.
Consider this tree, for example:
26
/ \
/ \
/ \
11 15
/ \ / \
/ B A \
6 5 6 9
/ \ / \
D \ C sp
3 3 4 5
/ \
E F
2 1
and trace the steps your function will follow looking for the letter C.
Perhaps you should consider traversing the entire tree (and building up the pattern of 1s and 0s as you go) without looking for any specific letter but taking a particular action when you find a leaf node?

Resources