java - 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;
}}
任何援助将不胜感激。
解决方案
试着在你的脑海中走过它。
- 您已获得一组卡片
- 一张牌,
x
被翻转 - 接下来翻另一张牌;如果和之前一样
x
,把两张卡都去掉 - 如果与前一个不同,则忽略两次翻转。
- 继续这些步骤,直到所有卡片都匹配并且没有剩余卡片
那么要将其转换为代码,您需要跟踪哪些内容?
- 所有卡片及其类型(
a
等b
) - 卡片状态:翻转或未翻转
- 所有卡片的一般状态:匹配或仍然存在(请记住,如果匹配,我们将其移除)
- 翻转次数
我们如何跟踪这一点?
- 我们可以跟踪数组中卡片的类型
char[] board
- 维护 a
private int flips
以跟踪翻转次数,并private int matches
跟踪比赛,最初0
- 维护 a
private int currentlyFlippedCard
以存储第一张翻转卡片的索引。 - 如果是第一次翻转,请将其存储在
currentlyFlippedCard
. int flips
每次翻转卡片时递增(flips++
)。- 如果是第二次翻转,则检查卡片类型是否与 中的卡片类型匹配
currentlyFlippedCard
。- 你怎么知道翻转是第一次还是第二次?因为我们
flips
每次都在增加。 - 对于第一次翻转,
flip == 1
; 第二,flip == 2
; 如果再次翻转,则变为flip == 3
,我们应该将其作为第一次翻转。 - 由此,我们可以说
flip
奇数时为第一次翻转,flip
偶数时为第二次。
- 你怎么知道翻转是第一次还是第二次?因为我们
- 如果两次翻转都不匹配:不要进行任何更改。
- 如果两个翻转都匹配:将两个翻转的两个索引都更改为
'0'
inchar[] board
以将其标记为非活动;递增int matches
_2
- 所以下次
i
调用 flip() 时,检查 ifboard[i] != '0'
,这将确保它在游戏中仍然处于活动状态 - 你怎么知道比赛是否结束?如果所有卡都匹配,则游戏结束。因此,如果
matches == n
,则所有卡都匹配。 - 您需要知道上一次翻转是否匹配(对于
wasMatch()
)。为此,您可以维护一个boolean
来跟踪它;或者另一种方式是,您可以使用变量currentlyFlippedCard
本身。
对于第二种方式:- 当第二次翻转不匹配时,什么都不做(
currentlyFlippedCard
将有前一次翻转的索引,意思是currentlyFlippedCard >= 0
) - 当第二次翻转匹配时,随着递增
matches
,设置currentlyFlippedCard = -1
。 - 当需要调用
wasMatch()
时,返回true
ifflips
是偶数 andcurrentlyFlippedCard == -1
。
- 当第二次翻转不匹配时,什么都不做(
- 对于,只需使用循环
boardToString()
将所有字符board[]
一个一个地放入其中。String
- 在这里,
0
将意味着它是匹配的;您只需添加一个if
检查以查看它是否为 ==0
并在插入String
. - 当前翻转的卡片也是如此;您可以检查该索引何时出现,并添加 a
*
或其他内容以指示它已翻转。
- 在这里,
这是一个简短的概述,您只需将其转换为代码即可。到目前为止,我没有添加实际代码,因为如果您自己尝试一下,它会对您有所帮助。
一切顺利,继续学习!:)
编辑1(评论后):
我猜wasMatch()
每第二次翻转后都会调用一次?我以为不会,并且不小心将递增索引放入flip()
.
因此,由于是一个单独的方法,您可以为翻转的卡片(比如和)wasMatch()
维护 2 个变量,并在.
至于:规格说它应该“恢复到面朝下的位置”。您可以不进行任何更改,也可以将其更改为某些默认值,例如.currentlyFlippedCard1
currentlyFlippedCard2
wasMatch()
flipMismatch()
currentlyFlippedCard1
currentlyFlippedCard2
-2
编辑2(评论后):
对于previousFlipIdentity()
:
- 检查
int flips
前一个翻转是第一次还是第二次翻转(通过检查int flips
是奇数还是偶数) - 如果第一次翻转,返回
board[currentlyFlippedCard1]
- 如果第二次翻转,返回
board[currentlyFlippedCard2]
我的建议是:先实现你知道的核心方法。一旦你运行了一些方法,你就会有一个更好的想法,你可以添加更多的功能。
推荐阅读
- qt - Qt5 Openvino opencv cmake windows
- javascript - 使用日期时间字段填充 chartjs ajax
- ios - URLImage 永远不会在 SwiftUI 的小部件应用中加载图像
- excel - Excel VBA:将每个工作表名称更改为每个工作表中的单元格 A1 值
- kubernetes - 每次关闭并重新启动终端时,都要从 Homebrew 重新安装 Homebrew 和软件
- python - CMD颜色问题
- ios - 更改 PHPickerViewController 中右栏按钮的默认标题
- stack - 使用堆栈的中序遍历的正确性
- python - Python Pandas - 基于另一个完成/填充数据框
- android - 使用“Theme.of”会导致在小部件上重新构建