Shrinking the Code - java

I've got some java code that is used for my games NPCs to move arround.
Those are obviously in an 1d array.
public void route11() {
Scanner in = new Scanner(System.in);
Random number = new Random();
int random = number.nextInt(2);
if(random ==1)
hunters[1].x = hunters[1].x -1;
else
hunters[1].y = hunters[1].y -1;
}
public void Update() {
route11();
route2();
route3();
route4();
route5();
}
Methods route2, route3, ..., route5 look pretty much the same, the only thing that changes is the value of the array to correspond with a different hunter.
Could this code be "shrinked"? Im pretty sure my lecturer will be happy to minus my mark for such a messy and very much anti-OO code.
Also, all my collision/score code looks something like this, and it works for individual hunters:
if(hunters[i].x==0 && hunters[i].y == 0){
hunters[i].x = 11;
hunters[i].y = 11;
Player.score = Player.score + 1;
}

Your issue has nothing to do with OOP design. This is just about learning to use the tools available to write less redundant and more manageable code. If you utilize a for loop in your update and pass each individual hunter then this becomes much more condensed.
I will note that there are some unrelated OOP issues that you would do well to correct.
Hunter's members such as X and Y should not be exposed publicly, utilize getters/setters
The same goes for the Player's score member/field
public void update()
{
for(var i = 0; i < 5; i++)
{
route(hunters[i]);
collisionAndScoring(hunters[i]);
}
}
public void route(Hunter hunter)
{
Scanner in = new Scanner(System.in);
Random number = new Random();
int random = number.nextInt(2);
if(random == 1)
{
hunters.x--;
}
else
{
hunter.y--;
}
}
public void collisionAndScoring(Hunter hunter)
{
if (hunter.x == 0 && hunter.y == 0) //You should define constants for these to give them more meaning
{
hunter.x = 11; //another opportunity for a constant
hunter.y = 11; //another opportunity for a constant
Player.score++;
}
}

Related

Java: good programming approach?

I am being asked to learn Java very quickly and I am struggling with not only the verbose syntax but also the expected style and approach requirements.
Given a simple FizzBuzz challenge I produced the following code:
public class FizzBuzz {
public static void main(String[] args) {
boolean hit;
for (int n = 1; n <= 30; n++) {
hit = false;
if (n % 3 == 0) {
System.out.print("Fizz");
hit = true;
}
if (n % 5 == 0) {
System.out.print("Buzz");
hit = true;
}
if (hit != true) {
System.out.print(n);
}
System.out.println();
}
}
}
Asked to refactor this code by the lead programmer and to consider possible future requirements and code managability issues I gave it some thought and produced the following refactored code:
public class FizzBuzz {
public static void main(String[] args) {
boolean hit;
for (int n = 1; n < 30; n++) {
hit = false;
hit = (n % 3 == 0) ? writeAction("Fizz") : hit;
hit = (n % 5 == 0) ? writeAction("Buzz") : hit;
if ( ! hit)
System.out.print(n);
System.out.println();
}
}
private static boolean writeAction(String actionWord){
System.out.print(actionWord);
return true;
}
}
However, the guy who set this task has moved on quite quickly and I never got any feedback on this approach. Am I going in the right direction with this or have I regressed?. To me this should scale better and would be easier to modify. I have also considered that maybe he was expecting some sort of TDD approach? I am aware that I have no tests currently.
This site isn't for reviews, but in case your question gets moved, here is some feedback (from the "clean code" perspective):
your "main" code sits in a main() method. Makes re-using it very hard.
talking about re-use - various things in there prevent re-using it
you have some duplicated code in there
you are violating the single layer of abstraction principle
How I would write something along the lines of:
public class FizzBuzz {
private final OutputStream out;
public FizzBuzz(OutputStream out) {
this.out = out;
}
public void runFizzBuzzUpTo(int n) {
for (int i = 1; i < n; i++) {
if ( writeIfTrue(n % 3 == 0, "Fizz") ) {
continue;
}
if ( writeIfTrue(n % 5 == 0, "Buzz") ) {
continue;
}
out.println(n);
}
}
private boolean writeIfTrue(boolean toCheck, String word) {
if (toCheck) {
out.println(word);
}
return toCheck;
}
public static void main(String[] args) {
new FizzBuzz(System.out).runFizzBuzzUpto(30);
}
}
Things I changed:
made the output the "core" thing of a class
provided the possibility to run for arbitrary positive numbers
Stuff still missing:
"single layere of abstraction" is still not good
instead of fixing "30" in main() - one could check for exactly one argument passed to main() - which would then be used as parameter for runFizzBuzzUpTo()
Of course, the second code is more modular and easier to modify that way. I mostly don't prefer to write the if conditions in the short way...
The method writeAction could be void because you don't have to return anything.
But you have good ideas :)

