RockPaperScissors game using hashmap - java

I am working on a rock paper scissors game for my programming class and the professor wanted us to use a hash map to store the user's patterns and the times the pattern occurred in the hash map.
So I created a Pattern class that holds an array of values and in the Computer class I store it inside a hash map. The way I intended for the program to work is that the program will first generate a move based on the patterns in the hash map. If the map is empty then it would just generate a random move. Then after the user has made his move, his move will be put into an array to make a new pattern and the pattern will be saved to the hash map. If the pattern is already inside the map then the number of times it occurred will increase.
The predicted move is made by comparing the last three moves of the user with the patterns in the map and see which move will the user potentially throw next. So if the user last 4 moves were: R P S R then the program will take P S R and then add in R P S and see if those patterns are in the map. If they are, it will see which one is most likely to occur. Then if the user plays R next, the array will be updated into P S R R and the pattern continues.
So beginner mode is to start with an empty map and veteran is to load a previously saved map. However, I ran into some problems:
After I put the Pattern and times into the hash map, when I tried to iterate through it and see what patterns is it storing inside the map, I see that all patterns are the same and that does not suppose to happen. The pattern is suppose to be: R -> R P - > R P S (if the user throws rock, paper, scissors respectively) but now it just shows R P S -> R P S -> R P S. This can be seen in the getSize() in Computer.
I ran into a NullPointerException after the 4th move. The problem might be solved if I can solve the previous question but I have no idea why it happens.
I get a warning when I tried to read the map from a file so I was just wondering if the warning could potentially mess with the program.
Unchecked cast from Object to HashMap<Pattern, Integer>
Some help or pointers of what went wrong in my program would be greatly appreciated.
Computer:
import java.io.*;
import java.util.*;
public class Computer {
/**
* The hashmap that will holds the pattern and how many times it occured.
*/
private HashMap<Pattern, Integer> map;
/**
* Constructor
*/
public Computer() {
map = new HashMap<Pattern, Integer>();
}
/**
* Storing the pattern to the map.
*
* #param p
* The pattern that will be saved to the map.
*/
public void storePattern(Pattern p) {
Integer time = map.get(p);
// If time is null then the Pattern is not yet in the hashmap
if (time == null) {
map.put(p, 1);
} else {
map.put(p, time + 1);
}
}
/**
* Generating the computer's next move.
*
* #return The move that the computer will make.
*/
public char generateMove(Pattern user) {
int r = 0, p = 0, s = 0;
char returns = 'a';
if (!map.isEmpty()) {
char[] userPatts = user.getPattern();
char[] patts = userPatts.clone();
patts[patts.length - 1] = 'R';
Pattern testPatt = new Pattern(patts);
if (map.containsKey(testPatt))
r = map.get(patts);
patts[patts.length - 1] = 'P';
testPatt = new Pattern(patts);
if (map.containsKey(testPatt))
p = map.get(patts);
patts[patts.length - 1] = 'S';
testPatt = new Pattern(patts);
if (map.containsKey(testPatt))
s = map.get(patts);
if ((s - r) > 0 && (s - p) > 0)
return 'R';
if ((p - s) > 0 && (p - r) > 0)
return 'S';
if ((r - s) > 0 && (r - p) > 0)
return 'P';
if (s == r && r != 0)
return 'P';
if (s == p && s != 0)
return 'R';
if (r == p && p != 0)
return 'S';
}
// Throwing a random move
int max = (int) (Math.random() * 3) + 1;
if (max == 1)
returns = 'P';
else if (max == 2)
returns = 'S';
else if (max == 3)
returns = 'R';
return returns;
}
/**
* Loading the hashmap from a file.
*/
public void loadMap() {
File f = new File("HashMap.dat");
if (f.exists()) {
try {
ObjectInputStream in = new ObjectInputStream(
new FileInputStream(f));
map = (HashMap<Pattern, Integer>) in.readObject();
System.out.println("Successfully loaded.");
in.close();
} catch (IOException e) {
System.out.println("Error processing file.");
} catch (ClassNotFoundException e) {
System.out.println("Could not find class.");
}
}
}
/**
* Saving the hashmap to a file.
*/
public void saveMap() {
File f = new File("HashMap.dat");
try {
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream(f));
out.writeObject(map);
System.out.println("Map saved.");
out.close();
} catch (IOException e) {
System.out.println("Error processing file.");
}
}
public void getSize() {
System.out.println("Map size: " + map.size());
for (Map.Entry<Pattern, Integer> entry : map.entrySet()) {
Pattern b = entry.getKey();
char[] a = b.getPattern();
for (int i = 0; i < a.length; i++) {// Why a.length allows i to go
// from 0 to 3 if a.length == 4?
System.out.print(a[i] + " ");// Why are all the patterns the
// same?
}
System.out.println();
}
}
}
Pattern:
import java.io.Serializable;
import java.util.Arrays;
public class Pattern implements Serializable {
/**
* Array that holds the patterns.
*/
private char[] pattern;
/**
* Constructor.
*/
public Pattern(char[] patt) {
pattern = patt;
}
/**
* Getting the pattern array.
*
* #return The pattern array.
*/
public char[] getPattern() {
return pattern;
}
/**
* Override the hashCode().
*/
#Override
public int hashCode() {
return Arrays.hashCode(pattern);
}
/**
* Override the equals()
*/
#Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Pattern)) {
return false;
}
Pattern s = (Pattern) o;
return Arrays.equals(s.getPattern(), pattern);
}
}
Main:
import java.util.Scanner;
/**
* This program allows the user to play Rock Paper Scisors with a computer with
* a twist: The computer will try to predict the user's next move and try to
* beat it.
*
* #author:
*/
public class RockPaperScisors {
public static void main(String[] args) {
char computer = 'S';
int playerScore = 0, compScore = 0, tie = 0, full = 0;
char[] patt = new char[4];
Computer comp = new Computer();
boolean stop = false;
System.out
.println("Do you want to play veteran or beginner mode?\n1. Veteran\n2. Beginner");
int mode = input(2, 1);
if (mode == 1)
comp.loadMap();
comp.getSize();
while (!stop) {
// Generate computer's move.
computer = comp.generateMove(new Pattern(patt));
System.out.println("Enter R P S. Enter Q to quit.");
char a = input();
if (a == 'Q') {
stop = true;
break;
}
System.out.println("You threw: " + a);
if (full <= (patt.length - 1)) {
patt[full] = a;
full++;
} else {
for (int i = 0; i <= patt.length - 2; i++) {
patt[i] = patt[i + 1];
}
patt[patt.length - 1] = a;
}
for (int i = 0; i <= patt.length - 1; i++) {
System.out.print(patt[i]);
}
System.out.println();
// Store the new pattern
comp.storePattern(new Pattern(patt));
System.out.println("Computer plays: " + computer);
// Check for win or tie
if (a == computer) {
System.out.println("Tie.");
tie++;
} else {
if (a == 'R' && computer == 'P') {
System.out.println("Computer wins.");
compScore++;
}
if (a == 'R' && computer == 'S') {
System.out.println("Player wins.");
playerScore++;
}
if (a == 'P' && computer == 'S') {
System.out.println("Computer wins.");
compScore++;
}
if (a == 'P' && computer == 'R') {
System.out.println("Player wins.");
playerScore++;
}
if (a == 'S' && computer == 'R') {
System.out.println("Computer wins.");
compScore++;
}
if (a == 'S' && computer == 'P') {
System.out.println("Player wins.");
playerScore++;
}
}
// Saving the map
comp.saveMap();
comp.getSize();
System.out.println("Your score: " + playerScore + "\tTie: " + tie
+ "\tComputer score: " + compScore);
}
System.out.println("Thank you for playing.");
}
public static int input(int upper, int lower) {
Scanner in = new Scanner(System.in);
boolean valid = false;
int validInt = 0;
while (!valid) {
if (in.hasNextInt()) {
validInt = in.nextInt();
if (validInt <= upper && validInt >= lower) {
valid = true;
} else {
System.out.print("Invalid- Retry: ");
}
} else {
in.next();
System.out.print("Invalid input- Retry: ");
}
}
return validInt;
}
public static char input() {
Scanner in = new Scanner(System.in);
boolean valid = false;
char validChar = 'a';
while (!valid) {
if (in.hasNext()) {
validChar = in.next().charAt(0);
if (validChar == 'R' || validChar == 'P' || validChar == 'S'
|| validChar == 'Q') {
valid = true;
} else {
System.out.print("Invalid- Retry: ");
}
} else {
in.next();
System.out.print("Invalid input- Retry: ");
}
}
return validChar;
}
}

