How to implement a condition with two loops - java

public void PlayforMe()
{
for (int i=game.size()-1;i>=1;i--)
{
Card a = game.get(i);
Card b = game.get(i-1);
if (a.getSuit().equals(b.getSuit()) | (a.getCardNum().equals(b.getCardNum())))
{
game.remove(b);
break;
}
}
for (int j=game.size()-1;j>=3;j--)
{
Card c = game.get(j);
Card d = game.get(j-3);
if (c.getSuit().equals(d.getSuit()) | (c.getCardNum().equals(d.getCardNum())))
{
game.set(j-3,game.get(j));
game.remove(j);
break;
}
}
}
I have written this piece of Java code for a solitaire type game I'm making in Java code. I'm very new to the language (and programming in general). I have an arrayList for my deck and an arrayList for my 'game'. In this method/move I have it so it will find the card nearest the end of the dealt cards and 'swap' it with the card directly before it if the suit or the card number are the same.
If this move isn't an option with the cards dealt then I need it to go through the second loop which finds the card nearest the end of the dealt cards and 'swaps' it with the card [3] places before it if the suit or the card number are the same.
They work individually, but I can't get a condition working (e.g. I've tried the if statement) that will go through the first loop, and if it doesn't successfully remove a card it will go through the second loop.
The method should only preform one move, prioritising moving a card onto the card next(before) it if the conditions are met. I can make it so it'll go through both loops (i.e. putting the piece of code into two methods and calling them both from my menu) but I need it to do the first loop and only do the second if the first one turns out unsuccessful (i.e. card b isn't removed/game.remove(b); isn't called.)
If anyone has any suggestions I'd appreciate it :)

You want to put Boolean finished = false; at the start of the function, then finished = true when you have finished. Then put if (finished) { ... } round your second loop.
Alternatively put a return in the first loop when finished. This will return out your function and execute no more lines of code. Although some people consider this bad style.

If the first for loop succeeds, return instead of breaking.

Related

Hangman that saves wrong guesses in array and prints them before each guess. also prints gameboard with "_" and correct guesses

