[Reach教程翻译] 2.8 玩家交互、自主运行游戏

  • Ivan
  • 更新于 2021-12-01 09:18
  • 阅读 2959

不同于先前的自动化测试,这篇教程里,我们修改了前端,让用户可以将合约真正部署到共识网络上,并实现自主下注、出拳。 (而这一切都只需要修改前端,也就是说在上一篇教程里,我们后端的Reach合约就已经完整了!)

[Reach教程翻译] Reach是安全简单的Dapp开发语言 让用户可以像开发传统App一样开发DApp 目前使用Reach开发的智能合约可以部署在以太坊、Conflux、Algorand Reach官网 Reach官方文挡

2.8 玩家交互、自主运行游戏

原文链接

在之前实现的程序中,我们的石头剪刀布会一直运行直到确定最终的赢家为止。在本节中,我们不会改变Reach程序本身。反之,我们会通过修改Javascript前端来打造一个可交互的版本,这个版本将能够在真正的共识网络上运行。

我们将从头开始,再次展示程序的每一行。您会发现这个版本与先前的版本非常相似,但是为了完整起见,我们会显示每一行。

rps-8-interact/index.mjs

 1    import { loadStdlib } from '@reach-sh/stdlib';
 2    import * as backend from './build/index.main.mjs';
 3    import { ask, yesno, done } from '@reach-sh/stdlib/ask.mjs';
 4    const stdlib = loadStdlib(process.env);
 5    
 6    (async () => {
..    // ...
  • 第 1、2、4 行和之前一样 : 导入标准库和后端。
  • 第 3 行是新加入的,导入了一个 Reach 标准库中的 ask.mjs 库。下面我们将看到如何使用这三个函数。

rps-8-interact/index.mjs

..    // ...
 7    const isAlice = await ask(
 8      `Are you Alice?`,
 9      yesno
10    );
11    const who = isAlice ? 'Alice' : 'Bob';
12    
..    // ...
  • 第 7-10 行,询问用户是否以 Alice 的身份参与,期望得到“是”或“不是”的回答。ask 会反复显示问题并提示用户输入,直到得到的输入是 'y' 或 'n'为止。

rps-8-interact/index.mjs

..    // ...
13    console.log(`Starting Rock, Paper, Scissors! as ${who}`);
14    
15    let acc = null;
16    const createAcc = await ask(
17      `Would you like to create an account? (only possible on devnet)`,
18      yesno
19    );
20    if (createAcc) {
21      acc = await stdlib.newTestAccount(stdlib.parseCurrency(1000));
22    } else {
23      const secret = await ask(
24        `What is your account secret?`,
25        (x => x)
26      );
27      acc = await stdlib.newAccountFromSecret(secret);
28    }
29    
..    // ...
  • 第 16 - 19 行,用户可以选择新创建一个测试帐户,或者输入密钥来导入自己的帐户。
  • 第 21 行像之前一样创建测试帐户。
  • 第 27 行导入帐户。

rps-8-interact/index.mjs

..    // ...
30    let ctc = null;
31    if (isAlice) {
32      ctc = acc.contract(backend);
33      ctc.getInfo().then((info) => {
34        console.log(`The contract is deployed as = ${JSON.stringify(info)}`); });
35    } else {
36      const info = await ask(
37        `Please paste the contract information:`,
38        JSON.parse
39      );
40      ctc = acc.contract(backend, info);
41    }
..    // ...
  • 第 31 行确定以下分支中玩家扮演的角色是Alice-部署合约,还是Bob-加入Alice部署的合约。
  • 第 32 - 34 行部署合约并打印合约公开信息(ctc.getInfo),部署者可以在部署好后将这个信息发送其他要加入合约的参与者,用于让他们加入合约。
  • 第 36 - 41 行请求、解析和处理这个信息。

rps-8-interact/index.mjs

..    // ...
43    const fmt = (x) => stdlib.formatCurrency(x, 4);
44    const getBalance = async () => fmt(await stdlib.balanceOf(acc));
45    
46    const before = await getBalance();
47    console.log(`Your balance is ${before}`);
48    
49    const interact = { ...stdlib.hasRandom };
..    // ...
  • 定义几个辅助函数并声明参与者交互接口。

rps-8-interact/index.mjs

..    // ...
51    interact.informTimeout = () => {
52      console.log(`There was a timeout.`);
53      process.exit(1);
54    };
..    // ...
  • 定义一个超时处理程序。

rps-8-interact/index.mjs

..    // ...
56    if (isAlice) {
57      const amt = await ask(
58        `How much do you want to wager?`,
59        stdlib.parseCurrency
60      );
61      interact.wager = amt;
62      interact.deadline = { ETH: 100, ALGO: 100, CFX: 1000 }[stdlib.connector];
63    } else {
64      interact.acceptWager = async (amt) => {
65        const accepted = await ask(
66          `Do you accept the wager of ${fmt(amt)}?`,
67          yesno
68        );
69        if (!accepted) {
70          process.exit(0);
71        }
72      };
73    }
..    // ...
  • 根据是 Alice 还是 Bob,决定请求赌注值 wager ,还是定义 acceptWager 方法

rps-8-interact/index.mjs

..    // ...
75    const HAND = ['Rock', 'Paper', 'Scissors'];
76    const HANDS = {
77      'Rock': 0, 'R': 0, 'r': 0,
78      'Paper': 1, 'P': 1, 'p': 1,
79      'Scissors': 2, 'S': 2, 's': 2,
80    };
81    
82    interact.getHand = async () => {
83      const hand = await ask(`What hand will you play?`, (x) => {
84        const hand = HANDS[x];
85        if ( hand == null ) {
86          throw Error(`Not a valid hand ${hand}`);
87        }
88        return hand;
89      });
90      console.log(`You played ${HAND[hand]}`);
91      return hand;
92    };
..    // ...
  • 接着定义两人共同的 getHand 方法。

rps-8-interact/index.mjs

..    // ...
94    const OUTCOME = ['Bob wins', 'Draw', 'Alice wins'];
95    interact.seeOutcome = async (outcome) => {
96      console.log(`The outcome is: ${OUTCOME[outcome]}`);
97    };
..    // ...
  • 最后是 seeOutcome 方法。

rps-8-interact/index.mjs

..    // ...
99    const part = isAlice ? ctc.p.Alice : ctc.p.Bob;
100    await part(interact);
101    
102    const after = await getBalance();
103    console.log(`Your balance is now ${after}`);
104    
105    done();
106    })();
  • 最后的最后,我们选择合适的后端并等待其完成。**

