什么RESTful API将用于回合制游戏服务器?

时间:2009-01-01 22:34:55

标签: rest chess

您如何将回合制游戏服务器建模为RESTful API?例如,国际象棋服务器,您可以在其中与同一API的另一个客户端进行国际象棋游戏。您需要某种方式向其他客户请求和谈判游戏,以及某种方式来玩游戏的各个动作。

这是REST(RESTful)API的良好候选者吗?或者这应该以不同的方式建模?

10 个答案:

答案 0 :(得分:4)

我在想:

/game/<gameID>/move/<moveID>

就基本资源而言。我不知道如何处理“让其他玩家感动了吗?”但是,这个想法。我已经考虑过简单地进行GET请求阻止,直到进行移动 - 即。我的客户会将我移动的坐标设为

/game/13/move/1

然后GET

/game/13/move/2

服务器不会立即响应,但保持连接打开,直到其他玩家移动(即PUT到该位置)。这就是nakajima所说的“彗星式”吗?

查理,我不太确定你所说的“令牌”是什么意思 - 它是否解决了相同的问题而不需要轮询或阻塞连接?

对于玩家ID,将这些作为部分URL的资源进行建模是否有意义?我打算简单地使用HTTP用户身份验证(用户/传递作为每个请求的一部分发送)。您仍然可以在没有身份验证的情况下获取大多数资源,但是如果您尝试了,那么,

PUT /game/13/move/2
如果你没有该游戏的正确凭据,它会给你一个权限被拒绝的错误。

答案 1 :(得分:4)

好吧,REST的基本思想是你正在转移国家;你想在服务器上很少或没有“会话状态”。所以你不想使用会话状态和keepalive,这就是Comet所做的。但想想一下邮件游戏的例子:你们都有一个董事会副本,你们交换动作。邮局不了解游戏。

