[原创]一步一步用C#编写三国杀(一):规则和需求描述

原创文章,转载请保留作者署名!

 

最近做翻译做的头疼,疼过之余,想想之前公司内组织的三国杀开发兴趣小组在三国杀开发问题上几乎又停滞了。于是又翻出来搞了搞,这次却搞的有点像模像样了,特地把思路和方法都共享出来,一起学习。

 

三国杀在上海是挺风靡的,如果你还不知道玩法和规则,请猛击这里

 

今天要说的是实现的第一步。为了尽量简化需求,我们最初要实现的东西也挺简单,就是能支持两个玩家自动对战。具体的描述如下:在一个场景中设置两个玩家,游戏的牌堆中只有三种基本牌:杀、闪、桃。其中,只有杀和桃是属于主动性游戏牌,即可以在自己行动回合将其打出;闪是被动性游戏牌,只有当别人对自己出杀的时候才可以出闪,否则扣除一点体力,而使用桃则为自己增加一点体力。同样,为了简化实现,只要有能使用的牌,就必须使用;而且,如果你的手牌数量大于体力值,则需要弃牌直到手牌数与体力值相等。在这种情况下,只要有一方体力为0,游戏结束!

 

对需求进行整理,不难发现有以下需求待实现:

1、游戏结束的条件:只要有玩家死亡即宣告结束。

2、牌堆的实现,注意牌堆中拿出的牌需要从牌堆中移除,以及洗牌的功能。

3、杀、闪、挑的逻辑实现。

4、从手牌中计算是否还有可用的牌。

5、玩家轮询行动的实现。

 

在设计中,我的思路是这样的:一局游戏实际都在一个场景中进行,直到游戏结束。因此首先有场景的定义:

 

/// <summary>
/// 表示游戏场景。
/// </summary>
public class Scene
{
    
private readonly Player[] players;
}

 

 

其中场景中定义了游戏玩家,因为场景中的游戏玩家在场景生成之后就固定了,所以使用了readonly。

 

同样,游戏实际是个循环,结束的条件就是有玩家死亡。因此,先定义玩家死亡的条件:

 

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

 

 

这样,由于其中引用到了Player类,因此,建立玩家类,来对其按照需求进行设计。代码如下:

 

Player
    /// <summary>
    
/// 表示游戏中的玩家。
    
/// </summary>
    public class Player
    {
        
private readonly List<GameCard> handCards = new List<GameCard>(20);

        
public Player(string name, byte maxHp)
        {
            
this.Name = name;
            
this.Hp = maxHp;
            
this.MaxHp = maxHp;
        }

        
/// <summary>
        
/// 表示该玩家的名称。
        
/// </summary>
        public string Name { getprivate set; }

        
/// <summary>
        
/// 表示该玩家是否已经死亡。
        
/// </summary>
        public bool IsDead
        {
            
get { return Hp == 0; }
        }

        
/// <summary>
        
/// 表示该玩家所选武将的当前HP.
        
/// </summary>
        public byte Hp { getprivate set; }

        
/// <summary>
        
/// 表示该玩家所选武将的最大HP.
        
/// </summary>
        public byte MaxHp { getprivate set; }
    }

 

 

其中的handCards表示玩家手中可以拿的手牌数量,这里设定上限为20张。那么同样要开始定义游戏卡牌,代码如下:

 

GameCard
    /// <summary>
    
/// 表示游戏中用作游戏的卡牌。
    
/// </summary>
    public abstract class GameCard
    {
        
/// <summary>
        
/// 表示牌的花色。
        
/// </summary>
        public CardMark Mark { getprotected set; }

        
/// <summary>
        
/// 表示牌的大小。
        
/// </summary>
        public CardValue Value { getprotected set; }

        
/// <summary>
        
/// 表示牌的名称。
        
/// </summary>
        public string Name { getprotected set; }

        
/// <summary>
        
/// 对目标玩家使用卡牌。
        
/// </summary>
        
/// <param name="source">使用卡牌的源对象。</param>
        
/// <param name="target">使用卡牌的目标对象。</param>
        public abstract void Use(Player source, Player target);
    }

 

 

