Arrays, algorithms and elements - java

I am trying to make a poker game through java.
The first thing I wanted to do is distribute 5 cards using arrays. I have done the distribution part, but how can I prevent the same cards being distributed twice. In other words, how can I check if an array already contains an element. I want it to be able to detect if the element already exists in an array, and if it does, I want to be able to change just that card that has been given out twice, help would be much appreciated.
My codes down below,
import java.util.Random;
import java.util.Scanner;
import java.util.Arrays;
public class Poker
{
public final static String[] numbers = {"❤","♠","♦","♣"};
public final static String[] sign = {"1","2","3","4","5","6","7","8","10","J","Q","K","A"};
private String[] hand = {"","","","",""};
private boolean found;
private Random random;
public Poker()
{
found = false;
String hand[] = {"","","","",""};
int tokens = 10;
Scanner in = new Scanner(System.in);
random = new Random();
}
public void handOut()
{
for (int i = 0; i < 5; i++)
{
int numberRandom = random.nextInt(numbers.length);
int signRandom = random.nextInt(sign.length);
String pickedNumber = numbers[numberRandom];
String pickedSign = sign[signRandom];
String combinedSigns = pickedSign + pickedNumber;
hand[i] = combinedSigns;
System.out.print(hand[i] + " ");
}
System.out.println("\n");
}
}

Your choice of terminology is ... err ... interesting :-)
The card value is a "face value", not a sign. And whether it's hearts or diamonds or so on, that's its "suit" rather than its number.
But, on to the question. I believe the best way to do this is to construct an entire 52-card deck out of your facevalue and suit arrays and then use a Fisher Yates shuffle to distribute cards.
This is a nifty way to randomly choose elements from an array without duplicates. The beauty is that the items in the array don't actually need to be shuffled up front. Details on how it works can be found here.

If you can use the collections framework as opposed to an array, create a Stack and populate it with all the 52 cards. then call Collections.shuffle() on it.
finally set hand[i]=(deck name).pop()
Once a card is popped from the stack it will be removed from the deck so it can't be dealt again.

What you want to do is break your code into different methods. You should have a method for generating one card, a method for checking whether or not a card is in the hand, and a method to distribute cards to the hand.
public String generateCard() {
int numberRandom = random.nextInt(numbers.length);
int signRandom = random.nextInt(sign.length);
String pickedNumber = numbers[numberRandom];
String pickedSign = sign[signRandom];
return pickedSign + pickedNumber;
}
public static boolean cardIsInHand(String card) {
for(int i = 0; i < 5; i++) {
if(hand[i] != null && hand[i].contains(card)) {
return true;
}
}
return false;
}
public static void handout() {
for (int i = 0; i < 5; i++) {
String card = generateCard();
while(cardIsInHand(card)) {
card = generateCard();
}
hand[i] = card;
}
}

Related

How is using a char array parameter benefits the solution?