Why a.length allows i to go from 0 to 3 if a.length == 4?
In computer science you start counting at 0 so a length of 4 is
int array = new array[4];
array[0];
array[1];
array[2];
array[3];
Why are all the patterns the same?
in your main inside while (!stop) you should try patt = new char[4]; to ensure you don't use the same reference to that array over and over, because changing the base object will change all references aswell.
Just to clarify what i mean by references:
Is Java “pass-by-reference” or “pass-by-value”?

Related

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;
}
}

Looking for a better java OO approach to a lot of Boolean if else statements

I was given this project by a friend who is coding in school, but I am trying to find a better way to code it. It is calling different Boolean methods, checking if true and adding to a count for latter use.
public static void testHand(PokerHand d) {
if (d.isRoyalFlush()) {
royalFlush++;
} else if (d.isStraightFlush()) {
straightFlush++;
} else if (d.is4OfAKind()) {
fourtOfAKind++;
} else if (d.isFullHouse()) {
fullHouse++;
} else if (d.isFlush()) {
flush++;
} else if (d.isStraight()) {
straight++;
} else if (d.is3OfAKind()) {
threeOfAKind++;
} else if (d.is2Pair()) {
twoPair++;
} else if (d.isPair()) {
pair++;
} else if(d.isHighCard()){
highCard++;
}
}
The code for PokerHand is as follows:
public class PokerHand {
private Card[] hand; // the hand of 5 cards
// the default constructor
public PokerHand() {
hand = new Card[5];
}
// A constructor to help with testing
public PokerHand(Card c0, Card c1, Card c2, Card c3, Card c4) {
hand = new Card[5];
hand[0] = c0;
hand[1] = c1;
hand[2] = c2;
hand[3] = c3;
hand[4] = c4;
}
/* This methods fills the hand with cards from the deck.
It uses an insertion sort so that the cards are ordered by rank.*/
public void fillHand(Deck deck) {
for (int i = 0; i < 5; i++) {
int j = i - 1;
Card temp = deck.dealCard();
while (j >= 0 && hand[j].getRank() > temp.getRank()) {
hand[j + 1] = hand[j];
j--;
}
hand[j + 1] = temp;
}
}
//PLACE ADDITIONAL METHODS AFTER THIS COMMENT
/*Checking for Royal flush by first checking if straight flush
and then if highest card is an Ace.*/
public boolean isRoyalFlush() {
return (isStraightFlush() && hand[4].getRank() == 14);
}
//Check for Straight Flush by seeing if it is both a straight and a flush
public boolean isStraightFlush() {
return (isFlush() && isStraight());
}
/*Checking if hand is a Four-of-a-kind. Done by looking at first card and
checking if it equals next 3 cards. If not, then checking second card and
checking if it equals next three cards.*/
public boolean is4OfAKind() {
boolean isFour = false;
for (int i = 0; i < hand.length - 3; i++) {
int card = hand[i].getRank();
if (card == hand[i + 1].getRank()
&& card == hand[i + 2].getRank()
&& card == hand[i + 3].getRank()) {
isFour = true;
}
}
return isFour;
}
//Checking if hand holds a Full House By:
public boolean isFullHouse() {
//Setting two boolean values
boolean a1, a2;
//First checking if it is a pair followed by a 3-of-a-kind.
a1 = hand[0].getRank() == hand[1].getRank() &&
hand[2].getRank() ==hand[3].getRank() && hand[3].getRank() == hand[4].getRank();
//Second, checking if it is 3-of-a-cind followed by a pair
a2 = hand[0].getRank() == hand[1].getRank() && hand[1].getRank() == hand[2].getRank() &&
hand[3].getRank() == hand[4].getRank();
//Returns true if it is either.
return (a1 || a2);
}
/*Checking if hand is a Flush by first getting the first card's suit
and checking if it is the same for all cards.*/
public boolean isFlush() {
String suit = hand[0].getSuit();
return hand[1].getSuit().equals(suit)
&& hand[2].getSuit().equals(suit)
&& hand[3].getSuit().equals(suit)
&& hand[4].getSuit().equals(suit);
}
/*Checking id hand is a Straight by first getting the rank of the first
card, then checking if the following cards are incremented by 1*/
public boolean isStraight() {
int card = hand[0].getRank();
return (hand[1].getRank() == (card + 1) &&
hand[2].getRank() == (card + 2) &&
hand[3].getRank() == (card + 3) &&
hand[4].getRank() == (card + 4));
}
/*Checking if hand is a Three-of-a-kind. Done by looking at first card and
checking if it equals next 2 cards. If not, then checking next card and
checking if it equals next 2 cards. This is done three times in total.*/
public boolean is3OfAKind() {
boolean threeKind = false;
for (int i = 0; i < hand.length - 2; i++) {
int card = hand[i].getRank();
if (card == hand[i + 1].getRank() &&
card == hand[i + 2].getRank()) {
threeKind = true;
}
}
return threeKind;
}
//Checking hand for 2 pairs by:
public boolean is2Pair() {
int count = 0; // Number of pairs.
int firstPair = 0; //If pair found, store rank.
//Go through hand
for (int i = 0; i < hand.length - 1; i++) {
int card = hand[i].getRank();
//Finding pairs. Cannot be same rank pairs.
if (card == hand[i + 1].getRank() && card != firstPair) {
firstPair = card;
count++;
}
}
return count == 2;
}
/*Checking if hand is a Pair. Done by looking at first card and
checking if it equals the next card. If not, then it checks the next card and
sees if it equals the next card. This is done four times in total.*/
public boolean isPair() {
boolean isPair = false;
for (int i = 0; i < hand.length - 1; i++) {
int card = hand[i].getRank();
if (card == hand[i + 1].getRank()) {
isPair = true;
}
}
return isPair;
}
//If hand is not equal to anything above, it must be High Card.
public boolean isHighCard() {
return !(isRoyalFlush() || isStraightFlush() || is4OfAKind()
|| isFullHouse() || isFlush() || isStraight()
|| is3OfAKind() || is2Pair() || isPair());
}
}
You could use the ternary operator ? : to shorten the code. Like
public static void testHand(PokerHand d) {
royalFlush += d.isRoyalFlush() ? 1 : 0;
straightFlush += d.isStraightFlush() ? 1 : 0;
fourtOfAKind += d.is4OfAKind() ? 1 : 0; // <-- this appears to be a typo.
fullHouse += d.isFullHouse() ? 1 : 0;
flush += d.isFlush() ? 1 : 0;
straight += d.isStraight() ? 1 : 0;
threeOfAKind += d.is3OfAKind() ? 1 : 0;
twoPair += d.is2Pair() ? 1 : 0;
pair += d.isPair() ? 1 : 0;
highCard += d.isHighCard() ? 1 : 0;
}
Alternatively, you could encode the hand types with an enum. Give the PokerHand a HandType (or create a factory method). Something like,
enum HandType {
ROYALFLUSH, STRAIGHTFLUSH, FOUROFAKIND, FULLHOUSE, FLUSH,
STRAIGHT, THREEOFAKIND, TWOPAIR, PAIR, HIGHCARD;
static HandType fromHand(PokerHand d) {
if (d.isRoyalFlush()) {
return ROYALFLUSH;
} else if (d.isStraightFlush()) {
return STRAIGHTFLUSH;
} else if (d.is4OfAKind()) {
return FOUROFAKIND;
} else if (d.isFullHouse()) {
return FULLHOUSE;
} else if (d.isFlush()) {
return FLUSH;
} else if (d.isStraight()) {
return STRAIGHT;
} else if (d.is3OfAKind()) {
return THREEOFAKIND;
} else if (d.is2Pair()) {
return TWOPAIR;
} else if (d.isPair()) {
return PAIR;
} else {
return HIGHCARD;
}
}
}
Then you can create an array of counts for testHand like
private static int[] handCounts = new int[HandType.values().length];
public static void testHand(PokerHand d) {
handCounts[HandType.fromHand(d)]++;
}
I would suggest you model the potential hands as an enum. They are a good use case because they have a fixed set of members.
Something like the following:
enum Rank {
ROYAL_FLUSH(Hand::isRoyalFlush),
FOUR_OF_A_KIND(Hand::isFourOfAKind),
...
public static Rank getRank(Hand hand) {
for (Rank rank: values()) {
if (rank.test.test(hand))
return rank;
}
throw new IllegalStateException("No rank for hand " + hand.toString());
}
private final Predicate<Hand> test;
Rank(Predicate<Hand> test) {
this.test = test;
}
}
Then all your if statements can be replaced by Rank.getRank(hand).
Maybe the switch statement will suit your needs :
switch (d) {
case d.isRoyalFlush() : royalFlush++; break;
case d.isStraightFlush(): straightFlush++; break;
... ... ...
default : do-something();
}

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 my recursive backtracking stop at seemingly random points