so I've been studying Java for about 3 months and I am supposed to do a Hangman code using only arrays, loops, and if statements. the word to be guesses is read from another file and saved as a string. I have to be able to save the wrong guesses in an array. and after each guess print all the wrong guesses so far, as well as the gameboard with underscores for not guessed letters and the correct guesses of course in their place. here is my code so far :
for(int l = 0; l<wordlength;l++)
{
System.out.print("_");
}
System.out.println();
System.out.println("WRONG: ");
for(int c = 0; c<numofGuesses;c++)
{
System.out.println();
System.out.print("GUESS"+guessN+"/"+numofGuesses+": ");
char guess1=in.next().charAt(0);
char guess = Character.toUpperCase(guess1);
guessN = guessN+1;
for (int j = 0; j<wordlength;j++)
{
if (guess==guessword.charAt(j))
{
System.out.println("Great guess!");
System.out.print (guessword.charAt(j));
}
else
{
System.out.print("_");
WRONG[u]=guess;
u++;
}
}
if you guess A it prints correctly "A___" but then if you guess B after instead of printing "AB__" (the word to guess is ABLE) i get "B__" also the wrong array is not storing and printing all the wrong guesses each time. please help I've been trying for 5 days and that's all I did the entire day today and I couldn't get past this.
Because this sounds a lot like a homework assignment, I will give directions for solving this, but not provide a full working solution. Hopefully, seeing how one could1 go about approaching such a problem is enough of a step in the right direction to be able to solve it yourself.
Let's first think about what we need to do.
Read a word that needs to be guessed, say String toBeGuessed.
You did this. ✔
Keep track of the characters the player has guessed so far.
Keep track of the number of turns a player has gotten.
Keep track of if the word has been guessed (player won!).
Say that the number of guesses a player can make is fixed. This can be modeled using a constant:
/**
* Number of guesses a player can take.
*/
public static final int NUM_GUESSES = 10;
Now let's think about the main logic of our hangman game. It is good to first think about the structure of your program and only later actually implement it. When thinking of the program structure, we don't bother with specifics of the programming language of your choice yet. In pseudocode, it would be something like the following, maybe (let's indicate what you already have with ✔).
for turn from 1 upto NUM_GUESSES do ✔
show player what they guessed so far
show the gameboard
ask player for their new guess ✔
save player's guess and update internal state
check if the player won, let them know if they did
if player did not win
let them know
Right. So, we need to somehow store the guesses that a player made. Every guess is a character, and we know there will be at most NUM_GUESS guesses in total. A good option (and one that is suggested by your exercise) is an array!
/**
* Characters that have been guessed so far.
*/
private char[] guessed;
This can be initialized as follows, since we know the maximum number of guesses:
this.guessed = new char[NUM_GUESSES];
This gives us an array of NUM_GUESSES characters that are initialized to 0 (see here). Since users won't guess that character, we can use it to represent guesses that have not been done yet. Alternatively, we can keep track of the current turn of the player in a separate variable. Your choice!
In the following, I will not keep track of the current turn in a separate variable, just to show more of arrays and loops. It might be a fun exercise to change this to using an int turn variable!
show player what they guessed so far
Alright, this should be fairly straightforward now. We basically need to print the part of the guessed array that is not 0. That can be done using a loop, like so for example:
System.out.print("You so far guessed: ");
for (int i = 0; i < guessed.length; ++i) {
if (i > 0) {
System.out.print(", ");
}
if (guessed[i] != 0) {
System.out.print(guessed[i]);
} else {
break; // stop the loop as soon as we run into a 0
}
}
System.out.println(".");
This will print something like You so far guessed: a, b, c. when the player guessed those characters. See how we only print the comma when some other character was printed before?
show the gameboard
The next point of the program structure is trickier to get right. Let's think a bit about structure again.
for each character in toBeGuessed
if the character has been guessed
print it
else
print an underscore
Looping over every character of a word can be done as follows.
int length = toBeGuessed.length();
for (int i = 0; i < length; ++i) {
char character = toBeGuessed.charAt(i);
// do something with character here
}
How do you find if a character has been guessed yet? Well, by checking if it is stored in the guessed array. This again can be done using a loop. That loop will be very similar to the one we have written above, when showing what the player guessed so far. I think you should be able to figure that one out.
save player's guess and update internal state
We move on to the next point of the program structure. Say that we have a char guess that the player guessed. We need to store this in our array guessed. Where? Well, at the first open spot, that seems a reasonable choice. To find that one, let's use a loop again, and break the loop when we have found an open spot.
for (int i = 0; i < guessed.length; ++i) {
if (guessed[i] == 0) {
guessed[i] = guess;
break;
}
}
check if the player won, let them know if they did
What we need to know in order to see if the player won, is simply if the number of characters they guessed right is equal to the number of characters in toBeGuessed. You could modify the loop for showing the gameboard to not print characters, but count correct ones. Then at the end compare to toBeGuessed.length() and if they are equal, the player won.
if player did not win, let them know
This should be fairly easy, if you got the previous point working.
When you did all the above and stitched it together, you should have a working version of hangman. Your very own, something to be proud of!
Some tips and tricks:
you can implement most of the points described above as separate methods;
when you do so, you can write one main method that calls the other methods (this will make it easier to read your own code and make changes to it);
try to put as little code as possible in the main method.
Here is a little template that you can start from.
import java.io.PrintStream;
import java.util.Scanner;
public class HangMan
{
/** Number of guesses a player can take. */
public static final int NUM_GUESSES = 10;
/** Word to be guessed in a game of hangman. */
private String toGuess;
/** Letters that have been guessed so far. */
private char[] guessed;
/**
* Construct a new game of hangman, ready to be played.
*/
public HangMan(String toGuess)
{
this.toGuess = toGuess;
this.guessed = new char[NUM_GUESSES];
}
// your other methods go here
/**
* Read guesses from given input and print results to given output.
* Continues until guesses have run out, or word was guessed.
*/
public void play(Scanner in, PrintStream out)
{
for (int round = 0; round < NUM_GUESSES; ++round) {
showGuessedSoFar(out);
showGameBoard(out);
char guess = askGuess(in, out);
saveGuess(guess);
if (hasPlayerWon()) {
out.println("You won!");
return;
}
}
// at this point, player ran out of guesses and hence lost
out.println("You lost...");
}
/**
* The bit that runs our hangman game.
*/
public static void main(String[] args)
{
// read word to guess from arguments, with a default value
// you would probably insert your "read word from file" code here
HangMan game = new HangMan(args.length >= 1 ? args[0] : "ABLE");
// play a game, using system input and output
game.play(new Scanner(System.in), System.out);
}
}
Good luck!
TL;DR. Trying to teach one how to think about a problem and how to write code that executes the solution one thought of. Features some example code with arrays and loops.
1 This is only one possible solution, there are always many ways to solve a given problem.

Rush Hour solver running into infinite loop any non-trivial puzzle

So I'm writing a Rush Hour solver in Java, which is meant to be able to solve the configurations here. However, even the simplest puzzle from that page results in the solver running infinitely and eventually running out of memory. I'm using a breadth first search to work my way through all possible moves arising from each board state (using a HashSet to ensure I'm not repeating myself), and mapping each state to the move that got it there so I can backtrack through them later.
The thing is, I've tried it with more trivial puzzles that I've come up with myself, and it's able to solve them (albeit slowly).
Is there anything blatantly wrong with how I'm approaching this problem? I can put up some code from the relevant classes as well if I need to, but I've tested them pretty thoroughly and I'm pretty sure the problem lies somewhere in the code below. My gut says it's something to do with the HashSet and making sure I'm not repeating myself (since the Queue's size regularly reaches the hundred thousands).
Any suggestions?
// Start at the original configuration
queue.add(originalBoard);
// We add this to our map, but getting here did not require a move, so we use
// a dummy move as a placeholder move
previous.put(originalBoard, new Move(-1, -1, "up"));
// Breadth first search through all possible configurations
while(!queue.isEmpty()) {
// Dequeue next board and make sure it is unique
Board currentBoard = queue.poll();
if (currentBoard == null) continue;
if (seen.contains(currentBoard)) continue;
seen.add(currentBoard);
// Check if we've won
if (currentBoard.hasWon()) {
System.out.println("We won!");
currentBoard.renderBoard();
return solved(currentBoard);
}
// Get a list of all possible moves for the current board state
ArrayList<Move> possibleMoves = currentBoard.allPossibleMoves();
// Check if one of these moves is the winning move
for (Move move : possibleMoves) {
Board newBoard = move.execute(currentBoard);
// We don't need to enqueue boards we've already seen
if (seen.contains(newBoard)) continue;
queue.add(newBoard);
// Map this board to the move that got it there
previous.put(newBoard, move);
}
}
As requested, here are my initialisations of the HashSet (they're class level variables):
private static HashSet<Board> seen = new HashSet<>();
And my Board.equals() method:
#Override
public boolean equals (Object b) {
Board otherBoard = (Board) b;
boolean equal = false;
if (this.M == otherBoard.getM() && this.N == otherBoard.getN()) {
equal = true;
// Each board has an ArrayList of Car objects, and boards are only
// considered equal if they contain the exact same cars
for (Car car : this.cars) {
if (otherBoard.getCar(car.getPosition()) == null) {
equal = false;
}
}
}
System.out.println(equal);
return equal;
}
You must implement Board.hashCode() to override the default Object-based version, in such a way that, per its contract, any two equal Board objects have the same hash code. If you do not, then your seen set does not in fact accomplish anything at all for you.
On another issue, I suspect that the way you're checking the boards' cars is not fully correct. If it works the way I think it does, it would consider these two boards to be equal:
. = empty space
* = part of a car
......
.**.*.
....*.
.*....
.*.**.
......
......
.*..**
.*....
......
.**.*.
....*.

java: Two Possible int Values: Score Tracker for a Game

I'm working on a project to create a Space Invaders style game:
I need to be able to keep score when a player hits the target (+1 point) or misses (-1 point).
I will call the recordScore() method when the player shoots at the alien entity, however, I am unsure how to set it up so that my value (int point) can either be 1 or -1.
This is what I currently have:
public void recordScore(int point){
if(/*an alien ship is hit*/){
point = 1;
}
else{
point = -1;
}
I will call the method as such:
//if there is a hit
recordScore(1)
//if there is no hit
recordScore(-1)
...which I feel is a hint but I feel like using the loop is incorrect as I feel that would not work with how the method will be called but I can't currently think of any other way to initialize the variable to two values (or fill the if clause).
This is thinking backwards:
public void recordScore(int point){
if(/*an alien ship is hit*/){
point = 1;
}
else{
point = -1;
}
You are trying to assign a value to a method parameter which is the exact opposite of what you should be doing. Remember that point is coming into this method with a value assigned and passed into it.
Instead use the value that the parameter holds to assign to the value of a class field, or in your case to increment or decrement the value of a field.
So something like:
public void recordScore(int point) {
score += point; // similar to score = score + point;
}
is closer to what you need. I have no idea if you have a score field and you may name it something else.
Note that you state:
I feel like using the loop is incorrect
If you're referring to to the if/else structure, please understand that this is not a loop but rather a program control flow statement or logic block. A loop would make code repeat itself, and examples include for loops and while loops.
If you will only want to increment or decrement score by 1, another option is to use a method that uses a boolean parameter. For example
public void attemptHit(boolean hitSuccessful) {
if (hitSuccessful) {
score++;
else {
score--;
}
}
and you'd call it like:
attemptHit(true); // for a successful hit
attemptHit(false); // for a miss
This will prevent nonsense but valid code from being created such as
recordScore(-23020);

Java 7 card poker hand evaluator

I'm trying to create a hand evaluator that it will allow me to compare if one hand is better than another. I know there many other post on SO about this topic however many of them are old now and the links no longer link to anything useful. The only way I can think of doing this at the moment is to manually check for every different combination. Eg check for ace of any suit, if this doesn't exist then move to the next combination eg straight flush then 4 of a kind and so on. However, then how would you compare a pair of 2s to a pair of 3s unless you gave an integer to every combination of cards that made something interesting. However, that would very hard to do manually. Is there a better way?
Why hard?
class Card{
String suite;
int value;
....
}
// ...if two combinations are equal, Do for both combinations
int power = 0;
for (Card card: combination){
power += card.getValue()
}
// and compare!
I don't know if this is the best approach, but this could be possible and this is all manually.
Let's say you already have the code to determine which hand the player has in this format:
22s, KKs, 98o, 11o
Now you have an array with three values e.g.:
["K", "K", "s"]
...and another array:
[9, 8, "o"]
You first have to class those hands (like flush, straight etc.) to make sure which one will win (royal flush always win). And after those checks, you have to do some checks in the array. Check if it's suited or offsuit, if "K" is higher than 9 etc.
You can give them values like this:
...
8=8
9=9
10=10
J=11
Q=12
K=13
A=14 (or 1)
And then compare with that. This is a hard algorithm to do it properly without doing so many things manually. I hope someone who has experience with this takes my answer over and recover my mistakes or wrong steps/thoughts.
I would separate the problem for each type of combinations, and assign an integer for a specific occurence of a combination called ie. strength (so a Straight Flush of 5-4-3-2-A is the weakest and K-Q-J-10-9 is the strongest).
Individual combinations can be handled pretty well i think. For a royal flush, you sort your 7 cards by their number descending, and check if the first 5 cards are (A-K-Q-J-10) and if they are of the same suit. A royal flush's strength is indefinite.
For flush you can sort your cards by suit, and check if you can move 4 times in your list of card without witnessing a suit change. A Flush's strength is determined by the highest valued card of it.
A very brief template for the idea:
// main logic of who wins, note it doesn't handle when two players have the same
// combo with same strength
class HandComparator {
public Player compare(Player player1, Player player2) {
HandEvaluator handEvaluator = new HandEvaluator();
Combination player1Combo = handEvaluator.evaluate(player1.hand);
Combination player2Combo = handEvaluator.evaluate(player2.hand);
if (player1Combo.type.equals(player2Combo.type)) {
// note, strength is only taken into account if the two players have
// the same combo (ie both has full house)
if (player1Combo.strength < player2Combo.strength) {
return player2;
} else {
return player1;
}
} else if (player1Combo.type.compareTo(player2Combo.type) < 0) {
return player2;
} else {
return player1;
}
}
}
class Card {
int suit;
int number;
}
class Player {
List<Card> hand;
}
// this is built by CombinationRecognisers. Note, that the member 'strength' is
// related to a specific combination, not all possible hands
class Combination {
enum Type {
ROYAL_FLUSH,
STRAIGHT_FLUSH;
// etc.
}
Type type;
int strength;
}
// implement this for all combinations (ROYAL_FLUSH,STRAIGHT_FLUSH, etc)
interface CombinationRecogniser {
public Combination evaluate(List<Card> hand);
}
/*
* this class holds all CombinationRecognisers and iterates throught them. It
* will stop the moment a combo has been found.
*/
class HandEvaluator {
static List<CombinationRecogniser> recognizers = new ArrayList<CombinationRecogniser>();
static {
recognizers.add(new RoyalFlushRecogniser());
recognizers.add(new StraightFlushRecogniser());
}
public Combination evaluate(List<Card> hand) {
for (CombinationRecogniser recogniser : recognizers) {
Combination combination = recogniser.evaluate(hand);
if (combination != null) {
return combination;
}
}
return null;
}
}
class RoyalFlushRecogniser implements CombinationRecogniser {
#Override
public Combination evaluate(List<Card> hand) {
// code goes here that decides if the given hand is a valid royal flush
return null; // of new Combination() if the given hand is a valid royal flush
}
}
class StraightFlushRecogniser implements CombinationRecogniser {
#Override
public Combination evaluate(List<Card> hand) {
// code goes here that decides if the given hand is a valid straight flush
return null; // of new Combination() if the given hand is a valid royal flush
}
}
This code actually works if you implement the CombinationRecogniser interface for all special combinations. An example:

Jigsaw Puzzle Solver Method

Ok, so I have a 3 x 3 jig saw puzzle game that I am writing and I am stuck on the solution method.
public Piece[][] solve(int r, int c) {
if (isSolved())
return board;
board[r][c] = null;
for (Piece p : pieces) {
if (tryInsert(p, r, c)) {
pieces.remove(p);
break;
}
}
if (getPieceAt(r, c) != null)
return solve(nextLoc(r, c).x, nextLoc(r, c).y);
else {
pieces.add(getPieceAt(prevLoc(r, c).x, prevLoc(r, c).y));
return solve(prevLoc(r, c).x, prevLoc(r, c).y);
}
}
I know I haven't provided much info on the puzzle, but my algorithm should work regardless of the specifics. I've tested all helper methods, pieces is a List of all the unused Pieces, tryInsert attempts to insert the piece in all possible orientations, and if the piece can be inserted, it will be. Unfortunately, when I test it, I get StackOverflow Error.
Your DFS-style solution algorithm never re-adds Piece objects to the pieces variable. This is not sound, and can easily lead to infinite recursion.
Suppose, for example, that you have a simple 2-piece puzzle, a 2x1 grid, where the only valid arrangement of pieces is [2, 1]. This is what your algorithm does:
1) Put piece 1 in slot 1
2) It fits! Remove this piece, pieces now = {2}. Solve on nextLoc()
3) Now try to fit piece 2 in slot 2... doesn't work
4) Solve on prevLoc()
5) Put piece 2 in slot 1
6) It fits! Remove this piece, pieces is now empty. Solve on nextLoc()
7) No pieces to try, so we fail. Solve on prevLoc()
8) No pieces to try, so we fail. Solve on prevLoc()
9) No pieces to try, so we fail. Solve on prevLoc()
Repeat ad infinitum...
As commenters have mentioned, though, this may only be part of the issue. A lot of critical code is missing from your post, and their may be errors there as well.
I think you need to structure your recursion differently. I'm also not sure adding and removing pieces from different places of the list is safe; much as I'd rather avoid allocation in the recursion it might be safest to create a list copy, or scan the board
so far for instances of the same piece to avoid re-use.
public Piece[][] solve(int r, int c, List<Piece> piecesLeft) {
// Note that this check is equivalent to
// 'have r and c gone past the last square on the board?'
// or 'are there no pieces left?'
if (isSolved())
return board;
// Try each remaining piece in this square
for (Piece p : piecesLeft) {
// in each rotation
for(int orientation = 0; orientation < 4; ++orientation) {
if (tryInsert(p, r, c, orientation)) {
// It fits: recurse to try the next square
// Create the new list of pieces left
List<Piece> piecesLeft2 = new ArrayList<Piece>(piecesLeft);
piecesLeft2.remove(p);
// (can stop here and return success if piecesLeft2 is empty)
// Find the next point
Point next = nextLoc(r, c);
// (could also stop here if this is past end of board)
// Recurse to try next square
Piece[][] solution = solve(next.x, next.y, piecesLeft2);
if (solution != null) {
// This sequence worked - success!
return solution;
}
}
}
}
// no solution with this piece
return null;
}
StackOverflowError with recursive functions means that you're either lacking a valid recursion stop condition or you're trying to solve too big problem and should try an iterated algorithm instead. Puzzle containing 9 pieces isn't too big problem so the first thing must be the case.
The condition for ending recursion is board completion. You're only trying to insert a piece in the for loop, so the problem is probably either that the tryInsert() method doesn't insert the piece or it doesn't get invoked. As you're sure that this method works fine, I'd suggest removing break; from
if (p.equals(prev[r][c]))
{
System.out.println("Hello");
break;
}
because it's the only thing that may prevent the piece from being inserted. I'm still unsure if I understand the prev role though.

Categories

Resources