游戏要有挑战性,否则就不好玩了。现在我们要创建一个有敌人的房间。进入房间的玩家必须同敌人战斗,谁的生命值先达到零就输了。我们需要创建敌人列表,以及减少和恢复角色生命值的函数。另外还要建立一个战斗模块,并创建一个可以触发战斗的房间。第一步是构建敌人列表,使用以下代码创建lib/dungeon_crawl/enemies.ex文件:
我们使用了和英雄相同的DungeonCrawl.Character结构体创建敌人。下一步是创建减少和恢复角色生命值的函数,以及显示角色当前生命值的函数。在DungeonCrawl.Character模块中添加如下函数:
函数take_damage/2接收角色和角色丢失的生命值。它使用函数max保证角色不会出现负生命值。我们使用%{ map | key: new_value }更新结构体的值,这样做很方便。该函数返回具有新生命值的角色。函数heal/2接收角色和角色应该恢复的生命值。它使用函数min/2保证角色的生命值不超出允许的最大值。它同样返回具有新生命值的角色。函数current_stats/1生成一条消息,其中包含角色的当前生命值以及最大生命值。
战斗模块中的函数将处理两个角色的战斗。它不必关心谁是玩家,谁是敌人;只负责让两个角色轮流相互攻击,直到其中一个生命值为零。创建lib/dungeon_crawl/battle.ex文件,并编写以下模块:
函数fight/2首先检查两个角色的生命值是否为零。只要有一个为零,就结束战斗并返回一个元组,其中的角色与给定参数的顺序相同。否则,则调用attack函数相互攻击。attack函数检查攻击者是否生命值为零,如果为零,则被攻击者不会丢失生命值;否则,被攻击者会受到攻击者伤害范围内的随机值伤害。函数attack_message和receive_message会在控制台显示攻击的伤害值和当前角色的生命值。现在让我们构建可以用于战斗的房间触发器。创建文件lib/dungeon_crawl/room/triggers/enemy.ex:
函数run/2从敌人列表中随机抽取敌人,然后用玩家角色和敌人作为参数调用DungeonCrawl.Battle.fight/2。该函数返回战斗后更新的角色,forward标志代表玩家尚未找到出口。现在我们可以使用此触发器创建一个新房间并将其放在列表中:
战斗发生后,如果英雄活下来,他可以继续前进。如果他的生命值变成零,则玩家失败,游戏结束。用这个新规则更新lib/dungeon_crawl/cli/main.ex:(www.xing528.com)
我们修改了hero_choice/0,用you代替角色名称,为玩家提供更好的带入感。我们还在玩家选择动作之前显示角色的当前生命值,以便玩家做出选择。我们创建了crawl/2子句,它在角色生命值为零时结束游戏,同时显示“游戏结束”的消息。现在可以运行mix start查看游戏效果。
协议与行为的区别
协议用于结构体;行为用于模块。协议创建一个函数接口,以便处理多种数据类型;行为定义了模块应实现的一系列函数。
游戏已经构建完毕。在这个过程中,我们学习了使用Elixir的行为构建模块契约,明白了如何添加新模块,掌握了类型规范和Dialyzer的用法。你还学会了在应用程序中添加新库,以及如何在不添加代码的情况下获得新功能。
如果你想添加更多地下城房间,请参阅附录1。在那里你会看到一些改善游戏的想法,比如添加一个带陷阱的房间。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。