I am attempting to generate all closed curves in a finite region of the simple hexagonal lattice. This isn't too important, it is just a finite set of points a distance of 1 away from each other. My code however, will generate closed curves for a while, and then my program will quit working and get stuck in a infinite loop? I have tried forcing java to garbage collect by command, but the same code stops at different points. As far as I can tell, where it stops is random.
Sphere is an array storing all the points in the region under consideration
private static Sphere Sphere1 = new Sphere();
private static double [][] vectors = {{0, 0, 1},{0, 0, -1},{1, 0, 0},{-1,0,0},{.5, (Math.sqrt(3))/2, 0},{-.5, -(Math.sqrt(3))/2, 0},{.5, -(Math.sqrt(3))/2, 0},{-.5, (Math.sqrt(3))/2, 0}};
private static StringBuilder loopString = new StringBuilder("r");
private static String posPoints = "abcdefghijklmnopqrstuvwxyz1234567";
private static int garbage = 0;
private static boolean once = false;
private static PrintWriter output = null;
public static void main (String [] args){
try {
output = new PrintWriter(new FileOutputStream("closedLoops.txt"));
} catch (FileNotFoundException e){
System.out.println("error");
}
System.out.println("start");
KnotPoint loopPoint = new KnotPoint(0,0,1);
addVector(loopPoint, vectors);
}
public static void addVector(KnotPoint loopPoint, double [][] vectors){
garbage ++;
if (garbage == 200){
System.gc();
garbage = 0;
}
if (loopString.length() > 19
&& (loopString.charAt(loopString.length()-1) == 'z' ||
loopString.charAt(loopString.length()-1) == '3' ||
loopString.charAt(loopString.length()-1) == 'u' ||
loopString.charAt(loopString.length()-1) == 'o' ||
loopString.charAt(loopString.length()-1) == 'g' ||
loopString.charAt(loopString.length()-1) == 'j' ||
loopString.charAt(loopString.length()-1) == 'q'))
{
System.out.println(loopString);
output.println(loopString);
once = true;
return;
}
for (int i = 0; i < 8 ; i ++){
if (validAdd(loopPoint, vectors[i], loopString, posPoints)){
loopPoint.addNext(vectors[i]);
addVector(loopPoint, vectors);
//System.gc();
loopString.deleteCharAt(loopString.length()-1);
loopPoint.subtractLast(vectors[i]);
if(loopString.toString().equals("r") ){
output.println("you did it");
output.close();
System.out.println("you did it good job");
System.exit(0);
}
}
}
return;
}
public static boolean validAdd(KnotPoint loopPoint, double [] vector, StringBuilder loopString, String posPoints){
KnotPoint testAdd = new KnotPoint();
testAdd.set(loopPoint);
testAdd.addNext(vector);
int pointIndex = 0;
boolean pointCheck = false;
char point = '.';
for (int i = 0; i < 33; i ++){
if( testAdd.equals(Sphere1.getKnotPoint(i))){
pointIndex = i;
pointCheck = true;
point = posPoints.charAt(i);
}
}
if (pointCheck && !loopString.toString().contains(posPoints.substring(pointIndex, pointIndex + 1))&& point != 'r'){// added not r check
loopString.append(point);
return true;
} else {
return false;
}
}

