« | July 2025 | » | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | | |
| 公告 |
Sorry,这里只是一个网络收藏夹,收藏一些不得不收藏的文章。
|
Blog信息 |
blog名称:万色返空 日志总数:37 评论数量:116 留言数量:-3 访问次数:321190 建立时间:2004年12月25日 |

| |
[游戏]YU-GI-OH! POWER OF XLINQ [C#, XLINQ, XML] 文章收藏, 软件技术
尧天云 发表于 2005/11/2 18:00:52 |
转载于http://allenlooplee.cnblogs.com/archive/2005/10/13/253617.html
WRITTEN BY ALLEN LEE
0. TABLE OF CONTENT
1. YU-GI-OH! POWER OF XLINQ.
2. GAME CARDS.
3. <CARDS>...</CARDS>
4. CLASS CARD { ... }
5. GIVE ME WHAT I WANT!
6. SHOW ME THE RESULTS.
7. REFERENCES.
1. YU-GI-OH! POWER OF XLINQ.
如果你玩过游戏王的决斗怪兽游戏,你会发现一个好的卡片信息管理器能使你装备卡片组的工作事半功倍。例如,Yu-Gi-Oh! Power of Chaos 系列游戏就内置了一个简单的卡片信息管理器。
500)this.width=500'>
现在,我需要一个更强大的卡片信息管理器,代号为 Positron,它从各个方面对卡片信息进行筛选和排序,并协助我寻找合适的卡片装备到我的卡片组中。
2. GAME CARDS.
要管理好这些卡片,我们得首先了解这些卡片是如何分类的,以及它们包含了哪些信息。根据官方的说明,卡片的概要分类如下:
Monster Cards(怪兽卡)
A. Normal Monster Cards(普通怪兽卡)
B. Fusion Monster Cards(融合怪兽卡)
C. Ritual Monster Cards(仪式怪兽卡)
D. Effect Monster Cards(效果怪兽卡)
Spell Cards(魔法卡)
A. Normal Spell Cards(普通魔法卡)
B. Continuous Spell Cards(永续魔法卡)
C. Equip Spell Cards(装备魔法卡)
D. Field Spell Cards(场地魔法卡)
E. Quick-Play Spell Cards(速攻魔法卡)
F. Ritual Spell Cards(仪式魔法卡)
Trap Cards(陷阱卡)
A. Normal Trap Cards(普通陷阱卡)
B. Counter Trap Cards(反击陷阱卡)
C. Continuous Trap Cards(永续陷阱卡)
现在我们来细看每一种卡片上所包含的信息。所有的怪兽卡都包含了以下信息:
Monster Name(怪兽名字)
Attribute(属性)
Level(等级)
Type(类别)
Attack Points (ATK)(攻击力)
Defense Points (DEF)(防守力)
Card Description(卡片描述)
并由 Attribute 和 Type 来划分类别:
Attribute 枚举:
Earth(地属性)、Water(水属性)、Fire(炎属性)、Wind(风属性)、Light(光属性)、Dark(闇属性)
Type 枚举:
Type:Dragon(龙族)、Spellcaster(魔法使族)、Zombie(不死族)、Warrior(战士族)、Beast-Warrior(兽战士族)、Beast(兽族)、Winged Beast(鸟兽族)、Fiend(恶魔族)、Fairy(天使族)、Insect(昆虫族)、Dinosaur(恐龙族)、Reptile(爬虫族)、Fish(鱼族)、Sea Serpent(海龙族)、Machine(机械族)、Thunder(雷族)、Aqua(水族)、Pyro(炎族)、Rock(岩石族)、Plant(植物族)
500)this.width=500'>
上图所展示的是一张效果怪兽卡,它包含如下信息:
Monster Name(怪兽名字):Deepsea Warrior
Attribute(属性):Water
Level(等级):5
Type(类别):Warrior
Attack Points (ATK)(攻击力):1600
Defense Points (DEF)(防守力):1800
Card Description(卡片描述):When "Umi" is face-up on the field, this card is unaffected by any Spell Cards.
其中 Fusion Monster Cards 的 Card Description 上列出了融合所需的怪兽(Fusion-Material Monsters);Effect Monster Cards 的 Card Description 上描述了该效果怪兽的效果。
而 Spell Cards 和 Trap Cards 就比较简单,仅包含了:
Name(魔法卡或者陷阱卡的名字)
Category(魔法卡或者陷阱卡的类型)
Card Description(卡片描述)
500)this.width=500'>
3. <CARDS>...</CARDS>
接下来,我要为这些卡片信息建立 XML 表示模型。首先是怪兽卡的 XML 表示模型:
500)this.width=500'><monstercard img="500)this.width=500'>" category="500)this.width=500'>" name="500)this.width=500'>" attribute="500)this.width=500'>" level="500)this.width=500'>" type="500)this.width=500'>" atk="500)this.width=500'>" def="500)this.width=500'>">500)this.width=500'></monstercard>
其中,
img:指示该怪兽卡的图片位置。
category:指示该怪兽卡的类别。允许的值为 Normal、Effect、Fusion 或者 Ritual,分别表示普通怪兽、效果怪兽、融合怪兽或者仪式怪兽。虽然融合怪兽或者仪式怪兽也可以带有效果,但在正式的卡片归类里,这些怪兽将归入融合怪兽或者仪式怪兽类别。例如 Thousand-Eye Restrict 就既是融合怪兽也是效果怪兽,却被归类到融合怪兽里。
name:指示该怪兽卡的名字。
attribute:指示该怪兽的属性,允许的值如上面的 Attribute 枚举所示。
type:指示该怪兽的类型,允许的值如上面的 type 枚举所示。
level:指示该怪兽的等级,对应着卡片右上方的星星数目,其值为整数类型。
atk:指示怪兽的攻击力,其值为整数类型。
def:指示怪兽的防守力,其值为整数类型。
最后,mostercard 元素的内容则为卡片描述内容。
类似地,魔法卡的表示为:
500)this.width=500'><spellcard img="500)this.width=500'>" category="500)this.width=500'>" name="500)this.width=500'>">500)this.width=500'></spellcard>
其中,
img:指示该魔法卡的图片位置。
category:指示该魔法卡的类别。允许的值为 Normal、Continuous、Equip、Field、QuickPlay 或者 Ritual,分别表示普通魔法卡、永续魔法卡、装备魔法卡、场地魔法卡、速攻魔法卡或者仪式魔法卡。
name:指示该魔法卡的名字。
陷阱卡的表示为:
500)this.width=500'><trapcard img="500)this.width=500'>" category="500)this.width=500'>" name="500)this.width=500'>">500)this.width=500'></trapcard>
其中,
img:指示该陷阱卡的图片位置。
category:指示该陷阱卡的类别。允许的值为 Normal、Counter 或者 Continuous,分别表示普通陷阱卡、反击陷阱卡或者永续陷阱卡。
name:指示该陷阱卡的名字。
以下是一份示范代码:
500)this.width=500'> 500)this.width=500'> sample.xml Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->500)this.width=500'><?xml version="1.0" encoding="utf-8" ?>500)this.width=500'><cards>500)this.width=500'> <monstercards>500)this.width=500'> <monstercard img="Monster Cards\Barrel Dragon.jpg" category="Effect" name="Barrel Dragon" attribute="Dark" level="7" type="Machine" atk="2600" def="2200">Toss a coin 3 times. If 2 out of 3 results are Heads, destroy 1 monster on your opponent's side of the field. This card's effect can only be used during your own turn, once per turn.</monstercard>500)this.width=500'> <monstercard img="Monster Cards\Blue-Eyes White Dragon.jpg" category="Normal" name="Blue-Eyes White Dragon" attribute="Light" level="8" type="Dragon" atk="3000" def="2500">This legendary dragon is a powerful engine of destruction. Virtually invincible, very few have faced this awesome creature and lived to tell the tale.</monstercard>500)this.width=500'> <monstercard img="Monster Cards\Thousand-Eye Restrict.jpg" category="Fusion" name="Thousand-Eye Restrict" attribute="Dark" level="1" type="Spellcaster" atk="0" def="0">"Relinquished" + "Thousand-Eyes Idol". As long as this card remains face-up on the field, other monsters cannot change their positions or attack. This monster can take on the ATK and DEF of 1 opponent's monster on the field (a face-down monster results in an ATK and DEF of 0). Treat the selected monster as an Equip Spell Card and use it to equip "Thousand-Eyes Restrict". You may use this effect only once per turn and can equip "Thousand-Eyes Restrict" with only 1 monster at a time.</monstercard>500)this.width=500'> <monstercard img="Monster Cards\Magician of Black Chaos.jpg" category="Ritual" name="Magician of Black Chaos" attribute="Dark" level="8" type="Spellcaster" atk="2800" def="2600">This monster can only be Ritual Sommoned with the Ritual Spell Card, "Dark Magic Ritual". You must also offer monsters whose total Level Stars equal 8 or more as a Tribute from the field or your hand.</monstercard>500)this.width=500'> </monstercards>500)this.width=500'> <spellcards>500)this.width=500'> <spellcard img="Spell Cards\Dark Hole.jpg" category="Normal" name="Dark Hole">Destroys all monsters on the field.</spellcard>500)this.width=500'> </spellcards>500)this.width=500'> <trapcards>500)this.width=500'> <trapcard img="Trap Cards\White Hole.jpg" category="Normal" name="White Hole">When your opponent plays "Dark Hole", the monsters on your side of the field are not destroyed.</trapcard>500)this.width=500'> </trapcards>500)this.width=500'></cards>
4. CLASS CARD { ... }
首先,我定义一个 Card 的抽象了,里面有一个 ToXElement 的抽象方法:
500)this.width=500'>// Code #01500)this.width=500'>500)this.width=500'>abstract class Card500)this.width=500'>500)this.width=500'>500)this.width=500'>{500)this.width=500'> public abstract XElement ToXElement();500)this.width=500'>500)this.width=500'> // Other code omitted 500)this.width=500'>500)this.width=500'>}
接下来,我们来看看 MonsterCard 的 ToXElement 实现和其中一个构造函数:
500)this.width=500'>// Code #02500)this.width=500'>500)this.width=500'>class MonsterCard : Card500)this.width=500'>500)this.width=500'>500)this.width=500'>{500)this.width=500'> public MonsterCard(XElement info)500)this.width=500'>500)this.width=500'> 500)this.width=500'>{500)this.width=500'> m_ImageLocation = (string)info.Attribute("img");500)this.width=500'> m_Name = (string)info.Attribute("name");500)this.width=500'> m_Category = (MonsterCardCategory)Enum.Parse(typeof(MonsterCardCategory), (string)info.Attribute("category"), false);500)this.width=500'> m_Attribute = (MonsterAttribute)Enum.Parse(typeof(MonsterAttribute), (string)info.Attribute("attribute"), false);500)this.width=500'> m_Type = (MonsterType)Enum.Parse(typeof(MonsterAttribute), (string)info.Attribute("type"), false);500)this.width=500'> m_Level = Int32.Parse((string)info.Attribute("level"));500)this.width=500'> m_Atk = Int32.Parse((string)info.Attribute("atk"));500)this.width=500'> m_Def = Int32.Parse((string)info.Attribute("def"));500)this.width=500'> m_Description = (string)info.Value;500)this.width=500'> }500)this.width=500'>500)this.width=500'> public override XElement ToXElement()500)this.width=500'>500)this.width=500'> 500)this.width=500'>{500)this.width=500'> return new XElement("monstercard",500)this.width=500'> new XAttribute("img", m_ImageLocation),500)this.width=500'> new XAttribute("category", m_Category.ToString()),500)this.width=500'> new XAttribute("name", m_Name),500)this.width=500'> new XAttribute("attribute", m_Attribute.ToString()),500)this.width=500'> new XAttribute("level", m_Level.ToString()),500)this.width=500'> new XAttribute("type", m_Type.ToString()),500)this.width=500'> new XAttribute("atk", m_Atk.ToString()),500)this.width=500'> new XAttribute("def", m_Def.ToString()),500)this.width=500'> m_Description);500)this.width=500'> }500)this.width=500'>500)this.width=500'> // Other code omitted 500)this.width=500'>500)this.width=500'>}
在 ToXElement 中,我们使用了 Functional Construction 方式来创建 XML,它调用了 XElement 的
500)this.width=500'>// Code #03500)this.width=500'>500)this.width=500'>public XElement(XName name, params object[] contents)
XElement 懂得处理所有类型的输入参数,以下摘自 XLinq Overview:
A string, which is added as text content.
An XElement, which is added as a child element.
An XAttribute, which is added as an attribute.
An XProcessingInstruction, XComment, or XCData, which is added as child content.
An IEnumerable, which is enumerated, and these rules are applied recursively.
Anything else, ToString() is called and the result is added as text content.
null, which is ignored.
从这里,我们可以看出,XLing 使得无论读取或者创建 XML 都变得比以前更为便捷了。
5. GIVE ME WHAT I WANT!
现在我们来看这张卡:
500)this.width=500'>
这张卡的效果是禁止场上所有等级4或以上的怪兽攻击,于是,我希望能够找到等级3或者以下,并具有能直接攻击对手的效果的怪兽:
500)this.width=500'>// Code #04500)this.width=500'>500)this.width=500'>XElement cards = XElement.Load(@"E:\My Documents\Visual Studio\Projects\LINQLab\Sample.xml");500)this.width=500'>var wanted = from c in cards.Element("monstercards").Elements("monstercard")500)this.width=500'> where (Int32.Parse((string)c.Attribute("level")) < 4) && ((string)c.Attribute("category") == "Effect")500)this.width=500'> orderby Int32.Parse((string)c.Attribute("atk"))500)this.width=500'> select c;500)this.width=500'>foreach (var c in wanted)500)this.width=500'>500)this.width=500'>500)this.width=500'>{500)this.width=500'> Console.WriteLine((string)c.Attribute("name"));500)this.width=500'> Console.WriteLine("[{0}]", (string)c.Attribute("type"));500)this.width=500'> Console.WriteLine(c.Value);500)this.width=500'> Console.WriteLine("ATK/ {0} DEF/ {1}", (string)c.Attribute("atk"), |
|
|