The assignment states that there's another class that will call this class. It is similar to betting - you select 12 characters and put them in the array and the program will output a random set of characters. Then it will calculate how many of those matched.
The teacher told me that there should be a parameter of char[] type in the print() method and two in the checked method, but I don't understand the need for them. I could make something similar without his weird choices, but I'm stuck with that. Therefore, I am wondering, if anyone understands the reason for that. It is a method for user input already and it is a method for the computer generated randoms, so I don't see why I have to put a parameter on the other methods. Can't see how that is a logical choice.
Code to solve the assignment:
import java.util.Random;
import java.util.Scanner;
import java.util.Arrays;
public class Tipping
{
char[] ukensRekke;
public Tipping()
{
ukensRekke = new char[12];
}
public void WeekResult(){
String HBU = "HBU";
for(int i = 0; i < ukensRekke.length; i++){
ukensRekke[i] = HBU.charAt((int)(Math.random()*3));
}
}
public char[] getWeekResult(){
return ukensRekke;
}
public void print(char[] tastet){
tastet = new char[12];
for(int i = 0; i < tastet.length; i++){
System.out.print(tastet[i]);
}
}
public char[] register(){
Scanner scan = new Scanner(System.in);
char[] vinnerTall = new char[12];
for(int i = 0; i < vinnerTall.length; i++){
System.out.println("Skriv inn H,B eller U for kamp" + (i+1) + "; ");
vinnerTall[i] =scan.next().charAt(0);
System.out.println(vinnerTall[i]);
}
return vinnerTall;
}
public int check(char[] original, char[] tastet){
original = ukensRekke;
tastet = register();
return tastet.length;
}
}
UPDATE: Hi, so I was somewhat able to solve the problem, but it's still one finishing touch. Here's the part of the code I have problems with, hope someone can help me out.
System.out.println("Klassen Tipping instansieres...");
System.out.println();
System.out.println("Ukens rekke genereres...");
System.out.println();
System.out.println("Brukers rekke registreres.");
tp.register();
System.out.println();
System.out.println("Ukens rekke hentes...");
System.out.println();
System.out.println("Ukens rekke;");
tp.print(tp.getWeekResult());
System.out.println("Brukers rekke;");
tp.print(tp.register());
System.out.println();
System.out.println("Bruker hadde" + tp.check(tp.getWeekResult(),tp.register()) + "riktige tippetanger");
this is the class that I use to make a kinda like sheet, it prints out everything on the screen and takes the user input, but the last two method calls doesn't work, the program just skips it and starts all over again.
and this is the code I use that gets called from:
public void WeekResult(){
String HBU = "HBU";
for(int i = 0; i < ukensRekke.length; i++){
ukensRekke[i] = HBU.charAt((int)(Math.random()*3));
}
}
public char[] getWeekResult(){
return ukensRekke;
}
public void print(char[] tastet){
System.out.print(taste);
}
public char[] register(){
Scanner scan = new Scanner(System.in);
char[] vinnerTall = new char[12];
for(int i = 0; i < vinnerTall.length; i++){
System.out.println("Skriv inn H,B eller U for kamp" + "; ");
vinnerTall[i] = scan.next().charAt(0);
}
return vinnerTall;
}
Your teacher asks you to use a char[] array over a String object simply to use less memory.
Read the answer(s) to this question: How much memory does a string use in Java 8?
One of the answer shows that a String object takes up a minimum of 80 (-8) bytes in memory. In your case, the char array ukensRekke needs only 12 * 2 = 24 bytes. So less memory is used. This is a good advice. You should always keep these efficiency factors in mind to be able to make efficient programs.

Java: Initializing a new LinkedList Collection

I am trying to build a simple card game as a personal exercise. I have a collection Cards that should contain my deck. To initialize it, I want to pass it a map of what the deck should look like - an integer array (1 to n, 1 to 2) with (n, 1) containing a card type which is resolved within the card class, and (n, 2) containing the number of cards that type I want in the deck. I'm having difficulties with a NullPointer exception, however. Here is my Cards class:
import java.util.LinkedList;
public class Cards{
private LinkedList<Card> CardDeck;
...
public boolean MakeDeck(int[][] DeckMap){
/*feed the function a 2D int array (0 to n, 0 to 1)
#Param - DeckMap[][] - [n][0] to contain card type
[n][1] to contain DupeCount*/
//search the array for duplicates
for (int i = 0; i < DeckMap.length; i++){
int hold = DeckMap[i][0];
DeckMap[i][0] = -10;
for (int j = 0; j< DeckMap.length; j++){
if (DeckMap[j][0] == hold){
DeckMap[i][0] = hold;
return false;
}
}
DeckMap[i][0] = hold;
}
//Add the cards
// tried variations on this: CardDeck = new LinkedList<Card>;
for (int i = 0; i< DeckMap.length; i++){
Card cC = new Card();
cC.initializeCard(DeckMap[i][0], DeckMap[i][1]);
CardDeck.addLast(cC);
}
return true;
}
}
The NullPointer error occurs at the cC.addLast line - since I have initialized the Card class, the Null Pointer should refer to the CardDeck LinkedList I want to add the Card to, I think. But I can't work out how to initialize the list. Or is the .initializeCard call the problem (code below)? Thanks in advance for your help and apologies if I've missed something obvious.
Error:
java.lang.NullPointerException
at towergame.Cards.MakeDeck(Cards.java:75)
public class Card {
private static String cName;
private static int cDuplicateCount;
public static cEffect myEffects;
public final void initializeCard(int inEffect, int DupeCount){
myEffects = new cEffect();
myEffects.setEffect(inEffect);
cName = myEffects.getCardType();
cDuplicateCount = DupeCount;
}
...
}
Instead of this private LinkedList<Card> CardDeck;
use this private LinkedList<Card> CardDeck = new LinkedList<Card>();
it is throwing NPE because cardDeckhas not been initialized.