现在,我会承认,在我想到这一点时,我的脑海里正在增长 - 实际上,我可能会根据这个问题撰写一篇文章 - 但这就是一些故事:

  1. 你想玩国际象棋游戏 line,所以你去一个已知的URI 得到一个。你找回一页 显示谁,如果有人,等待 开始游戏。
  2. 你挑选一个等待的人 玩,然后单击相应的 链接。你得到一个新的显示(ajax 如果你愿意,可以在这里使用魔法 董事会成立。你们其中一个是白人, 白先行动。
  3. 有权移动的人进入 搬家,并承诺(如服用 你把手放在游戏中。) 董事会更新和权利 移动到另一个玩家。
  4. 您在服务器状态方面不需要任何东西 - 尽管您可能希望通过跟踪移动等来扩展这一点,例如排名 - 并且可以计算谁有权移动的问题完全来自董事会页面:如果你有权利,你有一张表格可以进入;当您发送表单返回时,响应会返回一个页面给您,没有用于输入移动的插槽。

    通过“令牌”我只是意味着一点状态“我的行动”/“你的行动”的任意表示。

    好像你需要的资源似乎是

    • “寻找游戏”主页
    • 如果您正在跟踪统计信息,则为用户页面 等等。
    • 每个有效游戏的唯一URI。

答案 2 :(得分:3)

您尝试建模的资源有哪些?我似乎有四个:你,你的对手,特定的游戏(会话,实例)和游戏板状态。所以它会从像

这样的东西开始
/game
/game/gameID/gamer/gamerID
/game/gameID/board

我们在InfoQ上有一个很好的介绍/概述。

答案 3 :(得分:2)

谢谢,查理。我还不清楚你如何得知对手在你的计划中的举动。当然,谁有权移动的问题可以简单地计算 - 从董事会资源,或通过使用明确说明轮到它移动的单独资源。但客户如何知道此资源已发生变化?是否必须继续轮询,记住以前的状态,直到它注意到某些事情发生了变化?在邮局模型中,邮局将邮件“推送”到客户端(您的邮箱),这在HTTP中是不可能的。

我认为这是一个更普遍的问题的一部分:如果有一个REST资源我想要监视更改或修改,那么最好的方法是什么?服务器可以做些什么来使客户更容易?

我认为我实际上会将此作为一个单独的问题发布,因为我认为它本身很有趣。

已编辑添加:What is a RESTful way of monitoring a REST resource for changes?

答案 4 :(得分:2)

我不认为REST是这种应用程序的不错选择。您需要进行的转换和操作(移动,查看移动历史,撤消,获取建议,转向通知)不能巧妙地映射到REST的资源概念。 (如果考虑一个RESTful API如何用于更复杂的回合制游戏,如Scrabble或Monopoly,可能会更加明显。)

我认为任何合理的REST API都可能最终成为非RESTful内容的包装器,例如来回发送portable game notation的有状态协议。

答案 5 :(得分:1)

我认为你可以模拟它。 实现它将更加困难,因为您需要一个comet - esque解决方案,或者您必须通过AJAX以相对较短的间隔轮询服务器。

就你如何展示RESTful界面而言,我要说你需要一个带坐标的棋盘,可以占据这些坐标的棋子,以及改变这些坐标的动作。

当玩家进行移动时,将创建一个新动作。验证确认允许后,您将更新游戏状态,然后呈现更新UI所需的任何响应。

所以这基本上就是我的模型。实施方面是我认为这里面临的更大困难。

答案 6 :(得分:1)

我不认为这一切都得到了证实,Nakajima。你可以传递数据,例如JSON,用于棋盘位置,移动,以及用于下一步移动的令牌。这就像通过邮件播放一样。

你首先去游戏并寻找合作伙伴,所以

/game/

为您提供等待的人员列表。当你进来时,如果没有人在等你就得到一个游戏ID;否则你会选择等待他人的游戏ID。

/game/gameID

显示了你的董事会。你需要一些东西来决定谁扮演白人的决定,我会把它作为一种练习。 GET操作为您提供了电路板,因此POST发送移动;如果你没有移动,你会收到错误。你可以在下一个GET找到结果。

天啊,在这个模型中,我甚至没有使用游戏玩家ID,虽然它可能是好的,所以没有人可以作为kibitzer潜入游戏。

答案 7 :(得分:1)

所以你的想法是,不是将动作作为第一类对象,而是将每一步都视为游戏本身的更新?这当然是一种不同的方式,但我认为我更倾向于将动作对象拆分为自己的第一类实体,原因有两个。最大的原因是我相信它更可测试。移动是否有效可以存在于操作对象中,而不需要担心电路板始终处于有效状态。当然,我不知道这两种方法会带来什么,但这对我来说感觉更好。

您可以通过YAGNI完全驳斥的另一个原因是,第一类动作对象将提供移动历史记录。或许有趣,但除非有要求,否则是一个没有实际意义的点。

答案 8 :(得分:1)

planet.jabber中的一位开发人员参与了Chesspark,一个在线国际象棋社区。他们广泛使用Jabber / XMPP;如果我没弄错的话,these are his posts on the subject

XMPP是一种即时消息传递协议,大致基于小型XML消息交换。有大多数语言的库,包括 Javascript。不过,我不确定它是否适合你的问题。

答案 9 :(得分:1)

对于像国际象棋这样的简单游戏,它实际上就是定义媒体类型。

这是一个可能是一个过度简化的mediatype模型国际象棋游戏的例子。

我将跳过可能在同一服务器上运行的多个游戏的管理,只是为已经运行的游戏建模。

第一步通常是为应用程序定义索引。

index

游戏的切入点。获取此信息以发现有关游戏的信息。

有效负载可能如下所示:

{
    "links": {
        "self": "http://my-chess-game.host/games/123",
        "player": "http://my-chess-game.host/players/1",
        "player": "http://my-chess-game.host/players/2",
        "me": "http://my-chess-game.host/players/1",
         ...
    }
    "board": [
        {
           "x": 0,
           "y": 1,
           "piece": null,
           "rel": "space",
           "href": "http://my-chess-game/.../boards/123/0/1/something-random-to-discourage-uri-construction"
        },
        {
           "x": 1,
           "y": 2,
           "rel": "space",
           "href": "...",
           "piece": {
               "player": "http://my-chess-game/.../players/1",
               "type": "http://my-chess-game/pieces/Bishop",
               "rel": "piece",
               "href": "http://my-chess-game/games/123/pieces/player1/Bishop/1",
               "links": [
                    { "rel": "move": "href": "http://my-chess-game/.../boards/123/..." },
                    ...
                ]
            }
        },

        ...
    ]
}

move

将JSON有效负载发布到标有rel move的链接以移动一块。必须包括以下字段:

  • location:要移动到
  • 的空间的URI

成功的回复状态代码为200,并且将包含与index有效负载相同的实体,并且具有更新的游戏状态。

400,如果不允许用户在那里移动他的作品,或者轮到他的话。

player

获取玩家的描述。

以下字段必须在响应中:

  • 用户名:播放器的用户名
  • href:识别此游戏玩家的URI。

piece

片段嵌入在index有效载荷中,但可以单独存在。每个piece必须包含以下字段:

  • type:标识作品类型的URI。例如。 Bishop,Rook,King。获取此URI可以提供有关此棋子在国际象棋游戏中如何运作的信息。
  • href:标识此板上实际部分的URI。对此URI的GET请求可以提供有关此特定部分的信息。

每件作品必须有一个move链接。

我可以在这里做出的另一个设计决定是为每个有效的移动提供单独的链接。可能有充分的理由这样做,但我想证明它并不是必需的。您可能希望包含一些其他资源来处理诸如帮助客户确定轮到它等等的事情。

对于更复杂的游戏,比如文明,RTS,FPS或MMOG,什么不是,这可能不是那么实用的IMO。