Imma java newbie so I try to learn things. I created a boolean method, it's a small craps game. I need this method is called from main method and keep playing while return value is true (game is won) but stop executing if return value is false. I also need how many times player won. So I created something like this:
while(Craps.play())
{
Craps.play();
i++;
}
System.out.println("In total you won " + i + " times");
i is initialized as private static int i = 0; //Game counter
But output didn't see me correct. First of all, if the game is lost (return value is false) it wo't stop execution. And it doesn't count winning number correct. For example if 3 games are won, it calculates if he won 2 games.
Is there any logic error with this loop?
Thanks
You shouldn't call Craps.play() inside the loop, since you will miss validations. Also, in your original code, you are calling Craps.play() twice, but you are incremeting i only once. Change your code to this and it should work as expected:
while(Craps.play()) {
i++;
}
Related
I'm trying to implement a word game in Java, where each player takes turns extracting a number of random letters from a set, then trying to create a valid word with those letters. This is what I have so far (simplified for clarity's sake):
In the Game class, I start the game by running a thread for each player (and one for the timekeeper). I want the first player in the activePlayers list (which initially is the same as the players list) to make the first move, so I initialized the turn and turnIndex attributes to correspond to this player:
public void play()
{
this.turn = activePlayers.get(0); //the player who joined first goes first
this.turnIndex = 0; //the player's index in the ArrayList
for(Player player : players) {
new Thread(player).start();
}
new Thread(new Timekeeper()).start(); //keeps track of the game's duration
}
In the Player class, I want the players on stand-by to not do anything, and simply wait for the current player to finish their business, hence the first while loop. Then, when a player's turn has ended, I want that thread to yield the monitor to another player's thread and wait its next turn. This is how I decided to approach it:
private synchronized boolean submitWord() throws InterruptedException
{
while(game.turn != this)
{
System.out.println(this.name + " is waiting their turn...");
wait();
}
Thread.sleep(1000);
List<Tile> extracted = game.getBag().extractTiles(wordLength);
if(extracted.isEmpty())
return false; //if there are no more letters to extract, the thread ends its execution
//game logic goes here - creating and validating the word
//after this player is done, the next player makes their move
game.turnIndex++;
if(game.turnIndex >= game.activePlayers.size())
game.turnIndex = 0;
game.turn = game.activePlayers.get(game.turnIndex);
notifyAll();
return true;
}
#Override
public void run()
{
do {
try {
this.running = this.submitWord();
} catch(InterruptedException e) {
System.out.println("Something went wrong with " + this.name + "...");
e.printStackTrace();
}
} while(this.running);
game.activePlayers.remove(this); //the player is now inactive
if(game.winner == this)
System.out.println("Winner: " + this.name + " [" + this.score + " points]");
}
However, when I try to run the program, I get something like this:
Player 2 is waiting their turn...
Player 3 is waiting their turn...
1 seconds elapsed...
Player 1: AERIAL [36 points]
Player 1 is waiting their turn...
2 seconds elapsed...
3 seconds elapsed...
4 seconds elapsed...
5 seconds elapsed...
6 seconds elapsed...
Basically, the game doesn't move past Player 1's first try, and I get stuck in an infinite loop where nothing happens. Am I not using the wait() and notifyAll() methods properly? How should I make the player threads communicate with each other?
If I have understood your code correctly, that submitWord method belongs to the Player class. The keyword synchronized should be used to obtain the monitor of a shared resource to limit different threads from accessing the same resource at the same time and avoid race conditions.
In your case, you're synchronizing over a Player thread which is not the right design. You should synchronize instead over the shared resource which is the game object in this scenario. Besides, try to use synchronized blocks rather than entire synchronized methods, as the latter are more likely to block.
Within the Player's run method you should check whether the thread can acquire the game resource first with a synchronized block, if they do, then you can check whether it's the Player's turn by confronting the turn index of the game object with the Player's index. If it's not the Player's turn it invokes the wait() method; otherwise it carries on with its task by invoking submitWord.
Here, I've tweaked your code. You forgot a notify (or notifyAll) call when you were returning false in your submitWord method. That might have caused some stuck scenarios when there were no combinations available.
//Now, this method can be called only under the condition the the game's monitor lock has been already acquired. So, it can only be invoked within a synchronized block.
private boolean submitWord() {
List<Tile> extracted = game.getBag().extractTiles(wordLength);
if(extracted.isEmpty()){
//notify is more efficient than notifyAll as it causes less overhead by awakening only one random thread instead of all the ones waiting
this.game.notify();
//you were returning without notifying here... This might have caused some stucking scenarios...
return false;
}
//game logic goes here - creating and validating the word
//Rotating the turn
game.turnIndex = (this.game.turnIndex + 1) % this.game.activePlayers.size();
game.turn = game.activePlayers.get(game.turnIndex);
this.game.notify();
return true;
}
#Override
public void run() {
do {
synchronized(this.game){
if (this.game.indexTurn == this.index){
this.running = this.submitWord();
//It's more efficient to check here whether the player must be removed or not as you already own the game's lock
if (!this.running){
this.game.activePlayers.remove(this);
}
} else {
try {
this.game.wait();
} catch(InterruptedException e) {
System.out.println("Something went wrong with " + this.name + "...");
e.printStackTrace();
}
}
}
} while(this.running);
//you should re-acquire the game's lock here since you're modifying the set of players
//synchronized(this.game){
// this.game.activePlayers.remove(this);
//}
if(this.game.winner == this){
System.out.println("Winner: " + this.name + " [" + this.score + " points]");
}
}
Just a thought, but it could be that the sleep is happening within a synchronized method: Thread.sleep is blocking other thread also, working on other method, along with itself callled inside synchronized method
I'm a bit new to Java and LibGDX, and I'm working on a point based game. A problem I'm facing is that the update method constantly runs something that I want to run on a timely manner. In my update method, I have the code to increment the score if a point is earned, and to make a lose state come up when the player lost. Without going into much detail, here's the pseudo code I have:
protected void update(float dt){
for(Thing x : a list) {
x.update(dt);
//continue
if (you complete the objective of the game) {
score++;
//do other stuff
}
//lost
if (you fail to complete the objective){
make lose state come up
}
}
//I want something like this to run:
if(score >=0 && score <=10){
do something ONCE(ie. print to console once)
}
if(score >= 11 && score <=15){
do something once
}
if(ect...){
do something else once
}
.
.
.
The problem here is that, if the IF condition is met, I notice the IF block gets executed multiple times very quickly(ie. printing to the console a lot). I have enclosed the details of the code that relies on the score in a separate class, I just want to be able to call the method from this update method and have it run once depending on the score conditions (ie. run it again if the score satisfies another IF statement)
I had the same problem, but I solved it by using following method. In Libgdx the update method runs in 1/60 second. That is the reason the method is rendering continously and the if condition will be executing various times.
To solve this problem, just declare an integer variable, say count, in your create method.
public static int count;
public static void create()
{
count =0;
// do other stuffs
}
protected void update(float dt){
// just increment this count value in your update method
for(Thing x : a list) {
count++
x.update(dt);
//continue
if (you complete the objective of the game) {
score++;
//do other stuff
}
//lost
if (you fail to complete the objective){
make lose state come up
}
}
// and make a small condition to run the if condition only once by using the declared variable "count".
if(count%60==0){
// here the condition only executes when the count%60==0.that is only once in 1/60 frames.
if(score >=0 && score <=10){
}
if(score >= 11 && score <=15){
}
if(ect...){
}
}
.
.
. This is how I solved the same issue.
The update() method is called every frame, multiple times very quickly(usually 60 times per second) in an infinite loop. This is not only specific in libGDX, but in any game engine. And when some condition of your if block evaluates to true, that if block is executed every frame until that condition becomes false again. But you want to execute the block only once after the condition changed.
Just declare a variable named isLastScoreUnder10 or whatever, and update it after the if block. Like this:
private boolean isLastScoreUnder10 = false;
protected void update(float dt){
if(!isLastScoreUnder10 && score >=0 && score <=10){
isLastScoreUnder10 = true;
// ..do something
} else {
isLastScoreUnder10 = false;
}
}
Hi guys I have a nested Thread and using it to see when a player has taken a turn (in a draughts game) O have a game object and a public variable changedTurns.
new Thread() {
public void run(){
check();
}
private void check(){
boolean sent = false;
while(true){
System.out.println("ee"); \\line 9
if(game.changedTurns){
System.out.println("gg");
if(!sent){
System.out.println("ok");
sent =true;
}
}
}
}.start();
Everything works as expected like above I.e console shows plenty of "ee" followed by "gg" and then "ok" when the player takes their turn, however without line 9 nothing is shown when the player takes their turn ?!
You don't need to use threading to analyze whether the player has taken a turn. Just create a Player[] array and add a variable turn for the index of the player whose turn it is. Increment turn when a Player makes a turn.
I am making a little game in Processing which is similar to those Guitar Hero style games and I am trying to do 2 things:
When the game loads, stop the time from moving
During the game, allow for Pause functionality
Now, I know I cant stop the time since the millis() returns the milliseconds since the application launched, so my timer will need to be millis() - millis() at the start to equal zero, so when the user presses START, they can obviously start at the start. The game reads a file at the start, similar to a subtitles file, that has the note to be played and the time in milliseconds that it should appear on screen.
My problem is, when I pause the game, the timer keeps going and when I unpause the game, all the notes get "bunched up" due to my logic, as you'll see from my code.
Can someone suggest a better algorithm than the one I'm using? Its late and I've been working on this all day and night. I think the problem is with the for() below:
public void draw()
{
if (gameInProgress)
{
currentTimerValue = millis(); // Update the timer with the current milliseconds
// Check to see if the note times falls between the current time, or since the last loop (difficult to match exact millisecond)
for(int i=0 ; i<songNotes.length ; i++)
{
if( songNotes[i].getStartTime() > previousTimerValue && songNotes[i].getStartTime() <=currentTimerValue)
notes.add(songNotes[i]);
}
noStroke();
textFont(f,18);
drawButtons(); //Draws coloured buttons relating to Button presses on the controller
drawHighScoreBox(); // Draws high score box up top right
drawLines(); // Draws the strings
moveNotes(); // Moves the notes across from right to left
//Now set the cutoff for oldest note to display
previousTimerValue=currentTimerValue; //Used everytime on the following loop
}
else
{
drawMenu(); // Draw the Main/Pause menu
}
}
NOTE: The boolean gameInProgress is set below when the users presses the pause button, eg "P", and songNotes is an array of objects of type Note that I wrote myself. It has 2 member variables, noteToBePlayed and timeToBePlayed. The method getStartTime()returns timeToBePlayed which is a millisecond value.
Any help is appreciated.
Thanks
How about having another integer to store time when you pause and use that to offset the game timer ?
So, in 'gameInProgress' mode you update currentTimerValue and previousTimerValue and in 'paused/menu' mode you update a pausedTimerValue, which you use to offset the 'currentTimerValue'. I hope this makes sense, it sounds more complicated in words, here's what I mean:
boolean gameInProgress = true;
int currentTimerValue,previousTimerValue,pausedTimerValue;
void setup(){
}
void draw(){
if(gameInProgress){
currentTimerValue = millis()-pausedTimerValue;
println("currentTimerValue: " + currentTimerValue + " previousTimerValue: " + previousTimerValue);
previousTimerValue=currentTimerValue;
}else{
pausedTimerValue = millis()-currentTimerValue;
}
}
void mousePressed(){
gameInProgress = !gameInProgress;
println("paused: " + (gameInProgress ? "NO" : "YES"));
}
Click the sketch to toggle modes and look in the console for times. You'll notice that you only loose a few millis between toggles, which is acceptable.
Use not system timer but special timer class with pause functionality. I'm sure it is not hard to implement such class by yourself. I know that java has Timer class but unfortunately it not support pause functionality.
I had a task to write simple game simulating two players picking up 1-3 matches one after another until the pile is gone. I managed to do it for computer choosing random value of matches but now I'd like to go further and allow humans to play the game. Here's what I already have : http://paste.pocoo.org/show/201761/
Class Player is a computer player, and PlayerMan should be human being. Problem is, that thread of PlayerMan should wait until proper value of matches is given but I cannot make it work this way. Logic is as follows: thread runs until matches equals to zero. If player number is correct at the moment function pickMatches() is called. After decreasing number of matches on table, thread should wait and another thread should be notified. I know I must use wait() and notify() but I can't place them right.
Class Shared keeps the value of current player, and also amount of matches.
public void suspendThread() {
suspended = true;
}
public void resumeThread() {
suspended = false;
}
#Override
public void run(){
int matches=1;
int which = 0;
int tmp=0;
Shared data = this.selectData();
String name = this.returnName();
int number = this.getNumber();
while(data.getMatches() != 0){
while(!suspended){
try{
which = data.getCurrent();
if(number == which){
matches = pickMatches();
tmp = data.getMatches() - matches;
data.setMatches(tmp, number);
if(data.getMatches() == 0){
System.out.println(" "+
name+" takes "+matches+" matches.");
System.out.println("Winner is player: "+name);
stop();
}
System.out.println(" "+
name+" takes "+matches+" matches.");
if(number != 0){
data.setCurrent(0);
}
else{
data.setCurrent(1);
}
}
this.suspendThread();
notifyAll();
wait();
}catch(InterruptedException exc) {}
}
}
}
#Override
synchronized public int pickMatches(){
Scanner scanner = new Scanner(System.in);
int n = 0;
Shared data = this.selectData();
System.out.println("Choose amount of matches (from 1 to 3): ");
if(data.getMatches() == 1){
System.out.println("There's only 1 match left !");
while(n != 1){
n = scanner.nextInt();
}
}
else{
do{
n = scanner.nextInt();
}
while(n <= 1 && n >= 3);
}
return n;
}
}
Well, let me first say that I think you are making this hardier than you need to. If it were me, I would create a 'GameMaster' class whose job it is to loop and tell each player when their turn comes up. Your player classes wouldn't have loops, just a takeTurn method. This way you can remove the waiting/notifying behavior from your player classes.
If you wish to keep the design you have, I would still get rid of the wait/notify and use a Semaphore. Check the docs for proper usage, but the gist is that you would remove the suspend/resume methods and have a acquire() call at the top of your loop and release at the bottom. Just make sure fairness is set to true in the constructor, that way you won't have to worry about a player taking two turns in a row by acquiring the semaphore lock twice in a row.
Ok, so I managed to do it without wait() etc.
http://paste.pocoo.org/show/201966/
When you find yourself having to set up communication between threads to synchronize their execution, just so that a specified sequence of events takes place (such as taking turns playing a game), it's a good sign that you may have more threads than you need.
In this case, consider a single thread that executes a takeTurn() method on various extensions of a Player class might make life easier for you. You could make Player an abstract base class that mandates .takeTurn(), then have HumanPlayer and MachinePlayer classes encapsulate the code that makes sense for each type of player inside that method. This should make extension to larger numbers of players relatively trivial as compared to lots of wait() and notify().