Print random integers without duplicates [duplicate]

This question already has answers here:
Generating Unique Random Numbers in Java
(21 answers)
Closed 9 years ago.
I have this assignment:
Print 5 random integer between 1-52 with no duplicate using if/else.
Here's my code so far. It prints some numbers, but it sometimes prints duplicates.
import java.util.Random;
public class RandomCards {
public static void main(String[] args) {
Random randomCards = new Random();
int card;
for (int x = 1; x <= 5; x++) {
card = randomCards.nextInt(52) + 1;
}
if (card != randomCards) // if the value of card is not equal, proceed
{
System.out.print(card + " ");
} else {
return card; // if the value are the same get random integers again
}
}
}
public static void main(String args[]) {
Random randomNumber = new Random();
// Set stores only Unique values
Set<Integer> cards = new HashSet<Integer>();
// Iterate over to generate random numbers
while (cards.size() < 5) {
int r = randomNumber.nextInt(52) + 1;
cards.add(r);
}
for(Integer card : cards) {
System.out.println(card);
}
}
You can use this
Random randomCards = new Random();
int[] card={0,0,0,0,0};
while(card[card.length-1] == 0) {
int temp=randomCards.nextInt(52);
for(int j=0;j< card.length ; j++){
if(card[j] == 0){
card[j] = temp;
break;
}
}
}
for(int j=0;j< card.length ; j++){
System.out.println(card[j]);
}
It's not clear what you're asking, but I note from your code that you don't have any duplicate detection. You need to save each value that you generate and check for duplicates when you create a new one. I suggest creating a Set<Integer> to hold your generated values, calling add() for each new card, and checking contains() to see whether a new value has already been selected. You'd want to change your loop condition to something like cards.size() < 5 as well.
Finally, note that your use of return card is incorrect and will result in a compile-time error. return is used to end a method and send a value back to where it was called from; the main method (which is always void) has no return value, and ending the method wouldn't make sense there anyway. It looks like some code may have been copied and pasted from a version where drawCard() was its own method. Instead, just keep looping until you find 5 unique cards (such as by using the size() method I mentioned earlier).
Maybe this?
Random rand = new Random();
// ArrayList to store non-duplicate cards.
ArrayList<Integer> cards = new ArrayList<Integer>();
// Iterate over to generate random numbers
while (cards.size() < 5)
{
int r = rand.nextInt(52) + 1;
if (!cards.contains(r))
cards.add(r); // Only add if there is no such number in list
}
Hope this helps.
Hope this would be of any help.
It comprises of separate methods for computation, setting the lower and upper bound and printing the list when it has 5integers in it. Using TreeSet solves your problem of duplicates. Here it goes,
package com.project.stackoverflow;
import java.util.Random;
import java.util.Scanner;
import java.util.TreeSet;
public class RandomGenerator {
public TreeSet<Integer> compute() {
TreeSet<Integer> generatedList = new TreeSet<Integer>();
Scanner s = new Scanner(System.in);
System.out.println("Enter the lower bound for checking random numbers:");
long lowBound = s.nextLong();
System.out.println("Enter the upper bound for checking random numbers:");
long topBound = s.nextLong();
Random randomNumbers = new Random();
for (int i = 0; i < topBound; i++) {
if (generatedList.size()==5) {
break;
}
else {
generatorFunc(lowBound, topBound,randomNumbers,generatedList);
}
}
return generatedList;
}
public void generatorFunc(long lowBound,long topBound,Random randomNumbers, TreeSet <Integer> generatedList) {
long limit = topBound - lowBound;
long part = (long)(limit * randomNumbers.nextDouble());
int randomNum = (int) (part + lowBound);
generatedList.add(randomNum);
}
public void printList() {
TreeSet<Integer> testListVals = compute();
System.out.println("New" + testListVals);
}
public static void main(String[] args) {
RandomGenerator obj = new RandomGenerator();
obj.printList();
}
}
If your problem is just about the duplicates, then you can store each random number generated in an array, and for every successive call to nextint(), check if it already exists in the array of stored values, and till it does, call nextint() again for that iteration itself, else store it in the array and go to next iteration.