现在我们可以运行在两个终端分别运行$ ./reach run来扮演 Alice 和 Bob 。

下面是一组运行的例子:

$ ./reach run
Are you Alice?
y
Starting Rock, Paper, Scissors as Alice
Would you like to create an account? (only possible on devnet)
y
Do you want to deploy the contract? (y/n)
y
The contract is deployed as = "0x132b724e55AEb074C15A5CBb7b8EeE0dBEd45F7b"
Your balance is 999.9999
How much do you want to wager?
10
What hand will you play?
r
You played Rock
The outcome is: Bob wins
Your balance is now 989.9999

另一边:

$ make run-bob
Are you Alice?
n
Starting Rock, Paper, Scissors as Bob
Would you like to create an account? (only possible on devnet)
y
Do you want to deploy the contract? (y/n)
n
Please paste the contract information:
"0x132b724e55AEb074C15A5CBb7b8EeE0dBEd45F7b"`
Your balance is 1000
Do you accept the wager of 10?
y
What hand will you play?
p
You played Paper
The outcome is: Bob wins
Your balance is now 1009.9999

当然,每次运行时的赌注可以不同,部署地址也会不一样。

如果你的版本不能正常运行,看看完整的版本: rps-8-interact/index.rshrps-8-interact/index.mjs ,并确保您完整地复制了所有内容!

如果我们在两个终端运行的是 $ REACH_CONNECTOR_MODE=ALGO-devnet ./reach run 则相当于在一个私有的 Algorand 测试网运行我们的程序。

连接真正的共识网络也一样简单,例如运行: $ REACH_CONNECTOR_MODE=ETH-live ETH_NODE_URI="http://some.node.fqdn:8545" ./reach run

您知道了吗? :

是非题 : Reach 帮助你自动化测试DApp,但它不支持构建交互式用户界面

答案是:

否! Reach 不会对使用 Reach 应用程序的前端做任何限制。

欢迎关注Reach微信公众号 并在公众号目录 -> 加入群聊 选择加入官方开发者微信群与官方Discord群 与更多Reach开发者一起学习交流!

_.png

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Ivan
Ivan
江湖只有他的大名,没有他的介绍。