Problem in toString function in java (works with local variable) - java

i have a class in a java program where i am using a toString function to retrieve data. the toString checks a private function in the same class which returns a int value, for displaying different types of return messages.~
The problem is that if i use a local variable in the string function every turns out good, but if i check in the if statements directlly the private function, this function doesnt return any value.
private int computerTryHorizontalPlay() {
int repeatedMyValueCount = 0;
int repeatedYourValueCount = 0;
int[] myPositions = new int[3];
int[] yourPositions = new int[3];
for (int a = 0; a < 3; a++) {
int repeatedMyValue = 0;
int repeatedYourValue = 0;
int emptyFields = 0;
int[] emptyPosition = new int[2];
for (int b = 0; b < 3; b++) {
if (jogoGalo[a][b] == 'X') {
repeatedMyValue++;
} else if (jogoGalo[a][b] == 'O') {
repeatedYourValue++;
}
if (jogoGalo[a][b] == '-') {
emptyPosition[0] = a;
emptyPosition[1] = b;
emptyFields++;
}
}
if (repeatedMyValue == 3 || repeatedYourValue == 3) {
return 3;
} else {
if (emptyFields == 1) {
if (repeatedMyValue == 2) {
repeatedMyValueCount++;
myPositions[repeatedMyValueCount - 1] = emptyPosition[0];
myPositions[repeatedMyValueCount] = emptyPosition[1];
} else if (repeatedYourValue == 2) {
repeatedYourValueCount++;
yourPositions[repeatedYourValueCount - 1] = emptyPosition[0];
yourPositions[repeatedYourValueCount] = emptyPosition[1];
}
}
}
}
if (repeatedMyValueCount > 0) {
jogoGalo[myPositions[0]][myPositions[1]] = 'X';
return 2;
} else if (repeatedYourValueCount > 0) {
jogoGalo[yourPositions[0]][yourPositions[1]] = 'X';
return 1;
}
return 0;
}
This doesn´t work!
public String toString() {
if(computerTryHorizontalPlay() == 3) {
return "The game has already ended!";
}
else if(computerTryHorizontalPlay() == 2) {
return "Computer won!";
}
else if(computerTryHorizontalPlay() == 1) {
return "Computer defendeu!";
}
return null;
}
This works!
public String toString() {
int horizontalFunctionValue = computerTryHorizontalPlay();
if(horizontalFunctionValue == 3) {
return "The game has already ended!";
}
else if(horizontalFunctionValue == 2) {
return "Computer won!";
}
else if(horizontalFunctionValue == 1) {
return "Computer defendeu!";
}
return null;
}
}

toString() must be a read-only method, i.e. it is not allowed to have side-effects like changing the state of the object. Since computerTryHorizontalPlay() is a state-changing method, you are not allowed to call it from toString().
Since the only state-change happens in the last if statement, you can change the code to not execute the play when called from toString(), like this:
private int computerTryHorizontalPlay() {
return computerTryHorizontalPlay(true);
}
private int computerTryHorizontalPlay(boolean doMove) {
// lots of code here
if (repeatedMyValueCount > 0) {
if (doMove)
jogoGalo[myPositions[0]][myPositions[1]] = 'X';
return 2;
} else if (repeatedYourValueCount > 0) {
if (doMove)
jogoGalo[yourPositions[0]][yourPositions[1]] = 'X';
return 1;
}
return 0;
}
public String toString() {
if(computerTryHorizontalPlay(false) == 3) {
return "The game has already ended!";
}
else if(computerTryHorizontalPlay(false) == 2) {
return "Computer won!";
}
else if(computerTryHorizontalPlay(false) == 1) {
return "Computer defeated!";
}
return null;
}

Related

Java Treemap comparator ignoring get when key is different instances