Return array in Java

I have my primary class running, and I wanted to run a separate class to shuffle numbers, then return the shuffled numbers into my primary class. In my shuffle class I have the return statement... but now what do I do? How do I use the random order of my int array in my primary class?
Here is my shuffle class:
public class Shuffle {
public static int[] getShuffle() {
int[] cards = new int[52];
ArrayList<Integer> cards_objs = new ArrayList<Integer>();
for (int i = 0; i < cards.length; i++) {
cards_objs.add(i);
}
Collections.shuffle(cards_objs);
for (int i = 0; i < cards.length; i++) {
cards[i] = cards_objs.get(i);
}
return cards;
}
}
I am making a card game(if you cant tell);
I wanted to use this shuffle class so that the cards are shuffled... but no card appears more than once.
when I return cards, how do I use them in my game class?
for example if the first number in the array is 1, then the card is Ace of clubs,
if the number is 2, then the card is Ace of diamonds. and so on...
I apologize for not posting enough information... I am new to java (as you can tell)
all help will be greatly appreciated,
-Steve
EDIT:
I found out what my problem was, I don't think I made it clear enough what my question was. Nonetheless thank you all for your help, it gave me ideas on different ways to approach this project.
I think using enum you can implement Card Game in a better way.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
// This is just sample example and it is just to show an approach. I had not enough time to make code perfect but it works fine.
public enum Deck
{
DECK;
enum Rank
{
DEUCE(2), THREE(3), FOUR(4), FIVE(5), SIX(6),
SEVEN(7), EIGHT(8), NINE(9), TEN(10), JACK(10), QUEEN(10), KING(10), ACE(11);
Rank(int rank)
{
this.rank = rank;
}
private final int rank;
}
enum Type
{
SPADES,
HEARTS,
DIAMONDS,
CLUBS;
}
class Card
{
private final Rank rank;
private final Type type;
Card(Rank rank, Type type)
{
this.rank = rank;
this.type = type;
}
#Override
public String toString()
{
return type.name() + rank.name();
}
}
static List<Deck.Card> cards = new ArrayList<Deck.Card>();
static
{
for (Rank rank : Deck.Rank.values())
{
for (Type type : Deck.Type.values())
{
cards.add(DECK.new Card(rank, type));
}
}
}
List<Deck.Card> shuffle()
{
Collections.shuffle(cards);
System.out.println(cards);
System.out.println(cards.size());
return Collections.unmodifiableList(cards);
}
public static void main(String[] args)
{
DECK.shuffle();
}
}
No need to define seperate class i feel, Just create an arraylist of numbers, pass it to Colections class of java
public static void shuffle(List list)
Your list will be shuffled directly
Either you change the array order so you can iterate the normal order in the array in your main class or you return an array back from your shuffle methode which contains the order (index) desired then access these up to this order.
Option A is to change the roder of the elemtns of your main array and Option B is to read the array and decide determin the new order, and return the order as ana rray backt, then access the main array up tot he new order.
You can simply have a method in you main class where you can do the shuffling and return the new set of shuffled numbers as an array.
If you do want to use another class, then you can do that using the instance of the class, and then call that reShuffleNumbers(), whereas reShuffleNumbers() will return array of numbers as you've wanted.
Try this -
public static void shuffleArray(int[] a) {
int n = a.length;
Random random = new Random();
random.nextInt();
for (int i = 0; i < n; i++) {
int change = i + random.nextInt(n - i);
swap(a, i, change);
}
}
private static void swap(int[] a, int i, int change) {
int helper = a[i];
a[i] = a[change];
a[change] = helper;
}
Pass the array to method shuffleArray() and you will get your array elements modified by position.
I hope this is what you are looking for.

