简体   繁体   中英

Matching Card Game in Java

Hi,

I'm making a matching card game and I don't understand how to actually do it. I was hoping someone could help explain what I can do to figure this out.

The following are the specifications:

In a card game of Pairs the goal is to turn over pairs of matching cards.

https://en.wikipedia.org/wiki/Concentration_(game) Here are the rules for the variation of Pairs we consider.

At the start of the game, there are n cards face-down, where n is a multiple of 4. There are 4 cards of each type, and the cards are labeled with letters a, b, . . . . For example, if n==24, there are 6 types of cards: a, b, c, d, e, and f. Say 1*4<=n and n<=4*26.

At each turn, the player flips 2 cards, one at a time, that are face-down. If the 2 flips are of the same type, the matched cards are left face-up. If the 2 flips mismatch, the mismatched cards are returned to the face-down position. The game ends when all cards are matched, and the score is the total number of flips made. (Flipping a pair of cards counts as 2 flips, so the best possible score is n flips.)

Write a pubic class titled MatchCardGame with the following members that implement this game of Pairs. The starter code in PlayCard.java should give you an idea of how MatchCardGame is used.

MatchCardGame should have no other public fields, methods, and constructors aside from the ones specified. However, it may and should have additional private fields, methods, or constructors.

The field

public final int n;

is the size of the game set by the constructor.

The constructor

public MatchCardGame(int n);

initializes a card game with a total of n cards. Assume n is a multiple of 4 and that 4<=n && n<=4*26. Without shuffling (explained in Problem 2) cards 0,1,2, and 3 should be a, cards 4,5,6, and 7 should be b, and so on.

The method

public String boardToString();

converts the state of the board to an appropriate String representation. You have freedom to choose your own representation, but it must reasonably represent the state of the game.

The method

public boolean flip(int i);

plays card number i. If card i cannot be played because it's face-up, or if i is an invalid card number, then return false. If i is a card number that can be played, play card i and return true.

The method

public boolean wasMatch();

returns true if the previous pair was a match and returns false otherwise. This method should be called only after flip has been successfully called an even number of times and before flipMismatch is called. (A successful call of flip is a call that results in a flip and returns true.)

The method

public char previousFlipIdentity();

returns the face of the previously flipped card as a char. This method should only be called after a card has been flipped.

The method

public void flipMismatch();

reverts the mismatched pair to face-down position. This method should only be called after a 2 calls of flip results in a mismatch.

The method

public boolean gameOver();

returns true if all cards have been matched and the game is over and returns false otherwise. The method public int getFlips();

returns the total number of card flips that have been performed so far.

Remark. MatchCardGame represents the physical state of the game, not the player. MatchCardGame has nothing to do with game strategies a human or AI player might employ.

Remark. The problem specifies how these methods should be used. For example, the input n of MatchCardGame's constructor needs to be a multiple of 4. You do not have to do any sort of error handling when these requirements are violated, although using asserts will help debugging.

So far, I have the following:

public class MatchCardGame {
//Private classes
private boolean facingup;
private char[] board;
private int flips = 0;
private int matches = 0;
private int currentflip;

//Public classes
public final int n;

public MatchCardGame(int n) {
    for (int i = 0; i < n; i++) {
        if (i % 4 == 0) {
            this.board[i] = 'a';
        }
        else if (i % 4 == 1) {
            this.board[i] = 'b';
        }
        else if (i % 4 == 2) {
            this.board[i] = 'c';
        }
        else {
            this.board[i] = 'd';
        }
    }
}

public String boardToString() {
    String stringboard = "";
    for (int i; i < n; i++) {
        if (facingup){
            stringboard += stringboard + "[" + this.board[i] + "] ";
        }
        else {
            stringboard += "[-] ";
        }
    }
    return stringboard;
}

public boolean flip(int i) {
    flips++;
    if (i < 0 || i >= n || currentflip == ((int) this.board[i]) % 32) {
        return false;
    }
    else {
        if (flips % 2 != 0) {
            currentflip = ((int) board[i]) % 32;
            facingup = true;
            return true;
        }
        else if (board[i] == this.board[i]) {
            currentflip = -1;
            this.facingup = true;
            board [i] = '0';
            this.board[i] = '0';
            matches += 2;
            return true;
        }
    }
}

public boolean wasMatch() {
    if (currentflip == -1) {
        return true;
    }
    else {
        return false;
    }
}

public char previousFlipIdentity() {
    return board [i];
}

public void flipMismatch() {
    facingup = false;
    this.facingup = false;

}

public boolean gameOver() {
    if (matches == n) {
        return true;
    }
    else {
        return false;
    }
}

public int getFlips() {
    return flips;
}}