The issue I'm having is that the get method throws NPE when the key is a different instance than the one in the TreeMap.
public class ConjuntDocuments {
private TreeMap<Capcalera, Document> almacen;
private ArrayList<Pair_plantilla> plantilla;
ConjuntDocuments() {
almacen = new TreeMap<Capcalera, Document>(new CustomComparator());
plantilla = new ArrayList<Pair_plantilla>();
}
private static class CustomComparator implements Comparator<Capcalera> {
#Override
public int compare(Capcalera c1, Capcalera c2) {
int ax = c1.get_tit().get_nom().compareFrase(c2.get_tit().get_nom());
if (ax < 0) return -1;
else if (ax > 0) return 1;
//titols iguals
else {
ax = c1.get_au().get_nom().compareFrase(c2.get_au().get_nom());
if (ax < 0) return -1;
else if (ax > 0) return 1;
}
//titols i autors iguals
return 0;
}
}
compareFrase compares ArrayLists(Paraula) -> Frase, Paraula is like a string, get_chars returns a String.
public int compareFrase(Frase f) {
for(int i=0; i<min(this.get_size(), f.get_size()); ++i){
int aux = this.get_paraula(i).get_chars().compareTo(f.get_paraula(i).get_chars());
if(aux < 0) return -1;
else if(aux > 0) return 1;
}
if(this.get_size() < f.get_size()) return -1;
else if(this.get_size() > f.get_size()) return 1;
return 0;
}
Titol and autor are Frases -> ArrayList(Paraula)
public class Capcalera {
private Titol tit;
private Autor au;
So after trying to figure this out, I've realised that the get method only works if the key referenced is the same instance than the one mapped, right after putting an entry (almacen.put(capcalera,document) , if I try to call almacen.get(Capcalera) it will return the value correctly, but if I create a new Capcalera, it will throw NPE. I'm assuming there is an issue with the comparator but since the entries are sorted correctly I can't figure out what is wrong.
EDIT:
I've implemented .equals and .hashcode from Capcalera, but I might be doing something wrong because .get from the Treemap still throws NPE.
#Override
public int hashCode() {
int hashTitol = tit != null ? tit.hashCode() : 0;
int hashAutor = au != null ? au.hashCode() : 0;
return (hashTitol + hashAutor) * hashAutor + hashTitol;
}
#Override
public boolean equals(Object other) {
if (other instanceof Capcalera) {
Capcalera otherCapcalera = (Capcalera) other;
return
(( this.get_tit().get_nom().equalsFrase(otherCapcalera.get_tit().get_nom()) ||
( this.get_tit() != null && otherCapcalera.get_tit() != null &&
this.get_tit().get_nom().equalsFrase(otherCapcalera.get_tit().get_nom()) )) &&
( this.get_au().get_nom().equalsFrase(otherCapcalera.get_au().get_nom()) ||
( this.get_au() != null && otherCapcalera.get_au() != null &&
this.get_au().get_nom().equalsFrase(otherCapcalera.get_au().get_nom()))) );
}
return false;
}
equalsFrase returns true if Titol/Autor are equals
public boolean equalsFrase(Frase f) {
for(int i=0; i<min(this.get_size(), f.get_size()); ++i){
int aux = this.get_paraula(i).get_chars().compareTo(f.get_paraula(i).get_chars());
if(aux < 0) return false;
else if(aux > 0) return false;
}
if(this.get_size() < f.get_size()) return false;
else if(this.get_size() > f.get_size()) return false;
return true;
}

Better way to call my methods in the main method for Connect Four

I'm building a program to play Connect Four. I have all my methods done and I'm just building my main method up to actually play the game. Is there a more efficient way to use my Play class than manually inputting the code the way I am? I was fine with doing this until I realized that I don't know how to find a winner doing it this way. Is there a loop I can use that'll properly go through my methods and make the main class tidier and more efficient?
Here is my code:
import java.util.Scanner;
public class Play {
public static void main(String[]args){
Scanner keyboard = new Scanner(System.in);
System.out.print("Welcome to Connect 4. Please enter your names. \nPlayer 1 Name: ");
String name1 = keyboard.nextLine();
System.out.print("Player 2 Name: ");
String name2 = keyboard.nextLine();
System.out.println(name1 + " - you have red chips \"R\" and you go first.");
Connect4Board game = new Connect4Board(6,7);
System.out.print(game);
System.out.println("Enter a column between 1-7: ");
int column = keyboard.nextInt();
game.add(column, "R");
System.out.print(game);
System.out.print(name2 + " - you have yellow chips \"Y\" and you go next.");
System.out.println("Enter a column between 1-7: ");
column = keyboard.nextInt();
game.add(column, "Y");
System.out.print(game);
}
}
class Chip { //Chip class determines the color of the chip
//Instance Variables
private String colour;
public Chip (String c) { //Constructor
colour = c;
}
public String getColour(){ //Get Method
return colour;
}
public void setColour(String c){ //Set Method
c = colour;
}
public boolean equals(Chip c){ //Checks if two colors are the same
return this.colour == c.getColour();
}
public String toString(){ //Converts to String
return colour;
}
}
class Board { //Creates a board with x rows and x columns.
//Instance Variables
private int rows;
private int cols;
public Board (int r, int c){ //Constructor
rows = r;
cols = c;
}
public int getRows(){ //Get Methods
return rows;
}
public int getCols(){
return cols;
}
public void setRows(int r){ //Set Methods
r = rows;
}
public void setCols(int c){
c = cols;
}
}
class Connect4Board extends Board {
//Instance Variable
private Chip [][] board;
private String colourOfWin = "";
public Connect4Board(int r, int c){
super(r, c);
board = new Chip[r][c];
}
public Chip[][] getBoard(){
return board;
}
public void setBoard(int r,int c){
setRows(r);
setCols(c);
}
public boolean add(int cols, String colour){
boolean result = true;
int counter = 0;
boolean testPlacement = false;
if(cols>=0 && cols<=6){
}
else
result = false;
if (board[5][cols] != null)
result = false;
for(int row = 5; row >= 0 && testPlacement == false; row--){
if(board[row][cols]==null){
counter += 1;
}
else
testPlacement = true;
}
if(result == true){
board[6-counter][cols] = new Chip(colour);
//
}
return result;
}
public String winType(){
String result;
if(rowWinner()){
result = "Row Winner";
}
else if(columnWinner()){
result = "Column Winner";
}
else if(rightDiagonalWinner() || leftDiagonalWinner()){
result = "Diagonal Winner";
}
else{
result = "No winner yet.";
}
return result;
}
public boolean rowWinner(){
boolean result = false;
boolean result1 = true; //Test the equals to see if true
for(int row=0; row<6 && result == false; row++){ //Nested for loops to proccess array. Row
for(int cols=0; cols<4 && result == false; cols++){ //Column
for(int win=0; win<4; win++){ //Check win
if(board[row][cols] != null && board[row][cols+win] != null){
if(board[row][cols+win].equals(board[row][cols])&& result1 == true ){ //result1 tests to see if the equals is true
}
else
result1 = false;
}
else
result1 = false;
}
if(result == true)
colourOfWin = board[row][cols].getColour();
result = result1;
}
}
return result;
}
public boolean columnWinner(){
boolean result = false;
boolean result1 = true; //Test the equals to see if true
for(int row=0; row<3 && result == false; row++){ //Nested for loops to proccess array. Row
for(int cols=0; cols<7 && result == false; cols++){ //Column
for(int win=0; win<4; win++){ //Check win
if(board[row][cols] != null && board[row+win][cols] != null){
if(board[row+win][cols].equals(board[row][cols])&& result1 == true ){ //result1 tests to see if the equals is true
}
else
result1 = false;
}
else
result1 = false;
}
if(result == true)
colourOfWin = board[row][cols].getColour();
result = result1;
}
}
return result;
}
public boolean rightDiagonalWinner(){
boolean result = false;
boolean result1 = true; //Test the equals to see if true
for(int row=0; row<3 && result == false; row++){ //Nested for loops to proccess array. Row
for(int cols=0; cols<4 && result == false; cols++){ //Column
for(int win=0; win<4; win++){ //Check win
if(board[row][cols] != null && board[row+win][cols+win] != null){
if(board[row+win][cols+win].equals(board[row][cols])&& result1 == true ){ //result1 tests to see if the equals is true
}
else
result1 = false;
}
else
result1 = false;
}
if(result == true)
colourOfWin = board[row][cols].getColour();
result = result1;
}
}
return result;
}
public boolean leftDiagonalWinner(){
boolean result = false;
boolean result1 = true; //Test the equals to see if true
for(int row=0; row<3 && result == false; row++){ //Nested for loops to proccess array. Row
for(int cols=6; cols<2 && result == false; cols--){ //Column
for(int win=0; win<4; win++){ //Check win
if(board[row][cols] != null && board[row+win][cols-win] != null){
if(board[row+win][cols-win].equals(board[row][cols])&& result1 == true ){ //result1 tests to see if the equals is true
}
else
result1 = false;
}
else
result1 = false;
}
if(result == true)
colourOfWin = board[row][cols].getColour();
result = result1;
}
}
return result;
}
public boolean winner(){
return rowWinner() || columnWinner() || rightDiagonalWinner() || leftDiagonalWinner();
}
public String toString(){
String b;
b="\tCol.\n";
for (int j=0;j<7;j++){
b=b+"\t"+(j+1);
}
b=b+"\n";
for (int i=0;i<6;i++){
b=b+(i+1)+"\t";
for(int j=0;j<7;j++){
if(board[5-i][j]==null){
b=b+" \t";
}
else{
b=b+board[5-i][j].getColour()+"\t";
}
}
b=b+"\n\n";
}
return b;
}
}

NullPointerException even when variables are not null

I'm currently designing a program to simulate an airport. I ran into a problem and I've already tried my best to figure out the problem and posting to this site was my final resort.
It keeps giving me a "Exception in thread "main" java.lang.NullPointerException at AirportApp.main(AirportApp.java:119)" which is under the //Landings section with the code
System.out.println(plane1.getCapacity());
The reason I did the print is to make sure plane1.getCapacity isn't a null. This is because when I tried the code below it
if(plane1.getCapacity() < 300);
it gave me the NullPointerException error. I did the print and it didn't return a null.
What I'm trying to do here is whenever a plane lands, it will be assigned to an empty gate. If the plane has a capacity of 300 or more, it will be assigned to the 4th or 5th gate only. The other planes can be assigned to any gate.
What I noticed was that the error happens only when the capacity is over 300.
I've already looked at my code over and over again making sure all variables were initialized and I still could not find anything wrong. Any help or hints will be greatly appreciated. Apologies for the messy code.
Main class.
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class AirportApp {
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
Random rn = new Random();
String [] flightNames = {"SQ", "MI", "TZ", "TR", "EK", "MO", "FC"};
int [] flightNum = {8421, 5361, 6342, 6135, 8424, 7424, 5435};
Queue landingRunway = new Queue(10);
Queue takeoffRunway = new Queue(10);
Queue planesQueue = new Queue(100);
Queue gatesQueue = new Queue(100);
ArrayList<Gate> allGates = new ArrayList();
for(int i = 1 ; i < 6 ; i++)
{
allGates.add(new Gate(i, 0, 0, true));
}
int minutes = 0;
int planesMissedTime = 0;
Boolean highWinds = null;
int tookOffPlanes = 0;
int smallCapPlanes = 0;
int largeCapPlanes = 0;
int landedPlanes = 0;
System.out.println("Please key in the number of minutes you want "
+ "the program to run: ");
int desiredMinutes = sc.nextInt();
while(minutes < desiredMinutes)
{
//Randomise wind warnings
int windRandom = rn.nextInt(2) + 1;
if(windRandom == 1)
{
highWinds = true;
}
if(windRandom == 2)
{
highWinds = false;
}
//Empty the gates
for(Gate c : allGates)
{
if(c.getAvailability() == false)
{
c.addMinInQueue(1);
if(c.getMinInQueue() == 15)
{
c.isAvailable();
}
}
}
//Every 2 minutes
if(minutes % 2 == 0)
{
//Randomise flight names and number
int index = rn.nextInt(flightNames.length);
int index1 = rn.nextInt(flightNum.length);
String name = flightNames[index];
int num = flightNum[index1];
//Randomise plane assignment
int planeDirection = rn.nextInt(2) + 1;
int planeCap = rn.nextInt(401) + 100;
//Arrival Planes
if(planeDirection == 1)
{
planesQueue.enqueue(new Plane(num, name, planeCap, 5 , 0 ));
System.out.println("A plane has been generated.");
}
//Departure Planes
if(planeDirection == 2)
{
planesQueue.enqueue(new Plane(num, name, planeCap, 0 , 5 ));
System.out.println("A plane has been generated.");
}
//Take-Offs
if(!takeoffRunway.isEmpty())
{
System.out.println("A plane has departed.");
Plane departPlane = (Plane) takeoffRunway.dequeue();
if (departPlane.getCapacity() < 300)
{
smallCapPlanes++;
}
tookOffPlanes++;
}
}
//Landings
if(minutes % 3 == 0 && !landingRunway.isEmpty())
{
System.out.println("A plane has landed.");
gatesQueue.enqueue(landingRunway.dequeue());
landedPlanes++;
loop1:
for(Gate e : allGates)
{
if(e.getAvailability() == true)
{
Plane plane1 = (Plane) gatesQueue.dequeue();
System.out.println(plane1.getCapacity());
if(plane1.getCapacity() < 300)
{
e.addNumOfPlanes(1);
e.setAvailability(false);
break loop1;
}
if(plane1.getCapacity() > 300)
{
largeCapPlanes++;
if(e.getGateId() == 4 || e.getGateId() == 5)
{
e.addNumOfPlanes(1);
e.setAvailability(false);
break loop1;
}
}
}
}
}
//Plane assigned to takeoff or landing queue
if(minutes % 5 == 0)
{
Plane item = (Plane) planesQueue.peek();
if(item.getArrivalTime() == 5 && landingRunway.isEmpty()
&& highWinds == false)
{
landingRunway.enqueue(planesQueue.dequeue());
System.out.println("A plane has been assigned to "
+ "the landing queue.");
}
else if(item.getDepartureTime() == 5 &&
takeoffRunway.isEmpty() && highWinds == false)
{
takeoffRunway.enqueue(planesQueue.dequeue());
System.out.println("A plane has been assigned to "
+ "the takeoff queue.");
}
else
{
planesMissedTime++;
}
}
minutes++;
}
Class 1
public class Plane
{
private int flightNo;
private String flightName;
private int capacity;
private int timeOfArrival;
private int timeOfDeparture;
private int delayTime;
public Plane(int flightNo, String flightName, int capacity,
int timeOfArrival, int timeOfDeparture)
{
this.flightNo = flightNo;
this.flightName = flightName;
this.capacity = capacity;
this.timeOfArrival = timeOfArrival;
this.timeOfDeparture = timeOfDeparture;
}
public void setFlightNum(int flightNo)
{
this.flightNo = flightNo;
}
public int getFlightNum()
{
return this.flightNo;
}
public void setFlightName(String flightName)
{
this.flightName = flightName;
}
public String getflightName()
{
return this.flightName;
}
public void addCapacity(int capacity)
{
this.capacity = capacity;
}
public int getCapacity()
{
return this.capacity;
}
public void setArrivalTime(int newArrivalTime)
{
this.timeOfArrival = newArrivalTime;
}
public int getArrivalTime()
{
return this.timeOfArrival;
}
public void setDepartureTime(int newDepartureTime)
{
this.timeOfDeparture = newDepartureTime;
}
public int getDepartureTime()
{
return this.timeOfDeparture;
}
}
Class 2
public class Gate
{
private int gateID;
private int numOfPlanes;
private int minInQueue;
private boolean availability;
public Gate(int id, int numPlanes, int minQueue, boolean available)
{
this.gateID = id;
this.numOfPlanes = numPlanes;
this.minInQueue = minQueue;
this.availability = available;
}
public int getGateId()
{
return this.gateID;
}
public void setGateId(int newID)
{
this.gateID = newID;
}
public int getNumOfPlanes()
{
return this.numOfPlanes;
}
public void addNumOfPlanes(int addNum)
{
this.numOfPlanes += addNum;
}
public int getMinInQueue()
{
return this.minInQueue;
}
public void setMinInQueue(int setMin)
{
this.minInQueue = 0;
}
public void addMinInQueue(int addMin)
{
this.minInQueue += addMin;
}
public boolean getAvailability()
{
return this.availability;
}
public void setAvailability(Boolean setAvailability)
{
this.availability = setAvailability;
}
public void isAvailable()
{
this.availability = true;
this.minInQueue = 0;
}
}
Queue class
class Queue
{
private int count;
private int front = 0;
private int rear = 0;
private Object [] items;
public Queue(int maxSize)
{
count = 0;
front = -1;
rear = -1;
items = new Object [maxSize];
}
public boolean enqueue (Object x)
{
if (count == items.length)
{
return false;
}
else
{
rear = (rear + 1) % items.length;
items[rear] = x;
if (count == 0)
{
front = 0;
}
count++;
return true;
}
}
public Object dequeue()
{
if (count == 0)
{
return null;
}
else
{
Object result = items[front];
front = (front + 1) % items.length;
count--;
if (count == 0)
{
front = -1;
rear = -1;
}
return result;
}
}
public int size()
{
return count;
}
public boolean isEmpty()
{
if (count == 0)
{
return true;
}
else
{
return false;
}
}
public Object peek()
{
if (count == 0)
{
return null;
}
else
{
return items[front];
}
}
}
The problem lies in the second if statement
if (plane1.getCapacity() > 300) {
largeCapPlanes++;
if (e.getGateId() == 4 || e.getGateId() == 5) {
e.addNumOfPlanes(1);
e.setAvailability(false);
break loop1;
}
}
You only break your loop if the gate is 4, or 5. So, if it is not gate 4 or 5, then you code will loop back to the next gate, grab another plane from the queue (which is empty and your plane1 is now null) and then try to get the capacity. And there you get your null pointer.
Note: Be careful nesting loops and if statements. This is where bugs enjoy living.
Happy Coding!
I ran the code and didn't get an error until I tried a large number for the time (1000). I'm assuming the error is with the Plane plane1 = (Plane) gatesQueue.dequeue(); section. I would throw some debug statements in there to see if for large n that the Queue is generated properly. if dequeue() returns null then plane1 will also be null
EDIT:
So I debugged it and confirmed that the issue is with your plane object in that loop. You enqueue your gates: gatesQueue.enqueue(landingRunway.dequeue()); then you run a loop: for(Gate e : allGates) and then you dequeue: Plane plane1 = (Plane) gatesQueue.dequeue();
If you dequeue more than what you enqueue you will return null. So you'll either have to change how you do your queue or put a check in that for-loop to check the size of your queue.
The reason you are seeing a number when you do your System.out.println() is because it is displaying that, returning to the top of the loop, and then trying to get the plane object again before you run the print again.

trouble with yahtzee in java

I have to create the yahtzee game and its methods like full house, small straight, big straight, 3 of kind, 4 of kind , and chance. Now this is what i have done so far and i would like to know if my methods are right and also i'm having a hard time trying to figure out how to check if its yahtzee , 3 of kind, 4 of kind , etc and this is in my main method. The program consists of seven rolls, where every roll can have up to two sub-rolls
static final int NUM_RERROLS_ = 2;
static final int NUM_OF_DICE = 5;
static final int NUM_ROLLS_ = 7;
static final int[] dice = new int[NUM_OF_DICE];
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
rollDice();
for (int i = 0; i < NUM_RERROLS_; i++) {
if (gotYatzee()) {
break;
}
System.out.println(diceToString());
askUser();
System.out.println("Which dice do you want to reroll: ");
secondReroll(convert(keyboard.nextLine()));
}
System.out.println(diceToString());
if (gotYatzee()) {
System.out.println("You got Yatzee & 50 points!");
} else if (largeStraight() == true) {
System.out.println("You got large straight");
} else {
System.out.println("Sorry no large straight");
}
if (smallStraight() == true) {
System.out.println("You got smallStraight");
} else {
System.out.println("Sorry no small straight");
}
if (fullHouse() == true) {
System.out.println("You got full house");
} else {
System.out.println("Sorry no full house");
}
{
System.out.println("SORRY NO YAHTZEE");
}
if (askUser() == false) {
if (largeStraight() == true) {
System.out.println("You got large straight");
} else {
System.out.println("Sorry no large straight");
}
if (smallStraight() == true) {
System.out.println("You got smallStraight");
} else {
System.out.println("Sorry no small straight");
}
if (fullHouse() == true) {
System.out.println("You got full house");
} else {
System.out.println("Sorry no full house");
}
}
}
public static void rollDice() {
for (int i = 0; i < NUM_OF_DICE; i++) {
dice[i] = randomValue();
}
}
public static int randomValue() {
return (int) (Math.random() * 6 + 1);
}
public static String diceToString() {
String dado = "Here are your dice: ";
for (int element : dice) {
dado = dado + element + " ";
}
return dado;
}
public static boolean gotYatzee() {
for (int element : dice) {
if (element != dice[0]) {
return false;
}
}
return true;
}
public static void secondReroll(int[] newValue) {
for (int element : newValue) {
dice[element - 1] = randomValue();
}
}
public static int[] convert(String s) {
StringTokenizer st = new StringTokenizer(s);
int[] a = new int[st.countTokens()];
int i = 0;
while (st.hasMoreTokens()) {
a[i++] = Integer.parseInt(st.nextToken());
}
return a;
}
public static boolean Chance() {
for (int element : dice) {
int i = 0;
if (element != dice[i]) {
i++;
return false;
}
}
return true;
}
public static boolean smallStraight() {
for (int i = 1; i <= NUM_OF_DICE; i++) {
boolean b = false;
for (int j = 0; j < NUM_OF_DICE; j++) {
b = b || (dice[j] == i);
}
if (!b) {
return false;
}
}
return true;
}
public static boolean largeStraight() {
int[] i = new int[5];
i = dice;
sortArray(i);
if (((i[0] == 1) && (i[1] == 2) && (i[2] == 3) && (i[3] == 4) && (i[4] == 5))
|| ((i[0] == 2) && (i[1] == 3) && (i[2] == 4) && (i[3] == 5) && (i[4] == 6))
|| ((i[1] == 1) && (i[2] == 2) && (i[3] == 3) && (i[4] == 4) && (i[5] == 5))
|| ((i[1] == 2) && (i[2] == 3) && (i[3] == 4) && (i[4] == 5) && (i[5] == 6))) {
return true;
} else {
return false;
}
}
public static boolean askUser() {
Scanner keyboard = new Scanner(System.in);
int a = 0;
String yes = "Yes";
String no = "No";
System.out.println("Do you want to reroll the dice again: Yes or No? ");
String userInput;
userInput = keyboard.next();
if (userInput.equals(yes)) {
System.out.println("ALRIGHTY!!");
return true;
} else if (userInput.equals(no)) {
}
return false;
}
public static boolean threeKind() {
int[] a = new int[5];
a = dice;
sortArray(a);
if ((((a[0] == a[1]) && (a[1] == a[2])) // Three of a Kind
|| ((a[1] == a[2]) && ((a[2] == a[3])
|| (((a[2] == a[3]) && (a[3] == a[4]))))))) {
return true;
} else {
return false;
}
}
/*public static boolean fourKind(int[] dice) {
}
*/
public static int[] sortArray(int[] numbers) {
int stop;
for (stop = 0; stop < numbers.length; stop++) {
for (int i = 0; i < numbers.length - 1; i++) {
if (numbers[i] > numbers[i + 1]) {
swap(numbers, i, i + 1);
}
}
}
return numbers;
}
public static void swap(int[] numbers, int pos1, int pos2) {
int temp = numbers[pos1];
numbers[pos1] = numbers[pos2];
numbers[pos2] = temp;
}
public static boolean fullHouse() {
int[] a = new int[5];
a = dice;
sortArray(a);
if ((((a[0] == a[1]) && (a[1] == a[2])) && // Three of a Kind
(a[3] == a[4]) && // Two of a Kind
(a[2] != a[3]))
|| ((a[0] == a[1]) && // Two of a Kind
((a[2] == a[3]) && (a[3] == a[4])) && // Three of a Kind
(a[1] != a[2]))) {
return true;
} else {
return false;
}
}
}
basically i want to figure out a way to check if its full house, 3 of kind, 4 of kind , etc
You have 6 dice after three rolls. Sort the array of user-retained dice after the 3 rolls.
Yahtzee: ((die[0] == die[4]) || (die[1] == die[5]))
4 of a kind: ((die[0] == die[3]) || (die[1] == die[4] || (die[2] == die[5]))
Small straight, 3 tests (x = 3,4,5): ((die[x] - die[x-3]) == 3)
Large straight, 2 tests (x = 4,5): ((die[x] - die[x-4]) == 4)
etc.
Chance: Up to the user, right?
Unless I'm missing something (I'm a little rusty on Yatzee), this should be fairly straightforward.

sorting collections with string elements in java

I have a collections...i wrote code to sort values using my own comparator
my comparator code is
private static class MatchComparator implements Comparator<xmlparse> {
#Override
public int compare(xmlparse object1, xmlparse object2) {
String match1 = object1.getMatchId();
String match2 = object2.getMatchId();
return match1.compareTo(match2);
}
}
I will call Collections.sort(list,new MatchComparator());
Everything is fine but my problem is the sorted list is wrong when i print it...
Input for list
Match19
Match7
Match12
Match46
Match32
output from the sorted list
Match12
Match19
Match32
Match46
Match7
my expected output is
Match7
Match12
Match19
Match32
Match46
to get the order you need, you could either prefix the 1 digit numbers with zero ( eg Match07 ) or you have to split the string in a prefix and a numeric part, and implement the sorting as numeric comparison
The problem is that String.compareTo(..) compares the words char by char.
If all string start with Match, then you can easily fix this with:
public int compare(xmlparse object1, xmlparse object2) {
String match1 = object1.getMatchId();
String match2 = object2.getMatchId();
return Integer.parseInt(match1.replace("Match"))
- Integer.parseInt(match2.replace("Match"));
}
In case they don't start all with Match, then you can use regex:
Integer.parseInt(object1.replaceAll("[a-zA-Z]+", ""));
Or
Integer.parseInt(object1.replaceAll("[\p{Alpha}\p{Punch}]+", ""));
And a final note - name your classes with uppercase, camelCase - i.e. XmlParse instead of xmlparse - that's what the convention dictates.
Implement a function and use it for comparison:
instead of
return match1.compareTo(match2);
use
return compareNatural(match1,match2);
Here is a function which does a natural comparison on strings:
private static int compareNatural(String s, String t, boolean caseSensitive) {
int sIndex = 0;
int tIndex = 0;
int sLength = s.length();
int tLength = t.length();
while (true) {
// both character indices are after a subword (or at zero)
// Check if one string is at end
if (sIndex == sLength && tIndex == tLength) {
return 0;
}
if (sIndex == sLength) {
return -1;
}
if (tIndex == tLength) {
return 1;
}
// Compare sub word
char sChar = s.charAt(sIndex);
char tChar = t.charAt(tIndex);
boolean sCharIsDigit = Character.isDigit(sChar);
boolean tCharIsDigit = Character.isDigit(tChar);
if (sCharIsDigit && tCharIsDigit) {
// Compare numbers
// skip leading 0s
int sLeadingZeroCount = 0;
while (sChar == '0') {
++sLeadingZeroCount;
++sIndex;
if (sIndex == sLength) {
break;
}
sChar = s.charAt(sIndex);
}
int tLeadingZeroCount = 0;
while (tChar == '0') {
++tLeadingZeroCount;
++tIndex;
if (tIndex == tLength) {
break;
}
tChar = t.charAt(tIndex);
}
boolean sAllZero = sIndex == sLength || !Character.isDigit(sChar);
boolean tAllZero = tIndex == tLength || !Character.isDigit(tChar);
if (sAllZero && tAllZero) {
continue;
}
if (sAllZero && !tAllZero) {
return -1;
}
if (tAllZero) {
return 1;
}
int diff = 0;
do {
if (diff == 0) {
diff = sChar - tChar;
}
++sIndex;
++tIndex;
if (sIndex == sLength && tIndex == tLength) {
return diff != 0 ? diff : sLeadingZeroCount - tLeadingZeroCount;
}
if (sIndex == sLength) {
if (diff == 0) {
return -1;
}
return Character.isDigit(t.charAt(tIndex)) ? -1 : diff;
}
if (tIndex == tLength) {
if (diff == 0) {
return 1;
}
return Character.isDigit(s.charAt(sIndex)) ? 1 : diff;
}
sChar = s.charAt(sIndex);
tChar = t.charAt(tIndex);
sCharIsDigit = Character.isDigit(sChar);
tCharIsDigit = Character.isDigit(tChar);
if (!sCharIsDigit && !tCharIsDigit) {
// both number sub words have the same length
if (diff != 0) {
return diff;
}
break;
}
if (!sCharIsDigit) {
return -1;
}
if (!tCharIsDigit) {
return 1;
}
} while (true);
} else {
// Compare words
// No collator specified. All characters should be ascii only. Compare character-by-character.
do {
if (sChar != tChar) {
if (caseSensitive) {
return sChar - tChar;
}
sChar = Character.toUpperCase(sChar);
tChar = Character.toUpperCase(tChar);
if (sChar != tChar) {
sChar = Character.toLowerCase(sChar);
tChar = Character.toLowerCase(tChar);
if (sChar != tChar) {
return sChar - tChar;
}
}
}
++sIndex;
++tIndex;
if (sIndex == sLength && tIndex == tLength) {
return 0;
}
if (sIndex == sLength) {
return -1;
}
if (tIndex == tLength) {
return 1;
}
sChar = s.charAt(sIndex);
tChar = t.charAt(tIndex);
sCharIsDigit = Character.isDigit(sChar);
tCharIsDigit = Character.isDigit(tChar);
} while (!sCharIsDigit && !tCharIsDigit);
}
}
}
a better one is here
The comparison is lexicographic and not numerical, that's your problem. In lexicoraphic ordering, 10 comes before 9.
See this question for open source implementation solutions. You can also implement your own string comparison, which shouldn't be that hard.
It seems that you expect not what the String.compareTo() really is. It performs so called lexicographical comarsion, but you try to compare it by number. You need to modify the code of your comparator.
#Override
public int compare(xmlparse object1, xmlparse object2) {
String match1 = object1.getMatchId();
String match2 = object2.getMatchId();
Long n1 = getNumber(match1);
Long n2 = getNumber(match2);
return n1.compareTo(n2);
}
where getNumber() extracts the last nuber from string "matchXX"

Categories