I made an 'Oregon Trail' like game, it uses a 'game over' method to ask if the user wants to play again.
The main issue:
My teacher mentioned something vague about if the game looped enough times, we'd end up with a stackOverflow. That makes sense to me because the game continues to nest methods inside of each other the way I have it, adding to the stack each time a 'new game' method is called because the outer methods are still there waiting to complete.
I've boiled down an example of what I mean. Assuming there were pauses for user input and such, how am I supposed to make sure my memory utilization doesn't keep growing as I call methods inside other methods? I think the word for this is 'recursive', thus my title.
If anyone could recommend correct form for dealing with this, I'd be really grateful.
public class Testing
{
public static void main(String[] args) {
System.out.println("main method");
gameStart();
}
private static void gameStart()
{
System.out.println("some other method called");
gameOver();
}
private static void gameOver()
{
System.out.println("game over called"); //I would ask the user if they want to play again.
//keeping it concise to illustrate my point, instead of using an if statement
gameStart();//starting the cycle I'm concerned about. Assume the user indicated they would like to play again.
}
}
Recursion needs a condition where it will not continue calling.
Recursion is most commonly seen where a method calls itself, such as computing the fibonacci sequence, where
fib(n) == fib(n-1) + fib(n-2)
fib(0) is defined as 0, so you don't have to compute.
fib(1) is defined as 1, so you don't have to compute.
Every other number is computed by the fib() method calling itself twice, but it escapes making the recursive call for the two defined cases, where there is nothing to compute. In pseudo code
int fib(int n)
{
if (n == 0) return 0; // doesnt have to recursively call
if (n == 1) return 1; // same
return fib(n-1) + fib(n-2);
}
In your case, you have two methods that call each other, but you have no condition where the calls can escape from that.
A possibility would be that gameOver() only calls gameStart() when the game ends in a tie, something like
public class Testing
{
public static void main(String[] args) {
System.out.println("main method");
gameStart();
}
private static void gameStart()
{
System.out.println("some other method called");
gameOver();
}
private static void gameOver()
{
System.out.println("game over called");
if (gameTied()) {
gameStart();
}
}
}
If you're just asking "do you want to play again?" -- that would be better done in main, along the lines of
public static void main(String[] args) {
System.out.println("main method");
String playGame = "Yes";
while (playGame.equalsIgnoreCase("Yes") {
gameStart();
playGame = ask("Play again?");
}
}
To avoid unlimited recursion you may switch over to iteration and introduce return values for those methods which currently decide how to proceed (currently by directly calling the corresponding actions).
Let those methods return some sign what to do next, for example by using an enum.
Then write a loop which calls the right methods depending on the return values.
Example (abbreviated, I assume you know Java syntax):
enum Action { Start, ShowEnd, Quit }
main:
Action nextAction = Action.Start;
while (action != Action.Quit)
{
switch (action)
{
case Start:
nextAction = gameStart();
break;
case ShowEnd:
nextAction = gameEnd();
break;
// ToDo: write more actions!
default:
break;
}
}
This assumes that each such method executes until a decision was made about which action to take next.
This way your call stack will always be quite flat, as the execution always returns to the main method and then branches off into other methods.
When you write recursive code you should make sure that you have some sort of end condition BESIDES calling the function again. For example I added an end condition for the gameOver method with if(gamePlayedThisManyTimes <= 1) return;. When running the following code, the value you give the method gameStart will determine how many games you play and gameOver will decrement the value when it calls 'gameStart' to eventually reach that end condition of the recursion.
public static void main(String[] args)
{
System.out.println("main method");
gameStart(10);
}
private static void gameStart(int playGameThisManyTimes)
{
System.out.println("Game " + playGameThisManyTimes + " started...");
System.out.println("some other method called");
gameOver(playGameThisManyTimes);
}
private static void gameOver(int gamePlayedThisManyTimes)
{
System.out.println("game over called for " + gamePlayedThisManyTimes); //I would ask the user if they want to play again.
if(gamePlayedThisManyTimes <= 1)
return;
else
gameStart(gamePlayedThisManyTimes - 1);
}
Output
main method
Game 10 started...
some other method called
game over called for 10
Game 9 started...
some other method called
game over called for 9
Game 8 started...
some other method called
game over called for 8
Game 7 started...
some other method called
game over called for 7
Game 6 started...
some other method called
game over called for 6
Game 5 started...
some other method called
game over called for 5
Game 4 started...
some other method called
game over called for 4
Game 3 started...
some other method called
game over called for 3
Game 2 started...
some other method called
game over called for 2
Game 1 started...
some other method called
game over called for 1
Related
I am making a minecraft mini game plugin, i need to make a loop that do the minigame, if the game is ended, stop it, but else continue, for making that i just created a boolean that is false and i put a :
while(isEnded) {
//my code
}
But in my code, there is async fuction, so it's repeat, but the async function don't have the time to finish before an other loop start, so all my game is glitched.
Any solution to await the async function ? ( i am using Bukkit.getServer().getScheduler().runTaskTimer(Main.plugin, new Runnable() { )
thanks for the help ;)
I don't really understand where you are stuck, but I will give you some way to do what you are looking for.
Run method from the end of mini-games.
For example, when the game when, you are running a method:
public void endGame() {
// do something
callMethod();
}
Use for another variable.
You can just set a variable, then run a task like that :
public static boolean isEnd = false;
public void runTask() {
Bukkit.getScheduler().runTaskTimer(myPlugin, () -> {
if(isEnd) {
// do something
}
}, 20, 20);
}
Finally, set the variable when it's fine with just MyClass.isEnd = true;
It will run each 20 ticks (so each second, because 20 ticks = 1 second).
If you know the time to wait, you can use the same scheduler as you are using and as I explain in #2 option.
I've seen answers using a for loop which I understood, however I came across this code recently and I have no idea how it works.
public class learn {
public static int factorial (int N){
if (N<=1 ) return 1; // won't this mean that "1" is returned at the end all the time?
else return (N*factorial (N-1)); /* since there's no variable storing the sum
I don't get how this is working out either,
won't it just be returned and lost?*/
}
public static void main(String[] args) {
System.out.println(factorial(4));
}
}
Coming from a python background, so maybe I am misunderstanding something about returns in java... [Edit] seems like return 1 is also written in Python, so it's probably not a language issue, I just don't get how recursive functions end (I get how the process goes - it's a function that calls itself).
Here's an illustration of how I interpret this code (wrongly):
factorial(4) is called
4 is more than 1, so the else statement will run -- 4*factorial(3)
factorial(3) is called - else statement runs again -- 3*factorial(2)
factorial(2) is called -- 2*factorial(1). At this point, we have 4*3*2*1 but the fact that the code only stops at the if (N<=1) return 1 line means that 1 is returned instead of the sum right? (I'm obviously wrong because the console printed the right number - 24)
won't this mean that "1" is returned at the end all the time?
No, it will only return 1 when N is less than 1. (according to your condition if (N<=1 ) return 1;)
For all other cases, it continues recursively.
since there's no variable storing the sum
I don't get how this is working out either,
won't it just be returned and lost?
When a method returns, it exits the current method and return to the point of invocation and continue from there. For simplicity, take this scenario: methodA calls methodB, and methodB calls methodC:
public void methodA(){
print("entering method A.."); //(1)methodA invoked..
methodB(); //(2)call methodB
print("exiting method A"); //(8)exit from methodB, continue from here
}
public void methodB(){
print("entering method B.."); //(3)mthodB invoked..
methodC(); //(4)call methodC
print("exiting method B"); //(7)exit from methodC, continue from here. exit methodB
}
public void methodC(){
print("entering method C.."); //(5)methodC invoked..
print("exiting method C"); //(6)exit methodC, continue from whoever called methodC
}
You will get the outpus as follows:
entering method A..
entering method B..
entering method C..
exiting method C
exiting method B
exiting method A
If you can understand the program flow of methodA B and C. Now try to understand a method calling "itself".
//Let say N is 3..
public static void main(String[] args){
factorial(3); //(9)
}
public static int factorial (int N) //(1)N:3, (3)N:2, (5)N:1
{
if (N<=1 )
return 1; //(6)Ret 1, return and continue from whoever called me
else
return (N*factorial (N-1)); //(2), (4), (7)Ret 2*1, (8)Ret 3*2*1
}
At (6), it exits the method by returning 1 and continue from the place which called this method. The place where it was called is at (7).
At (7), it exits the method by returning N*1 (which is 2*1 = 2) and continue from the place which called this method. The place where it was called is at (8).
At (8), it exits the method by returning N*2 (which is 3*2 = 6) and continue from the place which called this method. The place where it was called is at (9) which is the main method.
The if statement only returns 1 if the parameter N equals or is smaller than 1, otherwise the else clause will be executed. In the else clause, since it returns a product of parameter N and the returning value of factorial(N-1), Java needs to wait for factorial(N-1) to return a value in order to do the multiplication and return the value. There is no need to store the value of parameter N into a field since a parameter is also a variable, just its value is passed from the method's caller.
In your code, the factorial is invoked 4 times.
I have a requirement where i need to call multiple methods in a sequential manner. But if any one of the method fails due to a validation, the program should not continue. I cannot use "Throw Exception because these are not actually exception rather than a condition that satisfies my requirement and after satisfying it, I don't want the program to continue.
Below is a piece of code for example and understanding. Even i use Return, it still continues to next method.
public void method1(){
System.out.println("Method 1");
return;
}
public void method2(){
System.out.println("Method 2");
return;
}
public void method3(int a) throws Exception{
System.out.println("Method 3");
if (a==3) FinalMethod();
return;
}
public void method4(){
System.out.println("Method 4");
return;
}
public void method5(){
System.out.println("Method 5");
return;
}
public void FinalMethod() {
System.out.println("This is the final method - end of the program");
return;
}
public void callMethod() throws Exception{
method1();
method2();
method3(3);
method4();
method5();
}
The method callMethod will be called from Main method. Please help me to learn this.
Edited: If The argument is 3 in method3, it should call Finalmethod and after that the program should end. I dont want it to go for method4 and method5.
Why not have the methods return a boolean to determine if the next method should run?
This is what's currently going on in in the stack when you call FinalMethod from method3:
main -> callMethod -> method3 -> FinalMethod
So when FinalMethod finishes, you go back to method3, and from there, go back to callMethod, and continue running to the end.
What I would do is make method3 return a boolean if you want to exit and call it with regard to this:
public boolean method3(int a) {
System.out.println("Method e");
return a==3;
}
...
//In callMethod
if (method3(3)) { //If we want to exit after running method3
FinalMethod();
return;
}
Though you may use System.exit(exitCode), this is not good practice, as it violates the program flow - that the program will only end at the end of the main function.
Though method3 is currently throwing an exception, you don't actually throw one in the method. However, exceptions should only be used for undefined behaviour (particularly relating to circumstances beyond your control, eg. external code). It is preferable to provide a user-friendly error and continue the program if possible, or exit gracefully if not.
Unrelated tips:
You do not have to call return at the end of a void function.
By default, you should make methods private, and only make them public when required
Calling return at the end of a method block is redundant in this scenario.
Assuming that you are looking to terminate the program on error, you can possibly use System.exit(-1) in your catch (if you follow this way), or in the if statement, if this is how you are checking for the error
Edit: I should also clarify that there is no specific meaning to using System.exit(-1) as opposed to using any System.exit(n) where n != 0, unless otherwise specified in your own documentation
I am using Bukkit API 1.8 with Java 7.
I have a repeating task that loops through all the players on the server and sets their armor randomly to either leather, chainmail, etc...
When I use the method setHelmet,setChestplate, etc... I update their inventory like usual, but since this task is running every 6 ticks, it runs fast. Therefore, when a player tries to fire a bow, the bow resets its power every time this task runs.
Since I knew it was a problem with updating the inventory, I tried removing the updateInventory method.
After doing this the armor still got put on and changed, but the bow was still being reset every time the task was ran.
How would I keep the bow from resetting while still keeping the task running?
My code:
#SuppressWarnings("deprecation")
public static void repeatEffect()
{
main.getServer().getScheduler().scheduleAsyncRepeatingTask(main, new Runnable()
{
#Override
public void run()
{
for(Player o : Bukkit.getOnlinePlayers())
{
Material M1 = Material.WOOL;
int num = rainbow.get(o.getName());
if(num==1)
{
M1 = Material.LEATHER_HELMET;
}
else if(num==2)
{
M1 = Material.CHAINMAIL_HELMET;
}
else if(num==3)
{
M1 = Material.GOLD_HELMET;
}
else if(num==4)
{
M1 = Material.IRON_HELMET;
}
else if(num==5)
{
M1 = Material.DIAMOND_HELMET;
}
rainbow.put(o.getName(), num+1);
if(rainbow.get(o.getName())>5)
{
rainbow.put(o.getName(), 1);
}
ItemStack rrhelm = createItemStack(M1, 1, "§a§lR§b§la§c§li§d§ln§e§lb§f§lo§a§lw §c§lH§d§le§e§ll§f§lm§a§le§b§lt", "§7Very special piece of armor");
o.getInventory().setHelmet(rrhelm);
}
}
}
, 6, 6);
}
If changing armour resets the players bow, you could work around it by only changing the armour of players who are joining, not wielding a bow or just after an EntityShootBowEvent.
To see if the player is wielding a bow, use:
org.bukkit.Bukkit.entity.Player player = ...;
boolean hasBowEquiped = player.getEquipment().getItemInHand().getData().getItemType().equals(Material.BOW);
After testing this some more, the only way I was able to reproduce the bow complication was by calling the deprecated updateInventory() method which you said you removed. I'm fairly certain that you still have this method somewhere in your code because I can't find anything else that would cause the bow to act this way (I was still able to fire the bow but the animation looks glitchy and the power of the arrow is sometimes incorrect).
The only difference between my code is that I used new ItemStack(M1) instead of your createItemStack() method to instantiate the helmet (also tried changing name, lore and amount). I was still able to shoot a bow just fine. Could the resetting of the bow/inventory have something to do with your createItemStack method?
There's no reason why you should be running this task asynchronously. You're accessing the Bukkit API from an asynchronous task or different thread which is a big no-no and can cause all kinds of tricky problems. Use the scheduleSyncRepeatingTask method to run the task in the same thread.
For simplicity's sake I randomly set a single armor slot (also tried all four) to either leather or iron every 6 ticks. Didn't seem to interfere with the bow. Could we see your code? Here is mine:
public void onEnable() {
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
public void run() {
for (World world : Bukkit.getWorlds()) {
for (Player player : world.getPlayers()) {
if (Math.random() < 0.5) {
player.getInventory().setBoots(new ItemStack(Material.IRON_BOOTS));
} else {
player.getInventory().setBoots(new ItemStack(Material.LEATHER_BOOTS));
}
}
}
}
}, 0, 6);
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I want to provide implementation of a 4 player dice game in which each player is implemented as a thread . Each player get a chance to throw the dice in order of player number . each throw dies return a number 1 to 6 only . the game stop whenever any player scores 25 point or more print winner player .
I am Thinking of creating classes
Dice for handling Dice
Board For handling all Thread and Player Score
TheGame for Starting game
My class Dice
import java.util.Random;
public class Dice {
Random dice;
public Dice()
{
dice=new Random();
}
public int throwDice()
{
int a= dice.nextInt(70);
a=a/10;
if (a==0)
return 1;
else return a;
}
}
My Player Class
public class Player extends Thread {
Board board;
int num;
public Player(Board b,int n)
{
board=b;
num=n;
}
public void run()
{
System.out.println("Player "+num+" is started, playing game...");
while(board.flag)
{
board.play(num);
}
}
}
Game Class
public class TheGame {
public static void main(String[] args) {
System.out.println("Initializing board...");
Board b=new Board(); //Creating object of class board
System.out.println("Initializing players...");
Player p1=new Player(b,1); // Every player is Thread
Player p2=new Player(b,2);
Player p3=new Player(b,3);
Player p4=new Player(b,4);
p1.start(); //Starting Thread
p3.start();
p2.start();
p4.start();
}
}
I am not able to think Logic or decide where to start in class Board.
Please Help me with Board code
This is not assignment or homework .
I want to do it by myself but don't have any deep idea about Synchronization in Threading
I am trying to code i am not asking complete tutorials i am just asking how do i set order when player 1(thread) get execute after player 1 have done his chance.
This is just to point you in the right direction. You need to read a lot more than I can ever write here. Then you need to to fix all manner of weird and irreproducable bugs. But you did ask...
I think it's a lot simpler, and more interesting, if all 4 players throw at once. (Though you might have more than one winner.) To do that:
Create global monitors and field (Perhaps in Game class):
public static final turnMonitor = new Object();
public static final controlMonitor = new Object();
public static volatile gameOn = true;
Then create a Player class with a run method. (Player can extend Thread, or it can extend Runnable and you can pass it to a new Thread.) Like so:
public void run() {
while (gameOn) {
synchronized (turnMonitor) { turnMonitor.wait(); }
...roll dice here...
...Put sum of Player rolls in volatile instance field or synched field...
...Update volatile player turn counter...
synchronized (controlMonitor) {
// Tell control monitor we're done.
controlMonitor.notifyAll();
}
}
}
Then you'll want control code (in the Game class?):
while (true) {
// Roll dice
synchronized (turnMonitor) { turnMonitor.notifyAll(); }
// Wait for dice to roll
do {
synchronized (controlMonitor) { controlMonitor.wait(); }
} while ( ...not all players have rolled this turn... );
if ( there's a winner ) break;
}
gameOn = false;
This should give you a start. Do study up on synchronization, volatiles, wait(), and notifyAll(). If you can't find good examples anywhere, check here (for the very basics).
When starting, print lots of debugging messages. Threads are always running when you're not expecting them to. You are going to be surprised.
To have the players roll one at a time, I think you'd want multiple turn monitors. You can notify only one waiting thread at a time, but you can't control which thread gets notified, so trying get the right thread off one monitor would be difficult.