直到现在,所需要的定义已经基本完成。这其中的代码有很多不规范的地方,之所以展现出来,也是为了表现自己的思维过程,在后面会有很多对目前代码的重构。

 

在这样定义完了之后,下一步将开始仔细分析流程,按照流程先写出最初能运行的版本。(未完待续...)

posted @ 2010-07-25 22:16 阅读(3970) 评论(14) 编辑 收藏

 回复 引用 查看   
#1楼2010-07-25 22:18 | xoyozo      
实际的规则比这复杂多了,特别是有风、EX等,还有,小心盛大告你侵权哦~~
 回复 引用 查看   
#2楼[楼主]2010-07-25 22:21 |       
我又不商业化,告什么告
 回复 引用 查看   
#3楼2010-07-25 22:28 | Sourire      
恩恩;支持。很不错的。很有钻研精神
 回复 引用 查看   
#4楼2010-07-26 08:31 | pcy      
LZ想法不错

不过IsGameEnds()这个函数按你的意思为什么不这样写
private bool IsGameEnds()
{
    return players.Any(p => p.IsDead);  // 如果选择到IsDead的Player,游戏结束
}

 回复 引用 查看   
#5楼2010-07-26 09:09 | lovecherry      
不错,翻译还是要抓紧哥们
 回复 引用 查看   
#6楼2010-07-26 09:10 | Franky      
有意思 ..关注下

 回复 引用 查看   
#7楼2010-07-26 09:28 | liy      
这个好
 回复 引用 查看   
#8楼[楼主]2010-07-26 09:32 |       
引用pcy:
LZ想法不错

不过IsGameEnds()这个函数按你的意思为什么不这样写
private bool IsGameEnds()
{
    return players.Any(p => p.IsDead);  // 如果选择到IsDead的Player,游戏结束
}


因为工作什么一直在2.0下,Linq什么不是太熟,所以写出来可能会有更多收获。

 回复 引用 查看   
#9楼2010-07-26 10:24 | liumingzhu      
在一个场景中设置两个玩家,游戏的牌堆中只有三种基本牌:杀、闪、桃。其中,只有杀和桃是属于主动性游戏牌,tiffany necklaces 即可以在自己行动回合将其打出;闪是被动性游戏牌,只有当别人对自己出杀的时候才可以出闪,否则扣除一点体力,chanel bags而使用桃则为自己增加一点体力。同样,为了简化实现,只要有能使用的牌,就必须使用;而且,如果你的手牌数量大于体力值,则需要弃牌直到手牌数与体力值相等。在这种情况下,只要有一方体力为0,游戏结束!


cheap ghd straighteners

 回复 引用 查看   
#10楼2010-07-26 11:16 | MagicHu      
这种东西的难点,第一,可扩展性,第二,AI。
其他的,没有难度。

 回复 引用 查看   
#11楼2010-07-29 14:37 | 花道长      
希望楼主能开发成功,我以前和一个同事一起搞过,后来失败了,那时候用的是java
 回复 引用 查看   
#12楼2010-07-29 16:31 | 小孩妮      
学习学习 牛人
 回复 引用 查看   
#13楼2010-12-26 11:23 | 呱噪      
我们是大一的学生,做了一个创新项目,跟WEB三国杀差不多,想请教一下
万智牌是最精彩的回合制桌面游戏,在对战中牌手扮演一位法术师,运用有限的法术力资源,召唤各种奇珍异兽冲锋陷阵,施展别具特色的法术咒语运筹帷幄,但由于其价格昂贵、规则复杂而限制了其普及,本项目拟开发在线万智牌对战系统,可以让用户实现在线的对战,并能实现规则的自动判定。
本项目的关键技术实现万智牌的在线游戏,主要研究内容包括
1. web图形和动画的显示
2. 游戏规则的抽象
3. 用户行为的网络传输
4. 卡牌信息的数据库存储
5. 自动对战技术
要做这个游戏需要学习那些方面的知识,请高手帮忙推荐几本入门的书籍。在整个过程中,需要什么样的步骤。整体思路是什么?我们现在很盲目,希望大侠帮忙交流一下你的想法谢谢

 回复 引用 查看   
#14楼2010-12-26 11:25 | 呱噪      
用C#和用java写有什么区别?如果可以我们想用java写