C# 将项目从一个阵列移动到另一个阵列的优雅技术
背景:纸牌游戏;我想以一种干净的方式将牌从一副牌中分发给游戏中的每个玩家 这就是我的想法:C# 将项目从一个阵列移动到另一个阵列的优雅技术,c#,arrays,pass-by-reference,C#,Arrays,Pass By Reference,背景:纸牌游戏;我想以一种干净的方式将牌从一副牌中分发给游戏中的每个玩家 这就是我的想法: public static CardGame.IGame DealAll(this CardGame.IGame objThis, CardGame.Card[] cards) { if (objThis.Players.Length > 0) { for (int i = 0; i < cards.Length; i++)
public static CardGame.IGame DealAll(this CardGame.IGame objThis, CardGame.Card[] cards)
{
if (objThis.Players.Length > 0)
{
for (int i = 0; i < cards.Length; i++)
{
objThis.Deck.MoveTo(cards[i], objThis.CurrentPlayer.Hand);
objThis.AdvancePlayer();
}
}
return objThis;
}
public static Card[] MoveTo(this Card[] objThis, Card card, Card[] cards)
{
List<Card> lstCards = cards.ToList();
List<Card> lstThis = objThis.ToList();
lstThis.Remove(card);
lstCards.Add(card);
objThis = lstThis.ToArray();
cards = lstCards.ToArray();
return cards;
}
public static CardGame.IGame dealll(此CardGame.IGame对象,CardGame.Card[]卡)
{
如果(objThis.Players.Length>0)
{
对于(int i=0;i
当然,您可以看到参考问题。使用ref关键字会导致一些不太好看的代码,但这可能是不可避免的。有什么建议吗
我更喜欢一个足够灵活的解决方案来处理其他“传牌”情况(玩家将牌打到牌堆,将牌从牌堆移动到“垃圾”牌堆等)。好吧,一个简单的方法是首先不使用数组。从一开始就使用列表,你不需要重新分配等等-只需从牌堆中移除并添加到手上即可。你可能想考虑使用“<代码>队列>代码>。 更实用的方法是使用不可变集合和ref参数,但如果没有一些好的不可变集合类,这就不太实用。(它们是可用的,但没有内置到框架中。) 为什么要将卡片数组传递到方法中?难道它不应该处理甲板上的所有东西吗?在这一点上,更容易写:
foreach (Card card in deck)
{
CurrentPlayer.Hand.Add(card);
AdvancePlayer();
}
deck.Clear();
(顺便说一句,我不知道你为什么在这里使用扩展方法。这看起来更适合作为实例方法。)好吧,一个简单的方法是首先不使用数组。从一开始就使用列表,你不需要重新分配等等-只需从牌堆中移除并添加到手上即可。你可能想考虑使用“<代码>队列>代码>。 更实用的方法是使用不可变集合和ref参数,但如果没有一些好的不可变集合类,这就不太实用。(它们是可用的,但没有内置到框架中。) 为什么要将卡片数组传递到方法中?难道它不应该处理甲板上的所有东西吗?在这一点上,更容易写:
foreach (Card card in deck)
{
CurrentPlayer.Hand.Add(card);
AdvancePlayer();
}
deck.Clear();
(顺便说一句,我不知道你为什么要在这里使用扩展方法。这看起来更适合作为实例方法。)我认为这对于
数组来说是一个糟糕的情况,数组通常不会被重复地添加和删除。此外,我不会将此作为扩展方法,因为它与应用程序中的几个选定位置无关
考虑只使用一个列表,并使用一个负责移动的类方法
public class CardDealer {
...
private List<Card> _deck;
// Put the card [c] into [hand], and remove it from the deck.
public void Deal(List<Card> hand, Card c) {
_deck.Remove(c);
hand.Add(c);
}
}
公共级信用卡经销商{
...
私人名单;
//将卡[c]放入[手],并将其从牌组中取出。
公开作废交易(名单手、c卡){
_甲板。拆除(c);
另加(c);
}
}
评论者建议将一副牌最好建模为一个队列,这是一个合理的点,取决于你是否只能从牌堆顶部取牌。如果是这样的话,考虑一下:
public class CardDealer {
...
private Queue<Card> _deck;
// Put the top card of the deck into the specified hand.
public void Deal(List<Card> hand) {
// Deck is a Queue now. No need to specify which card to take.
Card c = _deck.Dequeue();
hand.Add(c);
}
}
公共级信用卡经销商{
...
专用队列甲板;
//将牌组顶部的牌放入指定的手牌中。
公开作废交易(挂牌交易){
//牌组现在是一个队列。无需指定要拿哪张牌。
卡片c=_deck.Dequeue();
另加(c);
}
}
我认为这对于数组来说是一个糟糕的情况,它通常不会被重复地添加和删除。此外,我不会将此作为扩展方法,因为它与应用程序中的几个选定位置无关
考虑只使用一个列表,并使用一个负责移动的类方法
public class CardDealer {
...
private List<Card> _deck;
// Put the card [c] into [hand], and remove it from the deck.
public void Deal(List<Card> hand, Card c) {
_deck.Remove(c);
hand.Add(c);
}
}
公共级信用卡经销商{
...
私人名单;
//将卡[c]放入[手],并将其从牌组中取出。
公开作废交易(名单手、c卡){
_甲板。拆除(c);
另加(c);
}
}
评论者建议将一副牌最好建模为一个队列,这是一个合理的点,取决于你是否只能从牌堆顶部取牌。如果是这样的话,考虑一下:
public class CardDealer {
...
private Queue<Card> _deck;
// Put the top card of the deck into the specified hand.
public void Deal(List<Card> hand) {
// Deck is a Queue now. No need to specify which card to take.
Card c = _deck.Dequeue();
hand.Add(c);
}
}
公共级信用卡经销商{
...
专用队列甲板;
//将牌组顶部的牌放入指定的手牌中。
公开作废交易(挂牌交易){
//牌组现在是一个队列。无需指定要拿哪张牌。
卡片c=_deck.Dequeue();
另加(c);
}
}
也许是这样的
interface ICardPile
{
ICollection<Card> Cards
{
get;
}
}
interface IOrderedCardPile : ICardPile // FIXME Better name.
{
}
class Deck : ICardPile
{
private Stack<Card> _cards = new Stack<Card>();
ICollection<Card> Cards
{
get
{
return _cards;
}
}
public Deck()
{
// TODO Fill deck.
}
public void DealCardsTo(IEnumerable<ICardPile> piles, int cardCount)
{
for(int i = 0; i < cardCount; ++i)
{
foreach(var pile in piles)
Cards.MoveSomeTo(piles, 1);
}
}
}
class Hand : IOrderedCardPile
{
private HashSet<Card> _cards = new HashSet<Card>();
ICollection<Card> Cards
{
get
{
return _cards;
}
}
}
也许是这样的
interface ICardPile
{
ICollection<Card> Cards
{
get;
}
}
interface IOrderedCardPile : ICardPile // FIXME Better name.
{
}
class Deck : ICardPile
{
private Stack<Card> _cards = new Stack<Card>();
ICollection<Card> Cards
{
get
{
return _cards;
}
}
public Deck()
{
// TODO Fill deck.
}
public void DealCardsTo(IEnumerable<ICardPile> piles, int cardCount)
{
for(int i = 0; i < cardCount; ++i)
{
foreach(var pile in piles)
Cards.MoveSomeTo(piles, 1);
}
}
}
class Hand : IOrderedCardPile
{
private HashSet<Card> _cards = new HashSet<Card>();
ICollection<Card> Cards
{
get
{
return _cards;
}
}
}
我没听说过排队课,但我会查一查。我忘了提到这一点,但我想在其他“传牌”情况下(打牌、将牌移到“垃圾”牌组等)使用足够灵活的方法。扩展方法似乎很合适。我想这样你会得到更多的复杂代码。我会认真建议以最简单的方式写它,然后考虑重用,当你实际上在多个地方得到类似的代码。FWIW,我同意乔恩。当您需要扩展类的行为而无法控制它时,应该使用扩展方法。但是您不需要扩展集合的行为;你只想做一些涉及收集的事情。我没有听说过队列类,但我会去看看。我忘了提到这一点,但我想要一些足够灵活的东西,以便在其他“传卡”情况下使用