Need Help sorting out nested for loops

I'm trying to make a trivia game for my English class that will randomly pick a question, but will not pick the same one twice. I currently have a prototype set up, but I can't figure out what is going wrong that is preventing it from actually printing the questions.
Here's the behemoth:
import java.io.*;
import java.util.*;
public class qpicker
{
public static void main (String args[])
{
int qs = 0;
boolean q1checker, q2checker, q3checker, q4checker, q5checker,
q6checker, q7checker, q8checker, q9checker, q10checker, q11checker,
q12checker,q13checker, q14checker, q15checker, q16checker, q17checker,
q18checker, q19checker, q20checker; //this disaster is where i declared my
q1checker = false; //booleans
q2checker = false;
q3checker = false;
q4checker = false;
q5checker = false;
q6checker = false;
q7checker = false;
q8checker = false;
q9checker = false;
q10checker = false;
q1checker = false;
q12checker = false;
q13checker = false;
q14checker = false;
q15checker = false;
q16checker = false;
q17checker = false;
q18checker = false;
q19checker = false;
q20checker = false; //here i tried to set all booleans to false,
//thinking maybe that was the issue
do
{
qs++;
Random random = new Random();
double rng = random.nextDouble();
double selecter = rng * 10;//makes the random number easier to read
if(rng <=.5)
{
if(q1checker = false)
{
System.out.println("Put first q in here");
q1checker = true;
break;
}
}
System.out.print("cheese");//code progress tracker
if(rng <=1 && rng >.5)//this is where the question would be pulled
{
if(q2checker = false)//this ensures questions aren't repeated
{
System.out.println("Put second q in here");//display quest.
q2checker = true;
break;
}
}
System.out.print("e");
if(rng <=1.5 && rng > 1)//question picked
{
if(q3checker = false)//ensures questions aren't repeated
{
System.out.println("Put third q in here");//display quest.
q3checker = true;
break;
}
}
System.out.print("y");
if(rng <=2 && rng > 1.5 )
{
if(q4checker = false)
{
System.out.println("Put fourth q in here");
q4checker = true;
break;
}
else if (q4checker = true)
{continue;}
System.out.print(" ");
}if(rng <=2.5 && rng > 2)
{
if(q5checker = false)
{
System.out.println("Put fifth q in here");
q5checker = true;
break;
}
}
System.out.print("good");
if(rng <=3 && rng > 2.5)
{
if(q6checker = false)
{
System.out.println("Put sixth q in here");
q6checker = true;
break;
}
}
System.out.print("ness");//spells out "cheesey goodness" 20 times
}while (qs < 20);//ensures all questions are printed (in final product)
}
}
static void shuffleArray(string[] ar)
{
//set the seed for the random variable
Random rnd = ThreadLocalRandom.current();
//go from the last element to the first one.
for (int i = ar.size()- 1; i > 0; i--)
{
//get a random number till the current position and simply swap elements
int index = rnd.nextInt(i + 1);
// Simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}
This way you shuffle the entire array and get the values in a random order but NO duplicate at all. Every single element changes position, so that no matter what element (position) you pick, you get a country from a random position. You can return the entire vector, the positions are random.
You could try this method, for shuffling your array and returning the entire array in random order since it mixes the elements.
From what I see you are trying to allow them to choose questions until they are exhausted, choosing randomly. You can do this easily with an ArrayList, where you pick randomly an index from the list to pull your question, remove the question from your list, so it is no longer available to choose from. Note that after you remove and use it from the list, the list will be smaller by 1
String[] questionArray = ["Question 1","Question 2","Question 3","Question 4","Question 5"];
ArrayList<String> questionList = Arrays.asList(questionArray);
//Get a random number within the range of 0..questionList.size()
int chosenIndex = 1; //Made up for simplicity
String chosen = questionList.remove(chosenIndex);
//Now that you have chosen a question, and it was removed from the list
//The list is one element smaller. Next time you get a random number
//make sure you use the range: 0..chosen.size()
System.out.println(chosen);
I believe this is what you are looking for.
You should use arrays.
Also remember that = is an assignment operator while == is comparation
This:
if(rng <=.5)
{
if(q1checker = false)
Is wrong, it should be:
if(rng <=.5)
{
if(q1checker == false)
Or better:
if(rng <=.5)
{
if(!q1checker)

Out of memory error or program unresponsive during multithreading JAVA

I am new to multi threading. Literally. And I am pretty new to Java overall. HOwever, I am making a simulation and the thread seem to be working well except I occasionally have the program become unresponsive and once it said out of memory error. I assume this is because I am creating too many threads? At the point it normally does this I have over 2000 threads running at the same time. I can adjust the code (i.e reduce the number of customers or increase time between ticks) to release the pressure on the system but I am wondering if there is something I could be doing to help ease the burden within each thread itself. I'm pretty sure it isn't a deadlock since the code runs fine if I do the above but run it for longer so the same amount of customers come through. I will show the relevant parts of the code and if more is required I am happy to put this up. Please I don't understand this very well, so some very simple and helpful explanations would be greatly appreciated, since if the comment is too complex I probably wont' know how to implement it.
This is the main class that creates the thread.
CheckoutFloor checkoutFloor = new CheckoutFloor();
checkoutFloor.addCheckoutOperators(checkoutOperators);
int tick = 0;
int customers = 0;
while (tick < simulationTime) {
for (int i = 0; i < 2; i++) {
Random rand = new Random();
int random = rand.nextInt(100) + 1;
if (random <= 50) {
customerRunnable customer = new customerRunnable(checkoutFloor);
Thread t = new Thread(customer);
t.start();
tick++;
}
else {
tick++;
}
Here is the runnable code:
public void run() {
try {
customer.addRandomShopTime();
while (customer.shopTime > 0) {
Thread.sleep(1);
customer.setShopTime();
}
CheckoutOperator checkoutOperator = checkoutFloor.weightedCheckoutDeterminator();
checkoutOperator.addCustomer(customer);
while (customer.checkoutTime > 0) {
Thread.sleep(1);
if (checkoutOperator.customerList.get(0) == customer) {
customer.setCheckoutTime();
}
}
checkoutOperator.removeCurrentCustomer();
} catch (InterruptedException e) {
}
And here are the relevant methods.
public synchronized void addCustomer(Customer newCustomer) {
customerList.add(newCustomer);
System.out.println("no. of customers" + counter);
counter++;
}
public synchronized CheckoutOperator weightedCheckoutDeterminator() {
int totalCustomers = 0;
int totalCustomersAdj = 0;
for (int i = 0; i < checkoutOpList.size(); i++) {
totalCustomers += getCheckoutOperator(i).getCustomerListLength();
}
if (totalCustomers == 0) {
return getCheckoutOperator(0);
} else {
totalCustomersAdj = (checkoutOpList.size() * totalCustomers) - totalCustomers;
int randomNumber = 0;
try {
randomNumber = new Random().nextInt(totalCustomersAdj) + 1;
} catch (IllegalArgumentException ex) {
return checkoutOpList.get(0);
}
for (int i = 0; i < checkoutOpList.size(); i++) {
int operatorCustLength = (getCheckoutOperator(i).getCustomerListLength());
if (randomNumber <= (totalCustomers - operatorCustLength)) {
return getCheckoutOperator(i);
} else {
randomNumber = randomNumber - (totalCustomers - operatorCustLength);
}
}
return checkoutOpList.get(0); //HOPEFULLY UNREACHABLE!!!
}
I'm just wondering if, due to my lack of knowledge, there is anything I am missing that woudl help the flow a bit more and help it run faster?
[edit: I should add that under normal conditions I would never have 2000 threads running and this is me pushing the system to the max. I suspect that this IS the problem and I guess I am asking if there is something else I am missing due to my lack of knowledge. I just don't like the idea that if someone changes the code to make it more intensive that it might crash.].

Finding an odd perfect number

I wrote these two methods to determine if a number is perfect. My prof wants me to combine them to find out if there is an odd perfect number. I know there isn't one(that is known), but I need to actually write the code to prove that.
The issue is with my main method. I tested the two test methods. I tried debugging and it gets stuck on the number 5, though I can't figure out why. Here is my code:
public class Lab6
{
public static void main (String[]args)
{
int testNum = 3;
while (testNum != sum_of_divisors(testNum) && testNum%2 != 2)
testNum++;
}
public static int sum_of_divisors(int numDiv)
{
int count = 1;
int totalDivisors = 0;
while (count < numDiv)
if (numDiv%count == 0)
{
totalDivisors = totalDivisors + count;
count++;
}
else
count++;
return totalDivisors;
}
public static boolean is_perfect(int numPerfect)
{
int count = 1;
int totalPerfect = 0;
while (totalPerfect < numPerfect)
{
totalPerfect = totalPerfect + count;
count++;
}
if (numPerfect == totalPerfect)
return true;
else
return false;
}
}
Make
testNum%2 != 2
as
testNum%2 != 0
testNum=3
while (testNum != sum_of_divisors(testNum) && testNum%2 != 2)
testNum++;
You may want to do 'testNum+=2' since you are concerned about only odd numbers and replace the testNum %2!=2 with testNum>0 or other stopping condition. Eventually your integers will overflow.
"My prof wants me to combine them to find out if there is an odd perfect number. I know there isn't one(that is known), but I need to actually write the code to prove that."
Do you mean between 3 & 2^32-1? It is not known that there are no odd perfect numbers.

Encoding codes in Java

Over the past couple of weeks I've read through the book Error Control Coding: Fundamentals and Applications in order to learn about BCH (Bose, Chaudhuri, Hocquenghem) Codes for an junior programming role at a telecoms company.
This book mostly covers the mathematics and theory behind the subject, but I'm struggling to implement some of the concepts; primarily getting the next n codewords.I have a GUI (implemented through NetBeans, so I won't post the code as the file is huge) that passes a code in order to get the next n numbers:
Generating these numbers is where I am having problems. If I could go through all of these within just the encoding method instead of looping through using the GUI my life would be ten times easier.
This has been driving me crazy for days now as it is easy enough to generate 0000000000 from the input, but I am lost as to where to go from there with my code. What do I then do to generate the next working number?
Any help with generating the above code would be appreciated.
(big edit...) Playing with the code a bit more this seems to work:
import java.util.ArrayList;
import java.util.List;
public class Main
{
public static void main(final String[] argv)
{
final int startValue;
final int iterations;
final List<String> list;
startValue = Integer.parseInt(argv[0]);
iterations = Integer.parseInt(argv[1]);
list = encodeAll(startValue, iterations);
System.out.println(list);
}
private static List<String> encodeAll(final int startValue, final int iterations)
{
final List<String> allEncodings;
allEncodings = new ArrayList<String>();
for(int i = 0; i < iterations; i++)
{
try
{
final int value;
final String str;
final String encoding;
value = i + startValue;
str = String.format("%06d", value);
encoding = encoding(str);
allEncodings.add(encoding);
}
catch(final BadNumberException ex)
{
// do nothing
}
}
return allEncodings;
}
public static String encoding(String str)
throws BadNumberException
{
final int[] digit;
final StringBuilder s;
digit = new int[10];
for(int i = 0; i < 6; i++)
{
digit[i] = Integer.parseInt(String.valueOf(str.charAt(i)));
}
digit[6] = ((4*digit[0])+(10*digit[1])+(9*digit[2])+(2*digit[3])+(digit[4])+(7*digit[5])) % 11;
digit[7] = ((7*digit[0])+(8*digit[1])+(7*digit[2])+(digit[3])+(9*digit[4])+(6*digit[5])) % 11;
digit[8] = ((9*digit[0])+(digit[1])+(7*digit[2])+(8*digit[3])+(7*digit[4])+(7*digit[5])) % 11;
digit[9] = ((digit[0])+(2*digit[1])+(9*digit[2])+(10*digit[3])+(4*digit[4])+(digit[5])) % 11;
// Insert Parity Checking method (Vandermonde Matrix)
s = new StringBuilder();
for(int i = 0; i < 9; i++)
{
s.append(Integer.toString(digit[i]));
}
if(digit[6] == 10 || digit[7] == 10 || digit[8] == 10 || digit[9] == 10)
{
throw new BadNumberException(str);
}
return (s.toString());
}
}
class BadNumberException
extends Exception
{
public BadNumberException(final String str)
{
super(str + " cannot be encoded");
}
}
I prefer throwing the exception rather than returning a special string. In this case I ignore the exception which normally I would say is bad practice, but for this case I think it is what you want.
Hard to tell, if I got your problem, but after reading your question several times, maybe that's what you're looking for:
public List<String> encodeAll() {
List<String> allEncodings = new ArrayList<String>();
for (int i = 0; i < 1000000 ; i++) {
String encoding = encoding(Integer.toString(i));
allEncodings.add(encoding);
}
return allEncodings;
}
There's one flaw in the solution, the toOctalString results are not 0-padded. If that's what you want, I suggest using String.format("<something>", i) in the encoding call.
Update
To use it in your current call, replace a call to encoding(String str) with call to this method. You'll receive an ordered List with all encodings.
I aasumed, you were only interested in octal values - my mistake, now I think you just forgot the encoding for value 000009 in you example and thus removed the irretating octal stuff.

Categories

Resources