How to check that a string is generated only once

I have this method that generates random questions, I want to be able to generate each question once and no more than once.
How could I do that?
This is the code so far:
package boss;
import java.util.Random;
import javax.swing.JFrame;
public class Boss {
public static void main(String[] args) {
LoginWindow window = new LoginWindow();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
public String getQuestions() {
String [] question = new String[30];
question[0] = "hello";
question[1] ="yo";
question[2] ="b";
question[3] ="ha";
//Generating random questions
Random r = new Random();
int i=r.nextInt(4);
String quest=question[i];
return quest;
}
}
You're not generating questions in your example - you're picking them from a fixed set stored in an array. It sounds like you just want to shuffle the array, then iterate over part of it until you have seen the required number of questions. So - suggest you shuffle the questions, then just iterate over the shuffled array, or shuffle an array of indexes 0..n and iterate over those in the original list of questions.
There's plenty of approaches to shuffling, perhaps the simplest is a single pass over the input data, swapping each element with some other randomly chosen element.
Use an ArrayList instead of a table. Removes the displayed question from the ArrayList when it has been displayed.
you have to keep a list of the ones you've already used and check against that.
boolean used[] = new boolean[30];
int i;
do {
Random r = new Random();
i=r.nextInt(4);
} while(used[i] == true);
String quest=question[i];
used[i] = true;
A fairly simple solution would be to keep a record of all the questions you have asked and only generate ones that you have not:
private ArrayList<Integer> questionsAsked = new ArrayList<>();
public String getQuestions()
{
String [] question = new String[30];
question[0] = "hello";
question[1] ="yo";
question[2] ="b";
question[3] ="ha";
//Generating random questions
Random r = new Random();
int i = r.nextInt(question.length);
//keep looping until you find a question you have not asked
while(questionsAsked.contains(i))
{
i = r.nextInt(question.length);
}
//add that question to the list of questions already asked
questionsAsked.add(i);
//ask the question
return question[i];
}
You can use Collections.shuffle together with queue remove and lazy question generation, working example:
import java.util.*;
public class Mkt {
private Queue<String> questions = null;
public Mkt() {
for(int i = 0; i < 10; i++) {
System.out.println(getQuestion());
}
}
public String getQuestion() {
if(questions == null || questions.size() == 0) {
questions = generateQuestions();
}
return questions.remove();
}
private Queue<String> generateQuestions() {
List<String> list = Arrays.asList("hello", "yo", "b", "ha");
Collections.shuffle(list);
return new LinkedList<String>(list);
}
public static void main(String[] args) {
new Mkt();
}
}
Sample run:
$ javac Mkt.java && java Mkt
ha
yo
hello
b
b
ha
hello
yo
hello
ha
You could solve this with a "shuffle" algorithm. Basically randomize (shuffle) your array and then just pick the next item from the list.
One of the easiest shuffle algorithms is Knuth's: http://en.wikipedia.org/wiki/Knuth_shuffle
Pseudocode to shuffle your array:
Random rand = new Random();
for (int i=questions.Length-1; i>=0; --i)
{
int nextRand = rand.Next(i);
// Switch the randomly selected 'next' to the current pointer in the array
string temp = questions[nextRand];
questions[nextRand] = i;
questions[i] = temp;
}
Keep track of what you've already picked.
String [] question = new String[30];
boolean[] picked = new boolean[30];
...
if (!picked[i])
{
String quest=question[i];
picked[i] = true;
}
else
// choose another
(Obviously you'll need to restructure your code and also deal with knowing when you've exhaused your question supply and all have been picked)

Categories