How to run two thread periodically? - java

I am asked to make a Player class ( that implements runnable ) in which I implement a run method which generates a random number and waits for the method getchoice and a getchoice method which return the generated number and notifies run . then a RockPaperScissors class( that implements Runnable) which contains method run that containt two threads containing each a player object , these two threads should play against each other 1000 times , then they should be interrupted and then it will be displayed how many times each player won . . my problem is , when my code starts to run , at the beginning it is perfect , but at a random round it starts to just play many times player 1 before going to player 2 which defeats the purpose of the game : here is the code :
public class RockPaperScissors implements Runnable {
int result1 ;
int result2 ;
int result3 ;
private final Object lock = new Object();
public void run(){
synchronized(lock){
Player a = new Player() ;
Player b = new Player() ;
Thread a1 = new Thread(a) ;
Thread b1= new Thread (b) ;
a1.start();
b1.start();
int choice1 = -100 ;
int choice2 = -1066 ;
for (int i = 0 ; i < 1000 ; i++){
try {
choice1 = a.getChoice();
} catch (InterruptedException e1) {
}
try {
choice2 = b.getChoice();
} catch (InterruptedException e) {
}
if (choice1 == 1 && choice2==0)
result2++;
else if (choice2 == 1 && choice1==0)
result1++;
else if (choice1 == 1 && choice2==1)
result3++ ;
else if (choice1 == 1 && choice2==2)
result1++ ;
else if (choice1 == 2 && choice2==1)
result2++ ;
else if (choice1 == 0 && choice2==2)
result1++ ;
else if (choice1 == 2 && choice2==0)
result2++ ;
else if (choice1 == 2 && choice2==2)
result3++ ;
else if (choice1 == 0 && choice2==0)
result3++ ;
}
and this is class Player :
public class Player implements Runnable {
private final Object lockvalue = new Object();
private int a;
public void run() {
synchronized (lockvalue) {
for (int counter = 0; counter < 1000; counter++) {
java.util.Random b = new java.util.Random();
a = b.nextInt(3);
System.out.println(counter);
try {
lockvalue.wait();
} catch (InterruptedException e) {
System.out.println("Thread player was interrupted");
}
}
}
}
public int getChoice() throws InterruptedException {
synchronized (lockvalue) {
lockvalue.notify();
return a;
}
}
}
if my programm runs perfectly the counter display should always have the number starting from 0 to 1000 duplicated one after the other , but here it starts like that but then it gets messed up and it never reaches 1000 , it stops sometimes at 700 sometimes at 800 . all I am allowed to used is notify() , notifyAll() , wait() , start() , interrupt() and join() .
your help would be greatly appreciated . Thanks

Your implementation and approach show that you don't understand concurrency, how it works and when should be applied.
I recommend you to read corresponding chapter (Concurrency) in Bruce Eckel's "Thinking in Java" - http://www.mindview.net/Books/TIJ/
To make your code work You have to add one more wait-notify before return in Player.getChoise()
Here is fixed version:
RockPaperScissors.java
package game;
public class RockPaperScissors
{
static int player1wins = 0;
static int player2wins = 0;
static int draw = 0;
public static void main(String[] args) throws InterruptedException
{
int cycles = 1000;
Player player1 = new Player("Player-1", cycles);
Player player2 = new Player("Player-2", cycles);
new Thread(player1).start();
new Thread(player2).start();
for (int i = 0; i < cycles; i++)
{
Choice choice1;
Choice choice2;
choice1 = player1.getChoice();
System.out.println("Value 1 is definitely generated");
choice2 = player2.getChoice();
System.out.println("Value 2 is definitely generated");
System.out.printf("\n%3d\nPlayer1 - %8s\nPlayer2 - %8s\n", i, choice1.name(), choice2.name());
if (choice1 == choice2)
{
draw++;
System.out.println("Draw!");
}
else if (choice1 == Choice.ROCK)
{
if (choice2 == Choice.PAPER)
{
player2wins++;
System.out.println("2 wins!");
}
else
{
player1wins++;
System.out.println("1 wins!");
}
}
else if (choice1 == Choice.PAPER)
{
if (choice2 == Choice.SCISSORS)
{
player2wins++;
System.out.println("2 wins!");
}
else
{
player1wins++;
System.out.println("1 wins!");
}
}
else if (choice1 == Choice.SCISSORS)
{
if (choice2 == Choice.ROCK)
{
player2wins++;
System.out.println("2 wins!");
}
else
{
player1wins++;
System.out.println("1 wins!");
}
}
}
System.out.printf("Player 1 wins - %3d times;\n" +
"Player 2 wins - %3d times;\n" +
"Draw result - %3d times\n\n", player1wins, player2wins, draw);
System.out.printf("Player-1 cycles left = %d\n" +
"Player-2 cycles left = %d\n", player1.getCounter(), player2.getCounter());
}
}
Player.java
package game;
import java.util.Random;
public class Player implements Runnable
{
private Random random = new Random();
private int value;
private int counter;
private String name;
public Player(String name, int cycles)
{
this.name = name;
this.counter = cycles;
}
public synchronized void run()
{
while (true)
{
try
{
wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
value = random.nextInt(3);
System.out.println(name + " ... Value was generated = " + value);
notify();
// Otherwise your thread will never stop!
counter--;
if (counter <= 0)
{
System.out.println(name + " ... Limit of operations is exceeded.");
break;
}
}
}
public synchronized Choice getChoice() throws InterruptedException
{
System.out.println(name + " ... now can generate value");
notify();
System.out.println(name + " ... wait until value is generated");
wait();
Choice choice = Choice.values()[value];
System.out.println(name + " ... returning generated value: " + value);
return choice;
}
public int getCounter()
{
return counter;
}
}
Choise.java
package game;
public enum Choice
{
ROCK,
PAPER,
SCISSORS;
}

I would consider implementing your logic using a semaphore or a CountDownLatch for better synchronization
http://tutorials.jenkov.com/java-util-concurrent/semaphore.html
http://tutorials.jenkov.com/java-util-concurrent/countdownlatch.html

Related

How to terminate while loop on Q press in java console application

How can i terminate while loop when user press 'q' so program should exit?
It is Simple Java Program and i am not using swing etc.
while (flag) {
int x = ran.nextInt(MaxValue - MinValue + 1);
System.out.print(x);
System.out.print(" enclosed by {");
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i][0]);
if ((x >= arr[i][0]) && (x <= arr[i][1])) {
System.out.print("(" + arr[i][0] + "," + arr[i][1] + ")");
}
}
System.out.print("}\n");
count++;
}
import java.util.Scanner;
public class test {
public void testFunction() {
listener threadobj = new listener();//create the object
Thread thread = new Thread(threadobj);//create the thread
thread.start();//start the thread. it runs asynchronously
while (flag /*assuming flag is unrelated*/
&& !threadobj.exit) {
//when !threadobj.exit is false it means that q has been pressed.
//so flag && !threadobj.exit will be false if at least one is false
//so the loop will end
int x = ran.nextInt(MaxValue - MinValue + 1);
System.out.print(x);
System.out.print(" enclosed by {");
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i][0]);
if ((x >= arr[i][0]) && (x <= arr[i][1])) {
System.out.print("(" + arr[i][0] + "," + arr[i][1] + ")");
}
}
System.out.print("}\n");
count++;
}
threadobj.killMe = true;//finish its loop incase it is still running :)
}
}
class listener implements Runnable {
public boolean exit; //if true then the q button has been pressed
public boolean killMe; //set to true to kill this thread
#Override
public void run() {
Scanner scanner = new Scanner(System.in);
while (!killMe) {
if(scanner.hasNext("q") || scanner.hasNext("Q")) { //Should trigger when a q is pressed.
exit = true; //if not use 'scanner.nextLine()'
//wait a bit for input, so less cpu is used for constant checks.
try {
this.wait(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public listener() {
exit = false;
killMe = false;
}
}

Implementing a Timer in a Rummikub game in Java

I am making a rummikub game in java and I want to implement a timer that runs for 2 minutes. Within the 2 minutes, the user has to enter inputs for whether they want to play or skip or end turn if a tile has been played. If they choose play they need to choose whether they want to play an individual tile, play a meld, or exit the sequence (All of these inputs have to be done within 2 minutes). If they don't finish the turn withing 2 minutes, then the turn has to end and no input should be taken and the next player plays their turn. I will post some of the code below. How should I go about implementing this timer? I have 2 methods for playing in the Human class and the GameTimer class and the playTurn() method in the Game class. At the moment I am testing with 10 seconds
package com.COMP3004.Rummikub.models;
import java.util.Timer;
import java.util.TimerTask;
public class GameTimer {
private int seconds;
private boolean started;
private boolean stopped;
private Timer timer;
private TimerTask task = new TimerTask() {
public void run() {
seconds++;
System.out.print(seconds + ", ");
if(seconds % 30 == 0) {
System.out.println();
}
if(seconds == 10) {
stop();
}
}
};
public GameTimer() {
started = false;
stopped = true;
seconds = 0;
timer = new Timer();
}
public void start() {
started = true;
stopped = false;
//timer.schedule(task, 0, 1000);
new Timer(true).schedule(task, 0, 1000);
//System.out.println("Timer Started");
/*if(seconds == 10) {
stop();
}*/
}
public boolean isStarted() { return started; }
public void stop() {
task.cancel();
seconds = 0;
//System.out.println("Timer Stopped");
stopped = true;
}
public boolean isStopped() { return stopped; }
public int getSeconds() { return seconds; }
public boolean stopsAtRightTime() {
start();
/*System.out.println(seconds);
int secondsPassed = 0;
do {
secondsPassed = seconds;
System.out.println(seconds);
}
while(seconds <= 10);
System.out.println(secondsPassed);
this.stop();
if(secondsPassed == 10) {
return true;
}*/
int secondsPassed = 0;
try {
Thread.sleep(60000);
secondsPassed = seconds;
System.out.println(seconds);
}
catch(InterruptedException e) {
}
if(secondsPassed == 60 || secondsPassed == 0) {
//stop();
return true;
}
return false;
}
}
public boolean makeAPlay(Scanner reader) {
returned = false;
while(true) {
System.out.println("Choose one of the following commands:");
System.out.println(" - 'M' to play a meld.");
System.out.println(" - 'T' to play an individual tile.");
System.out.println(" - 'B' to move an existing tile on the board.");
System.out.println(" - 'L' to exit this sequence.");
decision2 = 'K';
TimerTask timerTask = new TimerTask() {
public void run() {
if(decision2 == 'K') {
decision2 = 'L';
return;
}
}
};
try {
Timer timer = new Timer();
timer.schedule(timerTask, 10000 - getTimer().getSeconds()*1000);
decision2 = (decision2 == 'L')? 'L': reader.next().toUpperCase().charAt(0);
timer.cancel();
}
catch(Exception e) {
}
if (decision2 == 'M') {
String tileChoice = "";
Meld meld = new Meld();
this.getHand().createMeld();
while (!tileChoice.equals("D")) {
if (this.getHand().size == 0) { break; }
System.out.println("Current Meld: " + meld.meldToString());
System.out.println("Hand: " + this.getHand().handToString());
System.out.println("Select a tile you'd like to add to your meld, type 'D' to exit.");
tileChoice = reader.next().toUpperCase();
if (tileChoice.equals("D")) { break; }
for (int i = 0; i < this.getHand().size; i++) {
if (this.getHand().getTile(i).tileToString().equals(tileChoice)) {
meld.addTile(this.getHand().getTile(i));
this.getHand().removeFromHand(i);
break;
} else if (i == (this.getHand().size - 1) && !(tileChoice.equals("D"))) {
System.out.println("It seems that the tile " + tileChoice + " isn't in your posession. Please try again.");
}
}
}
if (tileChoice.equals("D")) {
if (meld.getMeldSize() >= 3 && meld.checkIfValidMeld() == true) {
for (int i = 0; i < meld.getMeldSize(); i++) {
System.out.println(meld.getTileInMeld(i).tileToString());
}
this.playMeld(meld, reader);
turnValue = turnValue + meld.getMeldValue();
} else {
System.out.println("Invalid meld. Please try again.");
for (int i = 0; i < meld.getMeldSize(); i++) {
this.getHand().addTile(meld.getTileInMeld(i));
}
this.getHand().sortHand();
tileChoice = "";
}
}
}
if (decision == 'T') {
if (initialMeldPlayed == true) {
String tileChoice = "";
System.out.println("Hand: " + this.getHand().handToString());
System.out.println("Which tile would you like to add to the board?");
tileChoice = reader.next().toUpperCase();
Tile tempTile = this.getHand().getTile(tileChoice);
if (this.getHand().getPlayerHand().contains(tempTile)) {
System.out.println("Where would you like to put " + tempTile.tileToString() + " ?");
System.out.println("X-Coordinate: ");
int xTile = reader.nextInt();
System.out.println("Y-Coordinate: ");
int yTile = reader.nextInt();
for (int i = 0; i < this.getHand().size; i++) {
if (this.getHand().getTile(i).tileToString().equals(tileChoice)) {
this.addTile(this.getHand().getTile(i), xTile, yTile);
}
}
System.out.println("Board:");
board.boardToString();
} else {
System.out.println("It seems that you don't have " + tileChoice + " isn't in your hand. Please try again.");
}
} else {
System.out.println("You cannot play individual tiles on the board during your initial meld.");
}
}
if (decision == 'B') {
if (initialMeldPlayed == true) {
while(true) {
board.boardToString();
System.out.println("Which tile would you like to move on the board?");
System.out.println("Current X-Coordinate ('-1' to exit): ");
int xTile = reader.nextInt(); if (xTile == -1) { break; }
System.out.println("Current Y-Coordinate ('-1' to exit): ");
int yTile = reader.nextInt(); if (yTile == -1) { break; }
Spot oldSpot = board.getSpot(xTile, yTile);
Tile tile = oldSpot.getTile();
System.out.println("Where would you like to move tile " + tile.tileToString() + " to?");
System.out.println("New X-Coordinate: ");
int xTileNew = reader.nextInt();
System.out.println("New Y-Coordinate: ");
int yTileNew = reader.nextInt();
Spot newSpot = board.getSpot(xTileNew, yTileNew);
this.moveTile(tile, newSpot);
}
} else {
System.out.println("You cannot manipulate the board during your initial meld.");
}
}
if (decision == 'L') {
if (board.checkIfValidMelds() == false) {
System.out.println("That wasn't a valid move. Please try again.");
this.setTilesBeenPlayed(false);
this.undoTurn();
return false;
} else {
return false;
}
}
return returned;
}
//return false;
}
public GameTimer getTimer() { return timer; }
public void play(Scanner reader, Deck deck) /*throws InterruptedException*/ {
turnValue = 0;
timer = new GameTimer();
long startTime = System.currentTimeMillis();
while( /*(System.currentTimeMillis()-startTime)<10000 ||*/ myTurn == true /*||timer.getSeconds()!=10*/) {
//reader = new Scanner(System.in);
System.out.println("Choose one of the following commands:");
System.out.println(" - 'P' to play your turn.");
System.out.println(" - 'S' to skip your turn & draw a tile.");
System.out.println(" - 'E' to end your turn if you've already played atleast one tile.");
if(timer.getSeconds() == 0) {
timer.start();
}
//while(timer.getSeconds() != 10) {
System.out.print(timer.isStopped());
/*else if(timer.getSeconds() == 10) {
//this.setHasInitialMeldBeenPlayed(false);
this.setTilesBeenPlayed(false);
this.undoTurn();
Tile t = this.getHand().dealTile(deck);
System.out.println("Out of time");
System.out.println("Turn ended: Player drew " + t.tileToString() + ".");
System.out.println("----------------------------------------");
this.setTurnStatus(false);
timer.stop();
}*/
decision = 'N'; //'N' for no input
TimerTask task = new TimerTask() {
public void run() {
if(decision == 'N') {
Tile t = getHand().dealTile(deck);
System.out.println("Timeout");
System.out.println("Turn ended: Player drew " + t.tileToString() + ".");
System.out.println("----------------------------------------");
setTilesBeenPlayed(false);
undoTurn();
setTurnStatus(false);
//return;
}
if(timer.getSeconds() == 10) {
}
}
};
try {
Timer timer = new Timer();
timer.schedule(task, 10000);
decision = reader.next().toUpperCase().charAt(0);
timer.cancel();
}
catch (Exception e) {
}
if (decision == 'P') {
makeAPlay(reader);
} else if (decision == 'S') {
if (hasTileBeenPlaced == false) {
Tile t = this.getHand().dealTile(deck);
System.out.println("Turn ended: Player drew " + t.tileToString() + ".");
System.out.println("----------------------------------------");
this.setTurnStatus(false);
timer.stop();
} else {
System.out.println("You've already made a play. Try typing 'E' to end your turn.");
}
} else if (decision == 'E') {
if (initialMeldPlayed == false) {
if (turnValue >= 1) {
System.out.println("Initial Meld Completed.");
System.out.println("----------------------------------------");
this.setHasInitialMeldBeenPlayed(true);
this.setTilesBeenPlayed(true);
this.setTurnStatus(false);
timer.stop();
} else {
System.out.println("Your Initial Meld total must be greater than or equal to 30 points.");
System.out.println("You played: " + turnValue + ". Please try again.");
this.setHasInitialMeldBeenPlayed(false);
this.setTilesBeenPlayed(false);
this.undoTurn();
turnValue = 0;
}
} else if (initialMeldPlayed == true) {
if (hasTileBeenPlaced == true) {
this.setTurnStatus(false);
timer.stop();
} else {
this.undoTurn();
System.out.println("You must either play your turn or draw a tile.");
}
}
}
else {
System.out.println("You may have entered the wrong character. Please try again.");
}
//}
}
}
public void playTurn(int i) {
printAll();
// Play if human
if (allPlayers.get(i).isAI() == false && allPlayers.get(i).myTurnStatus() == true) {
System.out.println("Player " + (i+1) + "'s Hand[" + allPlayers.get(i).getHand().size + "]: " + allPlayers.get(i).getHand().handToString());
int oneMoreTile = allPlayers.get(i).getHand().getNumTiles() + 1;
TimerTask timerTask = new TimerTask() {
public void run() {
if(allPlayers.get(i).getHand().getNumTiles() == oneMoreTile) {
}
else if(allPlayers.get(i).getHand().getNumTiles() == oneMoreTile - 1) {
Tile t = allPlayers.get(i).getHand().dealTile(deck);
System.out.println("ended: Player drew " + t.tileToString() + ".");
System.out.println("----------------------------------------");
allPlayers.get(i).setTurnStatus(false);
}
}
};
try {
Timer timer = new Timer();
timer.schedule(timerTask, 10000);
allPlayers.get(i).play(reader, deck);
timer.cancel();
if(allPlayers.get(i).myTurnStatus() == false) {
nextPlayersTurn(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// Play if AI
if (allPlayers.get(i).isAI() == true && allPlayers.get(i).myTurnStatus() == true) {
allPlayers.get(i).play(reader);
if (allPlayers.get(i).hasTilesBeenPlayed() == false) {
Tile t = allPlayers.get(i).getHand().dealTile(deck);
System.out.println("Turn ended: Player " + (i+1) + " has decided to draw a tile.");
System.out.println("Tile drawn: " + t.tileToString());
nextPlayersTurn(i);
}
}
// Sets next players turn
nextPlayersTurn(i);
}
Well this is very fast written code but I hope it can give you a better opinion about the event management.
private GameTimer _task; // the object.
// .....................
// Put these 2 lines wherever you call the event to start.
_task.setStartTime(System.currentTimeMillis() + (60000L * eventTime)); // eventTime == 2 minutes
ThreadPoolManager.getInstance().executeGeneral(_task);
// .....................
class GameTimer implements Runnable
{
private long _startTime;
public ScheduledFuture<?> nextRun;
public GameTimer(long startTime)
{
_startTime = startTime;
}
public void setStartTime(long startTime)
{
_startTime = startTime;
}
#Override
public void run()
{
int delay = (int) Math.round((_startTime - System.currentTimeMillis()) / 1000.0);
if (delay == 0)
{
// start
if (isStarted())
{
stop();
// You can place a scheduler here to trigger an auto-start.
}
else
{
start();
nextRun = ThreadPoolManager.getInstance().scheduleGeneral(this, endEvent);
// endEvent is the time you want the run() method to run again.
// In this case, when the event is finished.
// This line is triggering the jvm to auto run this method again in the given time.
// So if the event is already started, the run() method will run again and it will close it again.
}
}
}
}
Just to mention that the code is only an example of how you could rewrite better your event timer.
Hope it helps!

Error using linked list remove function. after advanced for loop breaks

I am trying to get my bet system to detect if the input numbers are duplicates. When you run the program, press 2 on the "for box" bet and follow instructions from there. The issue lies in the winlose duplicate and also for the non duplicate. I don't know how I am supposed to fix the issue.
Error stacktrace :
at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:966)
at java.util.LinkedList$ListItr.next(LinkedList.java:888)
at numbersgame.Test.winLoseBetDuplicate(NumbersGame.java:190)
at numbersgame.Test.checkDuplicate(NumbersGame.java:167)
at numbersgame.Test.WinLoseBox(NumbersGame.java:134)
at numbersgame.Test.getValues(NumbersGame.java:117)
at numbersgame.NumbersGame.main(NumbersGame.java:24)
C:\Users\cymmm1\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 6 seconds)
Code :
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package numbersgame;
import java.lang.reflect.Array;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JOptionPane;
/**
*
* #author cymmm1
*/
public class NumbersGame {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Test numbers = new Test();
numbers.getValues();
boolean win = numbers.win; //this checks if you won, either as a duplicate or not.
if (win) {
System.out.println("You won");
switch (numbers.bet_Type) {
case 1:
System.out.println("You waged " + numbers.bet_Amount
+ "dollars and you will get "
+ numbers.bet_Amount * 600 + " back.");
break;
case 2:
if (numbers.dupwin) {
System.out.println("You waged " + numbers.bet_Amount
+ "dollars and you will get "
+ numbers.bet_Amount * 200 + " back.");
} else {
System.out.println("You waged " + numbers.bet_Amount
+ "dollars and you will get "
+ numbers.bet_Amount * 100 + " back.");
}
break;
}
} else {
System.out.println("Sorry, you lost $" + numbers.bet_Amount + " dollars");
}
System.exit(0);
}
}
class Test {
public int bet_Type;
public int bet_Amount;
public int player_Number;
public int winning_Number;
private JOptionPane panel;
public boolean win;
public List<Integer> digits = new LinkedList<>();
List<Integer> digits2 = new LinkedList<>();
public void getValues() {
panel = new JOptionPane();
this.bet_Type = (Integer.parseInt(panel.showInputDialog("What is the bet type. 1 for straight, 2 for box")));
this.bet_Amount = (Integer.parseInt(panel.showInputDialog("How much is the bet")));
boolean bad = true;
while (bad) {
this.player_Number = (Integer.parseInt(panel.showInputDialog("What is the player's Number. 3 numbers must be inputted")));
int playerNumCopy = this.player_Number;
while (playerNumCopy > 0) {
digits.add(0, playerNumCopy % 10);
playerNumCopy = playerNumCopy / 10;
}
int lengthOfNum = digits.size();
if (lengthOfNum != 3) {
bad = true;
} else {
bad = false;
}
}
bad = true;
while (bad) {
this.winning_Number = (Integer.parseInt(panel.showInputDialog("What is the winning Number")));
int winningnumbercopy = this.winning_Number;
while (winningnumbercopy > 0) {
digits2.add(0, winningnumbercopy % 10);
winningnumbercopy = winningnumbercopy / 10;
}
int lengthOfNum = digits2.size();
if (lengthOfNum != 3) {
bad = true;
} else {
bad = false;
}
}
//========END OF CHECK FOR PROPER NUMBERS=================================
//Now to check for type of bet and se the method appropriate
if (this.bet_Type == 1) {
win = WinLoseStraight();
} else {
win = WinLoseBox();
}
}
private boolean WinLoseStraight() {
if (this.player_Number == this.winning_Number) {
return true;
} else {
return false;
}
// this goes back to getValues
}
private boolean WinLoseBox() {
//this checks for duplicates. if it isnt a duplicate then check for a box non-dup
boolean duplicatewin = checkDuplicate();
if (duplicatewin) { //you either won with a duplicate number or nonduplicate. check Duplicate does to things at once
return true;
} else {
return false;
}
}
public boolean duplicate;
public boolean dupwin;
//this checks for duplicated numbers
public boolean checkDuplicate() {
duplicate = false;
int[] array = new int[digits.size()];
int i = 0;
for (int numbers : digits) {
array[i] = numbers;
System.out.println(array[i]);
i++;
}
for (int j = 0; j < array.length; j++) {
for (int k = j + 1; k < array.length; k++) {
if (array[k] == array[j]) {
duplicate = true;
System.out.println(array[k] + " equals " + array[j]);
break; //if duplicated found, it will exit out of the for loop
}
}
if (duplicate) {
System.out.println("we found duplicate.");
dupwin = winLoseBetDuplicate(); //if it has duplicated numbers, it will check if your numbers match up
break;
} else {
dupwin = winLostBetNonDuplicate();
}
}
return dupwin; //this will return if you have won the prize with a duplicated number. goes back to getValues
}
private boolean winLoseBetDuplicate() {
/*how this method works is we make a linked list.
use a advanced for loop and when we encounter
a hit, we remove the number from it.
if there is still a number in the linkedlist of
player number it is a lose. we still have digits as a linked list. */
//
boolean won = false;
boolean match;
for (int digitsnumbers : digits) {
System.out.println("Checking the number: " + digitsnumbers);
for (int digits2numbers : digits2) {
if (digitsnumbers == digits2numbers) {
digits.remove(digits.indexOf(digitsnumbers));
digits2.remove(digits2.indexOf(digits2numbers));
System.out.println("we found a duplicated numer match. Removing from choosing. ");
System.out.println(digits);
System.out.println(digits2);
match = true;
} else {
match = false;
}
}
}
if (digits.size() > 0) {
won = false;
} else {
won = true;
}
return won;
}
private boolean winLostBetNonDuplicate() {
boolean won;
for (int digitsnumbers : digits) {
for (int digits2numbers : digits2) {
if (digitsnumbers == digits2numbers) {
digits2.remove(digits.indexOf(digits2numbers));
digits.remove(digits.indexOf(digitsnumbers));
break;
}
}
}
if (digits.size() > 0) {
won = false;
} else {
won = true;
}
return won;
}
}

Tic Tac Toe: All states get returned as best moves

I am working on building the game of Tic Tac Toe. Please find below the description of the classes used.
Game:: The main class. This class will initiate the multiplayer mode.
Board: This class sets the board configurations.
Computer: This class comprises of the minimax algorithm.
BoardState: This class comprises of the Board Object, along with the last x and y coordinates which were used to generate the board
configuration.
State: This class comprises of the score and the x and y coordinates that that will lead to that score in the game.
Context
Working on DFS here.
Exploring the whole tree works fine.
The game is set in such a way that the user is prompted to play first.
The user will put x and y co ordinates in the game.Coordinates are between 0 to 2. The Play of the player is marked as 1
The response from the computer is 2, which the algorithm decides. Th algorithm will determine the best possible coordinates to play and then play 2 on the position.
One of the winning configurations for Player is :
Player wins through diagonal
121
112
221
One of the winning configuration for AI is:
222
121
211
AI wins Horizontal
Problem
All the states give the max score.
Essentially, when you start the game in your system, you will find that since all states are given the max score, the computer looks to play sequentially.
As in if you put at (00), the computer plays at (01) and if you play at (02), the computer will play at (10)
I have been trying to debug it for a long time now. I believe, I may be messing up something with the scoring function. Or there could be a bug in the base recursion steps. Moreover, I don't think immutability among classes could cause problems as I have been recreating/creating new objects everywhere.
I understand, this might not be the best context I could give, but it would be a great help if you guys could help me figure out where exactly is it going wrong and what could I do to fix it. Answers through code/logic used would be highly appreciated. Thanks!
Game Class
import java.io.Console;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Game {
static int player1 = 1;
static int player2 = 2;
public static void main(String[] args) {
// TODO Auto-generated method stub
//
//PLays Game
playGame();
/* Test Use Case
ArrayList<Board> ar = new ArrayList<Board>();
Board b = new Board();
b.setVal(0,0,1);
b.setVal(0,1,1);
b.setVal(0,2,2);
b.setVal(1,0,2);
b.setVal(1,1,2);
b.setVal(2,0,1);
b.setVal(2,1,1);
b.display();
Computer comp = new Computer();
State x = comp.getMoves(b, 2);
*/
}
private static void playGame() {
// TODO Auto-generated method stub
Board b = new Board();
Computer comp = new Computer();
while(true)
{
if(b.isBoardFull())
{
System.out.println("Game Drawn");
break;
}
b.display();
int[] pmove = getPlayerMove(b);
b.setVal(pmove[0],pmove[1], player1);
if(b.isVictoriousConfig(player1))
{
System.out.println("Player 1 Wins");
break;
}
if(b.isBoardFull())
{
System.out.println("Game Drawn");
break;
}
b.display();
System.out.println("Computer Moves");
/*For Random Play
* int[] cmove = comp.computeMove(b);
*/
Computer compu = new Computer();
State s = compu.getMoves(b, 2);
int[] cmove = new int[2];
cmove[0] = s.x;
cmove[1] = s.y;
b.setVal(cmove[0],cmove[1], player2);
if(b.isVictoriousConfig(player2))
{
System.out.println("Computer Wins");
break;
}
}
System.out.println("Game Over");
}
//Gets Player Move. Basic Checks on whether the move is a valud move or not.
private static int[] getPlayerMove(Board b) {
// TODO Auto-generated method stub
int[] playerMove = new int[2];
System.out.println("You Play");
while(true)
{
#SuppressWarnings("resource")
Scanner reader = new Scanner(System.in); // Reading from System.in
System.out.println("Enter X Position: ");
while(true)
{
playerMove[0] = reader.nextInt(); // Scans the next token of the input as an int.
if(playerMove[0] >2)
{
System.out.println("Incorrect Position");
}
else
{
break;
}
}
System.out.println("Enter Y Position: ");
while(true)
{
playerMove[1] = reader.nextInt(); // Scans the next token of the input as an int.
if(playerMove[1] >2)
{
System.out.println("Incorrect Position");
}
else
{
break;
}
}
System.out.println("You entered positions: X is " + playerMove[0] + " and Y is " + playerMove[1] );
if(!b.isPosOccupied(playerMove[0], playerMove[1]))
{
break;
}
System.out.println("Incorrect Move. PLease try again");
}
return playerMove;
}
}
Board Class
import java.util.Arrays;
public class Board {
// Defines Board Configuration
private final int[][] data ;
public Board()
{
data = new int[3][3];
for(int i=0;i<data.length;i++ )
{
for(int j=0;j<data.length;j++ )
{
data[i][j] = 0;
}
}
}
//Displays Current State of the board
public void display()
{
System.out.println("Board");
for(int i = 0; i< data.length;i++)
{
for(int j = 0; j< data.length;j++)
{
System.out.print(data[i][j] + " ");
}
System.out.println();
}
}
// Gets the Value on a specific board configuration
public int getVal(int i, int j)
{
return data[i][j];
}
//Sets the value to a particular board location
public void setVal(int i, int j,int val)
{
data[i][j] = val;
}
public boolean isBoardFull()
{
for(int i=0;i< data.length ; i++)
{
for(int j=0;j< data.length ;j++)
{
if(data[i][j] == 0)
return false;
}
}
return true;
}
public boolean isVictoriousConfig(int player)
{
//Noting down victory rules
//Horizontal Victory
if ( (data[0][0] != 0) && ((data[0][0] == data [0][1]) && (data[0][1] == data [0][2]) && (data[0][2] == player)))
return true;
if ((data[1][0] != 0) && ((data[1][0] == data [1][1]) && (data[1][1] == data [1][2]) && (data[1][2] == player)))
return true;
if ((data[2][0] != 0) && ((data[2][0] == data [2][1]) && (data[2][1] == data [2][2]) && (data[2][2] == player)))
return true;
//Vertical Victory
if ( (data[0][0] != 0) && ((data[0][0] == data [1][0]) && (data[1][0] == data [2][0]) && (data[2][0] == player)))
return true;
if ((data[0][1] != 0) && ((data[0][1] == data [1][1]) && (data[1][1] == data [2][1]) && (data[2][1] == player)))
return true;
if ((data[0][2] != 0) && ((data[0][2] == data [1][2]) && (data[1][2] == data [2][2]) && (data[2][2] == player)))
return true;
//Diagonal Victory
if ( (data[0][0] != 0) && ((data[0][0] == data [1][1]) && (data[1][1] == data [2][2]) && (data[2][2] == player)))
return true;
if ( (data[0][2] != 0) && ((data[0][2] == data [1][1]) && (data[1][1] == data [2][0]) && (data[2][0] == player)))
return true;
//If none of the victory rules are met. No one has won just yet ;)
return false;
}
public boolean isPosOccupied(int i, int j)
{
if(data[i][j] != 0)
{
return true;
}
return false;
}
public Board(int[][] x)
{
this.data = Arrays.copyOf(x, x.length);
}
}
Board State
public class BoardState {
final Board br;
final int x ;
final int y;
public BoardState(Board b, int posX, int posY)
{
br = b;
x = posX;
y = posY;
}
}
State
public class State {
final int s;
final int x;
final int y;
public State(int score, int posX, int posY)
{
s = score;
x = posX;
y = posY;
}
}
Computer
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;
public class Computer {
int[] pos = new int[2];
static int player2 = 2;
static int player1 = 1;
ArrayList<Board> win =new ArrayList<Board>();
ArrayList<Board> loose =new ArrayList<Board>();
ArrayList<Board> draw =new ArrayList<Board>();
public Computer()
{
}
public int[] computeMove(Board b)
{
while(true)
{
Random randX = new Random();
Random randY = new Random();
pos[0] = randX.nextInt(3);
pos[1] = randY.nextInt(3);
if(!b.isPosOccupied(pos[0], pos[1]))
{
return pos;
}
}
}
public State getMoves(Board b,int p)
{
//System.out.println("test2");
int x = 0;
int y = 0;
BoardState bs = new BoardState(b,0,0);
//System.out.println("test");
State s = computeMoveAI(bs,p);
//System.out.println("Sore : X : Y" + s.s + s.x + s.y);
return s;
}
private State computeMoveAI(BoardState b, int p) {
// TODO Auto-generated method stub
//System.out.println("Hello");
int[][]sArray = new int[3][3];
for(int i1 =0;i1<3;i1++)
{
for(int j1=0;j1<3;j1++)
{
sArray[i1][j1] = b.br.getVal(i1, j1);
}
}
Board d = new Board(sArray);
//System.out.println("d is ");
//d.display();
//System.out.println("p is "+ p);
int xvalue= b.x;
int yvalue = b.y;
BoardState bs = new BoardState(d,xvalue,yvalue);
if(getConfigScore(d,p) == 1)
{
//System.out.println("Winning Config");
//System.out.println("X is " + b.x + " Y is " + b.y);
// b.br.display();
State s = new State(-1,bs.x,bs.y);
return s;
}
else if (getConfigScore(d,p) == -1)
{
//System.out.println("LooseConfig");
State s = new State(1,bs.x,bs.y);
//System.out.println("Coordinates are "+bs.x + bs.y+ " for " + p);
return s;
}
else if(bs.br.isBoardFull())
{
//System.out.println("Board is full");
State s = new State(0,bs.x,bs.y);
//System.out.println("score " + s.s + "x "+ s.x + "y "+ s.y);
return s;
}
else
{
//Get Turn
//System.out.println("In else condiyion");
int turn;
if(p == 2)
{
turn = 1;
}else
{
turn = 2;
}
ArrayList<BoardState> brr = new ArrayList<BoardState>();
ArrayList<State> st = new ArrayList<State>();
brr = getAllStates(d,p);
for(int k=0;k<brr.size();k++)
{
//System.out.println("Goes in " + "turn " + turn);
//brr.get(k).br.display();
int xxxxx = computeMoveAI(brr.get(k),turn).s;
State temp = new State(xxxxx,brr.get(k).x,brr.get(k).y);
st.add(temp);
}
//Find all Nodes.
//Go to First Node and proceed with recursion.
//System.out.println("Displaying boards");
for(int i=0;i<brr.size();i++)
{
//brr.get(i).br.display();
//System.out.println(brr.get(i).x + " " + brr.get(i).y);
}
//System.out.println("Board configs are");
for(int i=0;i<st.size();i++)
{
//System.out.println(st.get(i).x + " " + st.get(i).y + " and score " + st.get(i).s);
}
//System.out.println("xvalue" + xvalue);
//System.out.println("yvalue" + yvalue);
//System.out.println("Board was");
//d.display();
//System.out.println("Coming to scores");
//System.out.println(" p is "+ p);
if(p == 2)
{
//System.out.println("Size of first response" + st.size());
//System.out.println("Returns Max");
return max(st);
}
else
{
//System.out.println("The last");
return min(st);
}
}
}
private State min(ArrayList<State> st) {
// TODO Auto-generated method stub
ArrayList<State> st1= new ArrayList<State>();
st1= st;
int min = st.get(0).s;
//System.out.println("Min score is " + min);
for(int i=1;i<st1.size();i++)
{
if(min > st1.get(i).s)
{
min = st1.get(i).s;
//System.out.println("Min is");
//System.out.println(min);
//System.out.println("Min" + min);
State s = new State(min,st1.get(i).x,st1.get(i).y);
return s;
}
}
State s = new State(st1.get(0).s,st1.get(0).x,st1.get(0).y);
//System.out.println("Max" + st1.get(0).s);
//System.out.println("Exits Min");
//System.out.println("Min Score" + st1.get(0).s + " x" + st1.get(0).x + "y " + st1.get(0).y);
return s;
}
private State max(ArrayList<State> st) {
// TODO Auto-generated method stub
//System.out.println("Size of first response in funciton is " + st.size());
ArrayList<State> st1= new ArrayList<State>();
st1 = st;
int max = st1.get(0).s;
for(int i=0;i<st1.size();i++)
{
// System.out.println(i+1 + " config is: " + "X:" + st1.get(i).x + "Y:" + st1.get(i).y + " with score " + st1.get(i).s);
}
for(int i=1;i<st1.size();i++)
{
//.out.println("Next Item " + i + st.get(i).s + "Coordinates X"+ st.get(i).x +"Coordinates Y"+ st.get(i).y );
if(max < st1.get(i).s)
{
max = st1.get(i).s;
//System.out.println("Max" + max);
//System.out.println("Max is");
//System.out.println(max);
State s = new State(max,st1.get(i).x,st1.get(i).y);
//System.out.println("Max Score returned" + s.s);
//System.out.println("Returned");
return s;
}
}
State s = new State(st1.get(0).s,st1.get(0).x,st1.get(0).y);
//System.out.println("Max" + st1.get(0).s);
//System.out.println("Max is outer");
//System.out.println(st.get(0).s);
return s;
}
//Basic brain Behind Min Max algorithm
public int getConfigScore(Board b,int p)
{
int score;
int turn ;
int opponent;
if(p == player1)
{
turn = p;
opponent = player2;
}
else
{
turn = player2;
opponent = player1;
}
int[][]sArray = new int[3][3];
for(int i1 =0;i1<3;i1++)
{
for(int j1=0;j1<3;j1++)
{
sArray[i1][j1] = b.getVal(i1, j1);
}
}
Board d = new Board(sArray);
//System.out.println("s arrasy is ");
//d.display();
//System.out.println("turn is " + turn);
if(d.isVictoriousConfig(turn))
{
score = 1;
}
else if(d.isVictoriousConfig(opponent))
{
score = -1;
}
else
{
score = 0;
}
return score;
}
public static ArrayList<BoardState> getAllStates(Board b, int player)
{
ArrayList<BoardState> arr = new ArrayList<BoardState>();
int[][]s1 = new int[3][3];
for(int i1 =0;i1<3;i1++)
{
for(int j1=0;j1<3;j1++)
{
s1[i1][j1] = b.getVal(i1, j1);
}
}
Board d = new Board(s1);
for(int i = 0;i <3; i ++)
{
for (int j=0;j<3;j++)
{
if(!d.isPosOccupied(i, j))
{
int previousState = d.getVal(i, j);
int[][]s = new int[3][3];
for(int i1 =0;i1<3;i1++)
{
for(int j1=0;j1<3;j1++)
{
s[i1][j1] = d.getVal(i1, j1);
}
}
s[i][j] = player;
Board d1 = new Board(s);
BoardState bs = new BoardState(d1,i,j);
arr.add(bs);
}
}
}
return arr;
}
}
This is the output of the test case in the Game class:
Board
1 1 2
2 2 0
1 1 0
Score : X : Y -> 1: 1: 2
The solution here is score:1 for x:1, y:2. It looks correct.
But again, you could say since it is moving sequentially, and since position (1,2) will come before (2,2), it gets the right coordinate.
I understand that this may be huge lines of code to figure out the problem. But
computemoveAI(), getConfigScore() could be the functions to look out for. Also I do not want to bias your thoughts with where I think the problem could as sometimes, we look somewhere , but the problem lies elsewhere.!!

Why does this message print extra times (more than I want it to print)?

import java.util.ArrayList;
import java.lang.Math;
public class War {
ArrayList deck = new ArrayList(0);
ArrayList player1 = new ArrayList(0);
ArrayList player2 = new ArrayList(0);
int sum1 = 0;
int sum2 = 0;
int count = 0;
private void setup ()
{
for (int x = 1; x <= 13; x++)
{
for (int y = 1; y <= 4; y++)
{
deck.add(x);
}
}
while (deck.size() > 26)
{
double x = Math.random() * deck.size();
int y = (int) x;
player1.add(deck.remove(y));
}
while (deck.size() > 0)
{
double x = Math.random() * deck.size();
int y = (int) x;
player2.add(deck.remove(y));
}
for (int x = 0; x < 26; x++)
{
sum1 += (int) player1.get(x);
sum2 += (int) player2.get(x);
}
System.out.println("Player 1's starting power is " + sum1 + ".");
System.out.println();
System.out.println("Player 2's starting power is " + sum2 + ".");
System.out.println();
if (sum1 == sum2)
{
System.out.println("The two player's starting powers are equal! This'll be a good one, folks!");
}
}
public void play ()
{
if (hasSomeoneWon() || count == 0)
{
setup();
}
while (!player1.isEmpty() && !player2.isEmpty())
{
int a = (int) player1.get(0);
int b = (int) player2.get(0);
if (a > b)
{
player1.add(player1.remove(0)); // The winner's card is re-added to his deck before
player1.add(player2.remove(0)); // the loser's is added to the winner's deck.
}
if (a < b)
{
player2.add(player2.remove(0));
player2.add(player1.remove(0));
}
if (a == b)
{
war();
}
}
victory();
}
private void war ()
{
ArrayList temp1 = new ArrayList(0);
ArrayList temp2 = new ArrayList(0);
temp1.add(player1.remove(0));
temp2.add(player2.remove(0));
int x = 0;
while (!(player1.isEmpty() || player2.isEmpty()) && x < 3)
{
temp1.add(player1.remove(0));
temp2.add(player2.remove(0));
x++;
}
int a = (int) temp1.get(temp1.size() - 1);
int b = (int) temp2.get(temp2.size() - 1);
if (a == b)
{
if (temp1.size() != temp2.size())
{
if (temp1.size() > temp2.size())
{
while (!temp1.isEmpty())
{
player1.add(temp1.remove(0));
}
while (!temp2.isEmpty())
{
player1.add(temp2.remove(0));
}
}
else
{
while (!temp2.isEmpty())
{
player2.add(temp2.remove(0));
}
while (!temp1.isEmpty())
{
player2.add(temp1.remove(0));
}
}
}
else
{
if (player1.isEmpty() || player2.isEmpty())
{
if (player1.isEmpty())
{
while (!temp2.isEmpty())
{
player2.add(temp2.remove(0));
}
while (!temp1.isEmpty())
{
player2.add(temp1.remove(0));
}
}
else
{
while (!temp1.isEmpty())
{
player1.add(temp1.remove(0));
}
while (!temp2.isEmpty())
{
player1.add(temp2.remove(0));
}
}
}
else
{
war();
}
}
}
else
{
if (a > b)
{
while (!temp1.isEmpty())
{
player1.add(temp1.remove(0));
}
while (!temp2.isEmpty())
{
player1.add(temp2.remove(0));
}
}
else
{
while (!temp2.isEmpty())
{
player2.add(temp2.remove(0));
}
while (!temp1.isEmpty())
{
player2.add(temp1.remove(0));
}
}
play();
}
}
private void victory ()
{
if (player1.isEmpty() && sum2 > sum1)
{
System.out.println("Player 2 has won!");
}
if (player1.isEmpty() && sum1 > sum2)
{
System.out.println("Upset! Player 2 has won!");
}
if (player2.isEmpty() && sum1 > sum2)
{
System.out.println("Player 1 has won!");
}
if (player2.isEmpty() && sum2 > sum1)
{
System.out.println("Upset! Player 1 has won!");
}
hasSomeoneWon();
}
private boolean hasSomeoneWon ()
{
if (player1.isEmpty() || player2.isEmpty())
{
count++;
return true;
}
return false;
}
}
Sorry for including all of my code, but I don't know which part is causing the extra printing.
This is the card game War. It's supposed to play out the game between two players on its own and then print the winner. Whenever I've played it, though, the victory message (whichever one gets printed) is printed a variable number of times. I'm guessing this has something to do with either where and how often I've included my calls to some of the methods OR the recursive call to war within the war() method.
My only experience with Java is an AP Computer Science class I took this school year, so I'm for sure a noob by the standards of everyone reading this.
In the war() method you are recursively calling war() and war() will eventually end by recalling play(). So there will be multiple instances executing play(). Eventually when the cards run out for one player all this instances will comeback as the stack is unwound and continue executing play(). And finally of course calling victory() and printing it multiple times (should be the amount of times war() was called).
So each war() may print out a player has won once it reached the bottom of the recursion. I don't think the call to play() in war() is necessary, it will go back to the play() method after it finishes the war() method anyway.

Categories

Resources