Boolean in a method not returning correctly (array formal paramater)

I am trying to make a cee-lo program in simple, simple java. I'm just learning. However when I get to my instant w. (i have simplified it for the test) it just always returns false. I can't seem to figure out why. It even displays the correct data but when it compares it it fails.
public class ceeLo
{
public static void main (String [] args)
{
Scanner scan= new Scanner (System.in);
int [] die = new int [3];
int answer;
boolean roll = true;
boolean qualifed;
boolean instantW;
boolean instantL;
do
{
System.out.println("Roll the dice?");
answer = scan.nextInt ();
if (answer == 0)
roll= false;
else
{
int i;
for (i = 0; i < die.length; i++)
{
die[i]= rollin();
System.out.println(diceTxt(die[i]));
}
qualifed = (qualify (die));
System.out.println("Qualified = " + qualifed);
instantW = (easyW (die));
System.out.println("Instant win = " + instantW);
}
}
while (roll);
}
// Generate random numbers for the roll
public static int rollin ()
{
Random rand = new Random();
int die= rand.nextInt(6);
return die;
}
//Check if dice qualify with pair
public static boolean qualify (int [] die)
{
boolean qualify;
//Pair Qualifying roll
if (die[0] == die[1] || die[0] == die[2] || die[1] == die[2])
qualify = true;
else
qualify = false;
return qualify;
}
//Check if instant win
public static boolean easyW (int [] die)
{
boolean instantW;
// show contents of die [x] for testing
System.out.println (die[0] + "" + die[1] + "" + die[2]);
if (die[0] > 2 && die [1] > 2 && die[2] > 2)
instantW = true;
else;
instantW = false;
return instantW;
}
}
Remove semi-colon after else; it should be just else
I guess the reason is,
instantW = false; is being treated as separate statement not part of else block. Which is why instantW is always being assigned to false and returning false.
It is always better to use {} to define block even though they are single liners. It is my preference.
As Greg Hewgill suggested, using single statement instantW = die[0] > 2 && die [1] > 2 && die[2] > 2; would do good than if/else.
A better way to write boolean methods is really to do something like
boolean easyW(int[] die)
{
return (die[0] > 2 && die[1] > 2 && die[2] > 2);
}
Or even better (more general)
boolean easyW(int[] die)
{
for(int roll : die)
{
if(roll < 2)
{
return false;
}
}
return true;
}
But in your case, you have a ; after your else. Fixed version:
public static boolean easyW (int [] die)
{
boolean instantW;
// show contents of die [x] for testing
System.out.println (die[0] + "" + die[1] + "" + die[2]);
if (die[0] > 2 && die [1] > 2 && die[2] > 2)
instantW = true;
else
instantW = false;
return instantW;
}

Categories

Resources