首页 > 解决方案 > Java中的匹配纸牌游戏

问题描述

你好,

我正在制作一个匹配的纸牌游戏,但我不明白该怎么做。我希望有人可以帮助解释我能做些什么来解决这个问题。

以下是规格:

在对子的纸牌游戏中,目标是翻转配对的纸牌。

https://en.wikipedia.org/wiki/Concentration_(game) 以下是我们考虑的 Pairs 变化规则。

游戏开始时有n张面朝下的牌,其中n是4的倍数。每种牌有4张,牌上标有字母a、b、...。. . . 例如,如果 n==24,则卡片有 6 种类型:a、b、c、d、e 和 f。说 1*4<=n 和 n<=4*26。

在每一轮,玩家翻转 2 张牌,一次一张,面朝下。如果两次翻转的类型相同,则匹配的牌面朝上。如果 2 次翻转不匹配,则不匹配的卡将返回面朝下位置。当所有牌都匹配时,游戏结束,得分是翻转的总数。(翻转一对牌算作 2 次翻转,因此最好的分数是 n 次翻转。)

编写一个名为 MatchCardGame 的公共类,其中包含实现此对子游戏的以下成员。PlayCard.java 中的起始代码应该让您了解如何使用 MatchCardGame。

除了指定的之外,MatchCardGame 应该没有其他公共字段、方法和构造函数。但是,它可能而且应该有额外的私有字段、方法或构造函数。

公共最终诠释 n;

是构造函数设置的游戏大小。

构造函数

公共 MatchCardGame(int n);

初始化一个总共有 n 张牌的纸牌游戏。假设 n 是 4 的倍数并且 4<=n && n<=4*26。没有洗牌(在问题 2 中解释)牌 0、1、2 和 3 应该是 a,牌 4、5、6 和 7 应该是 b,依此类推。

方法

公共字符串 boardToString();

将板的状态转换为适当的字符串表示。您可以自由选择自己的代表,但它必须合理地代表游戏的状态。

方法

公共布尔翻转(int i);

玩卡号 i。如果卡 i 因为正面朝上而无法打出,或者如果 i 是无效卡号,则返回 false。如果 i 是可以打的牌号,打出牌 i 并返回 true。

方法

公共布尔 wasMatch();

如果前一对是匹配的,则返回 true,否则返回 false。只有在成功调用了偶数次之后,并且在调用 FlipMismatch 之前,才应调用此方法。(成功调用翻转是导致翻转并返回 true 的调用。)

方法

public char previousFlipIdentity();

将先前翻转的卡片的面作为字符返回。此方法仅应在翻牌后调用。

方法

公共无效翻转不匹配();

将不匹配的对恢复为面朝下位置。只有在两次调用翻转导致不匹配后才应调用此方法。

方法

公共布尔游戏结束();

如果所有卡都匹配并且游戏结束,则返回 true,否则返回 false。方法 public int getFlips();

返回到目前为止已执行的卡片翻转总数。

评论。MatchCardGame 代表游戏的物理状态,而不是玩家。MatchCardGame 与人类或 AI 玩家可能采用的游戏策略无关。

评论。问题指定了如何使用这些方法。例如,MatchCardGame 的构造函数的输入 n 需要是 4 的倍数。当违反这些要求时,您不必进行任何类型的错误处理,尽管使用断言将有助于调试。

到目前为止,我有以下内容:

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

任何援助将不胜感激。

标签: java

解决方案


试着在你的脑海中走过它。

  • 您已获得一组卡片
  • 一张牌,x被翻转
  • 接下来翻另一张牌;如果和之前一样x,把两张卡都去掉
  • 如果与前一个不同,则忽略两次翻转。
  • 继续这些步骤,直到所有卡片都匹配并且没有剩余卡片

那么要将其转换为代码,您需要跟踪哪些内容?

  • 所有卡片及其类型(ab
  • 卡片状态:翻转或未翻转
  • 所有卡片的一般状态:匹配或仍然存在(请记住,如果匹配,我们将其移除)
  • 翻转次数

我们如何跟踪这一点?

  • 我们可以跟踪数组中卡片的类型char[] board
  • 维护 aprivate int flips以跟踪翻转次数,并private int matches跟踪比赛,最初0
  • 维护 aprivate int currentlyFlippedCard以存储第一张翻转卡片的索引。
  • 如果是第一次翻转,请将其存储在currentlyFlippedCard.
  • int flips每次翻转卡片时递增( flips++)。
  • 如果是第二次翻转,则检查卡片类型是否与 中的卡片类型匹配currentlyFlippedCard
    • 你怎么知道翻转是第一次还是第二次?因为我们flips每次都在增加。
    • 对于第一次翻转,flip == 1; 第二,flip == 2; 如果再次翻转,则变为flip == 3,我们应该将其作为第一次翻转。
    • 由此,我们可以说flip奇数时为第一次翻转,flip偶数时为第二次。
  • 如果两次翻转都不匹配:不要进行任何更改。
  • 如果两个翻转都匹配:将两个翻转的两个索引都更改为'0'inchar[] board以将其标记为非活动;递增int matches_2
  • 所以下次i调用 flip() 时,检查 if board[i] != '0',这将确保它在游戏中仍然处于活动状态
  • 你怎么知道比赛是否结束?如果所有卡都匹配,则游戏结束。因此,如果matches == n,则所有卡都匹配。
  • 您需要知道上一次翻转是否匹配(对于wasMatch())。为此,您可以维护一个boolean来跟踪它;或者另一种方式是,您可以使用变量currentlyFlippedCard本身。
    对于第二种方式:
    • 当第二次翻转不匹配时,什么都不做(currentlyFlippedCard将有前一次翻转的索引,意思是currentlyFlippedCard >= 0
    • 当第二次翻转匹配时,随着递增matches,设置currentlyFlippedCard = -1
    • 当需要调用wasMatch()时,返回trueifflips是偶数 and currentlyFlippedCard == -1
  • 对于,只需使用循环 boardToString()将所有字符board[]一个一个地放入其中。String
    • 在这里,0将意味着它是匹配的;您只需添加一个if检查以查看它是否为 ==0并在插入String.
    • 当前翻转的卡片也是如此;您可以检查该索引何时出现,并添加 a*或其他内容以指示它已翻转。

这是一个简短的概述,您只需将其转换为代码即可。到目前为止,我没有添加实际代码,因为如果您自己尝试一下,它会对您有所帮助。
一切顺利,继续学习!:)

编辑1(评论后):
我猜wasMatch()每第二次翻转后都会调用一次?我以为不会,并且不小心将递增索引放入flip().
因此,由于是一个单独的方法,您可以为翻转的卡片(比如和)wasMatch()维护 2 个变量,并在. 至于:规格说它应该“恢复到面朝下的位置”。您可以不进行任何更改,也可以将其更改为某些默认值,例如.currentlyFlippedCard1currentlyFlippedCard2wasMatch()
flipMismatch()currentlyFlippedCard1currentlyFlippedCard2-2

编辑2(评论后):
对于previousFlipIdentity()

  • 检查int flips前一个翻转是第一次还是第二次翻转(通过检查int flips是奇数还是偶数)
  • 如果第一次翻转,返回board[currentlyFlippedCard1]
  • 如果第二次翻转,返回board[currentlyFlippedCard2]

我的建议是:先实现你知道的核心方法。一旦你运行了一些方法,你就会有一个更好的想法,你可以添加更多的功能。


推荐阅读