[转载]一步一步用C#编写三国杀(三):设计流程 - 忘却之都 - 博客园

[转载][原创]一步一步用C#编写三国杀(三):设计流程 – 忘却之都 – 博客园.

前面已经说了牌堆的设计,那么现在就正式进入流程,满足我们在(一)中所说的需求。

由于在(二)中已经说了要维护扩展,因此对于之前定义的Scene,则需要定义一个所选择的扩展包,代码如下:

扩展包

private readonly IPackage[] selectedPackages;

/// <summary>
/// 初始化新的<see cref=”Scene”/>类的实例。
/// </summary>
/// <param name=”packages”>所要加载的包。</param>
public Scene(IEnumerable<IPackage> packages)
{
players[currentToken].HasToken
= true;
selectedPackages
= packages.ToArray();
}

由于玩家是轮动的,因此设定一个令牌,只有持有令牌的玩家才能行动。

private int currentToken;

那么定义一个Start方法,开始游戏循环。

首先要根据选择的扩展包生成游戏牌堆。对于游戏牌堆,由于我们之前已经定义好了牌堆基类,因此实现就比较简单了,将扩展包中的游戏牌载入并洗牌即可。

游戏牌堆

/// <summary>
/// 表示游戏牌牌堆。
/// </summary>
public sealed class GameCardHeap : CardHeap<GameCard>
{
/// <summary>
/// 初始化新的<see cref=”GameCardHeap”/>类的实例。
/// </summary>
/// <param name=”packages”>所要加载的扩展包。</param>
public GameCardHeap(IEnumerable<IPackage> packages)
{
foreach (var package in packages)
{
((List
<GameCard>) Items).AddRange(package.GameCards);
}
Items.Shuffle();
}
}

回头看我们上面的Start方法,在牌堆创建后,就进入了流程循环,还是直接来代码吧,注释都写的蛮清楚的

流程循环

/// <summary>
/// 开始游戏。
/// </summary>
public void Start()
{
Player currentPlayer;
GameCardHeap heap
= new GameCardHeap(selectedPackages); // 创建牌堆

while(true)
{
currentPlayer
= players[currentToken]; // 设置当前有令牌的玩家

// 摸牌阶段
GameCard[] newCards = heap.Pop(2, true);
currentPlayer.Draw(newCards);

// 出牌阶段
while(currentPlayer.HasPlayableCard)
{
// NOTE:为了简单,先实现只杀下家,并只使用杀、闪、桃
int nextToken = currentToken == players.Length 1 ? 0 : currentToken + 1;
currentPlayer.Play(players[nextToken], currentPlayer.FirstPlayableCard);

if (IsGameEnds())
goto label;
}

// 弃牌阶段
// NOTE:为了简单,先实现只弃从头开始的牌到当前体力值
int disCardCount = currentPlayer.HandCards.Length currentPlayer.Hp;
if (disCardCount > 0)
{
GameCard[] removeCards
= currentPlayer.HandCards.Take(disCardCount).ToArray();
currentPlayer.Discard(removeCards);
}

// 将令牌给下一个人
GiveTokenToNext();
}
label:
Console.WriteLine(
游戏结束!);
}

这里使用了一个死循环,但在游戏结束的时候使用goto语句跳出循环。所涉及到的一些方法如下:

一些辅助方法

private void GiveTokenToNext()
{
if (currentToken == players.Length 1)
currentToken
= 0;
else
currentToken
++;

players[currentToken].HasToken = true;
}

private bool IsGameEnds()
{
return players.Any(p => p.IsDead); // 如果选择到IsDead的Player,游戏结束
}

注意,流程的设计中,由于玩家是在游戏逻辑边界内的,因此采用了主动的做法来进行设计。这样对于程序来说,我只要去考虑玩家的摸牌、出牌和弃牌所引起的各种变化即可。

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