2010-07-02 104 views
5

我正在实现一个简单的“玩你的卡片”(否则称为更高/更低)的游戏。如果你在规则非常简单之前还没有遇到过它。使用一套卡(例如心)。一次抽出一张卡,目的是正确猜测下一张卡的面值是高于还是低于先前抽取的卡的面值。Java - 简单游戏的设计建议

游戏的逻辑并不特别复杂,我并不担心这一点。我想出了一个设计,但我并不完全满意。有几个方面我确信它可以得到改进,这就是我希望得到您的建议。下面是这个类的接口(用于额外的理解意见,不实评论):

public interface PlayYourCardsRight { 

/** 
* Get the number of cards remaining with higher face values than the previously 
* drawn card 
* @return 
*/ 

public abstract int getNumberCardsHigher(); 

/** 
* Get the number of cards remaining with lower face values than the previously 
* drawn card 
* @return 
*/ 

public abstract int getNumberCardsLower(); 

/** 
* Get all cards that have already been drawn in the order they were drawn in 
* 
*/ 

public abstract List<Card> getPlayedCards(); 

/** 
* Simple prediction algorithm - if there are more cards left in the deck with 
* lower face values than the previous card, then predict 'Lower', if there 
* are more cards left in the deck with higher face values then predict 
* 'Higher', if there are equal numbers of higher/lower cards pick 'higher' or  'lower' 
* at random 
* 
* Prediction is an Enum (Higher/Lower/None) 
* 
*/ 

public abstract Prediction getPrediction(); 

/* 
* Draw the next card at random 
*/ 

public abstract void nextRound(); 

/** 
* Specifiy what the next card should be 
* 
* @param card 
*/ 

public abstract void nextRound(Card card); 

} 

正如你可以看到它是所有相当自我解释和简单。这里是我的问题:

我不希望构造函数自动绘制一张卡片。这意味着最初没有“先前绘制的卡”。我在Prediction枚举中有一个NO PREDICTION值,但由于没有“先前绘制的牌”,所以getNumberCardsHigher()getNumberCardsLower()方法不能返回理智值(当套牌中的所有牌都被绘制时,它们不能返回理智值)。

显然,我可以简单地抛出一个异常,但这看起来像是矫枉过正 - 尤其是随后所有对这些方法的调用都必须被包装在try/catch中。我也不满意返回一个负值,因为如果有人忘记/不能检查它们,很容易导致一些错误。

欢迎任何建议!

回答

4

我个人不要认为在参数检查的情况下抛出未经检查的异常根本就是矫枉过正的 - 这是假设你的代码断言了一个无效的状态(你不应该在该状态下调用那些方法,EVER)。

我通常使用IllegalArgumentException来表明参数已传入,但不符合方法调用的约定,并且IllegalStateException表明该对象此时不处于方法调用状态。

因为它们都是未经检查的异常,所以您不必尝试/捕获它们,只要让它们冒泡,它们就会执行异常很好的事情 - 它们会给您一个堆栈跟踪并准确告诉您错误的位置包括不正确地调用它的人。

我通常的方式使用某种类型的字符串,你的情况可能是:

throw new IllegalStateException("You cannot call this method until a card has been drawn"); 

按道理它只是没有意义的问,如果卡比卡更高或更低的那不存在。

现在,如果你的方法实际上抛出异常,那么你必须继续并修复你的代码,这样它才能在绘制卡之前调用该方法 - 所以你必须弄清楚如何绘制不管你的第一张卡片。

注意:异常仅用于错误检测,避免将它们用于流量控制。这意味着您不应该尝试捕捉异常并使用它来绘制卡片,然后再次调用!相反,您应该采用这样的方式进行编程,以保证在第一次调用方法之前绘制卡片。

0

我会争辩说,如果没有先前绘制的卡片,这两种方法都应返回card.count。还有相同数量的更低和更高的卡片,并且对于两个卡片都有更多更高/更低的卡片。你的算法然后会工作并返回一个NO_PREDICTION

+0

在这种情况下,我认为这两种方法都不会返回'card.count'。这个解决方案表明,有13张牌更高,13张牌更低,这意味着总共26张牌,即使在一套西装和游戏中只有13张牌。即使我们知道发生了什么,想象将这些信息呈现给用户。这似乎是一个非常不满意的行为。 – Peter 2010-07-02 16:45:57

+0

@Peter:我的推理如下:一张卡比卡片的缺失更低和更高。这是两个相反的状态在虚无概念上是平等的情况之一。这对我来说似乎并不直观,但这只是我的看法。当没有卡时,两者都应该返回0,所以它们在该阶段也是相等的。在开始时,它们应该返回相反的0,在这种情况下card.count。 – JRL 2010-07-02 17:05:03

0

我个人建议在玩家做任何事情之前先准备一张初始牌,因为玩家在第一张牌出现之前做任何事情都没有意义,但我认为“我不想让构造函数自动画卡“意味着你不想那样做。如果你不想这样做,我会让这些函数抛出异常,并且让这些调用它们的代码(预测函数)在游戏开始时返回“不预测”而不是甚至试图调用它们。比赛结束并不是特例,这两个函数应返回0,因为没有卡高于或低于其余的甲板

另外,补卡,没有必要宣布各功能abstract在一个接口,它是自动的,需要

+0

关于游戏结束的有趣(和正确的观点),我应该想到这一点!但是,我正在寻找使用例外的替代解决方案,甚至彻底改变了我的设计。 – Peter 2010-07-02 16:43:04

+0

为了清楚起见,我知道您不必将接口方法声明为抽象,Eclipse在我提取接口时会自动执行此操作(出于某种原因)。 **希望你可以编辑评论** – Peter 2010-07-02 16:50:25

+0

@Peter你可以,但只有五分钟:) – 2010-07-02 16:52:25

1

我不希望构造函数自动绘制一张卡片。这意味着最初没有“先前绘制的卡片”。我在预测枚举中有一个NO PREDICTION值,但由于没有“先前绘制的卡片”,getNumberCardsHigher()和getNumberCardsLower()方法不能返回理智值(它们不能在所有卡片都返回时返回理智值已被绘制)。

我觉得API产生了困惑的事实,你PlayYourCardsRight接口试图两回事模式:游戏引擎/规则的扑克牌。我会将卡片组和剩余卡片计数方法的状态移至Deck班。我会将API更改为getNumberCards[Higher/Lower](Card),并让游戏引擎指定要比较哪张牌,而不是期待牌组记下哪张牌是最后绘制的,我将其看作是游戏状态的一个元素,而不是牌组。

我强烈建议编写一些JUnit测试。 TDD有助于产生一个有凝聚力的解耦API。