Any assistance would be appreciated.

Try to walk through it in your mind.

  • You have been given a set of cards
  • One card, x is flipped
  • Other card is flipped next; if it's the same as the previous x , remove both cards
  • If it's not the same as the previous, ignore both flips.
  • Continue these steps till all cards are matched and no cards are remaining

So to convert it into code, what are the things you need to keep track of?

  • All cards and their types ( a , b and so on)
  • State of card: Flipped or not flipped
  • General state of all cards: Matched or still present (remember, if it's matched, we remove it)
  • Number of flips

How can we keep track of this?

  • We can keep track of the type of card in the array char[] board
  • Maintain a private int flips to keep track of number of flips, and private int matches to keep track of matches, initially 0
  • Maintain a private int currentlyFlippedCard to store the 1st flipped card's index.
  • If it's the first flip, store it in currentlyFlippedCard .
  • Increment int flips every time a card is flipped( flips++ ).
  • If it's the second flip, check if the type of card matches the type of card in currentlyFlippedCard .
    • How do you know if the flip is first or second? Because we increment flips every time.
    • For the first flip, flip == 1 ; second, flip == 2 ; if it's flipped again, it becomes flip == 3 , which we should take as the first flip.
    • From this, we can say that when flip is odd, it's the first flip, and when flip is even, it's the second.
  • If both flips do not match: don't make any changes.
  • If both flips match: change both index of both flips to '0' in char[] board to mark it as inactive; increment int matches by 2
  • So next time flip( i ) is called, check if board[i] != '0' , which will make sure it's still active in the game
  • How do you know if the game is over? If all cards are matched, game is over. So if matches == n , all cards are matched.
  • You need to know if the previous flip was a match(for wasMatch() ). For this, you can maintain a boolean to keep track of it; or another way is, you can use the variable currentlyFlippedCard itself.
    For the second way:
    • When second flip is not a match, do nothing( currentlyFlippedCard will have the index of previous flip, meaning currentlyFlippedCard >= 0 )
    • When second flip is a match, along with incrementing matches , set currentlyFlippedCard = -1 .
    • When you need to call wasMatch() , return true if flips is even and currentlyFlippedCard == -1 .
  • For boardToString() , just put all chars from board[] in a String one by one using a loop.
    • Here, 0 will mean it's matched; you can just add an if check to see if it's == 0 and change it to another character while inserting into the String .
    • Same goes for currently flipped card; you can just check when that index comes, and add a * or something to indicate it's flipped.

This is a brief overview, you just have to convert it into code. I have so far refrained from adding actual code, since it'll help you if you try it out yourself.
All the best, keep learning: :)

Edit 1(after comments):
I'm guessing wasMatch() is called after every 2nd flip? I assumed it won't be, and accidentally put the incrementing indexes in flip() .
So since wasMatch() is a separate method, you can maintain 2 variables for the flipped cards(say currentlyFlippedCard1 and currentlyFlippedCard2 ), and increment during wasMatch() .
As for flipMismatch() : Specs say it should 'revert it to facedown position'. You can either make no changes, or change currentlyFlippedCard1 and currentlyFlippedCard2 to some default value like -2 .

Edit 2(after comments):
For previousFlipIdentity() :

  • Check int flips to see if the previous flip was first or second flip(by checking if int flips is odd or even)
  • If first flip, return board[currentlyFlippedCard1]
  • If second flip, return board[currentlyFlippedCard2]

My suggestion is: implement core methods you know first. Once you get some methods running, you will have a better idea, and you can add in more functionality.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM