Coronavirus Quarantine - Node-RED Games?

Hi all, a bit of a long shot, but has anyone created any Node-Red games, that could help the lockdown hours pass (especially for those with kids)

Ideally it would be nothing hugely complex that requires additional nodes or difficult to obtain additional physical items. Motion sensors, IOT lights, plugs, digital assistants etc. that people likely already have would OK.

Any ideas, anything to share ?

1 Like

Funny you should ask. My grandson (9) and myself are working on a remote tic-tac-toe game as a starting point. So two people will be able to lay it oner the internet. We have the basic game running:
Screen Shot 2020-03-29 at 5.59.32 AM
We just need to get the communictions portion running.

He wanted to start with checkers, I was thnking battleship but decided to use tic-tac-toe asa starting point.

Why not work with your kids to build a game?


Not Node-RED but there are a few coding oriented sites out there that help with game creation based on visual coding - mainly Scratch-style I think.

Battleships would probably be another game you could easily do with Node-RED. Hangman would be another.

Nothing to do with Node-RED, but equally great fun for children.

Paul @zenofmud
Your grandchildren might enjoy tackling this (simple) problem.

I assume you know the Frere Jacques song ???

I need your help to fix this program as it doesn't sound right.

I've been pulling my hair trying to fix it - please help me before I'm completely bald !!!

Just click on this link to jump to my program

Hope you manage to fix it for me.

And there is also the excellent Machine Learning for Kids -!/worksheets
(which actually teaches me lots too)


Ooh, I didn't know about that one. I need to learn more about ML :slight_smile:

Also going to see if I can persuade my son to look at it

As for Battleships, I recently found the starting out code of one in I think it was C++, wrote it around the age of 14 I think. Definitely something I would be interested in recreating on a websockets base.

Which does give me similar ideas for multiplayer card games. My primary pi running node-red is currently still connected to the public wifi of the building my apartment is in. Which more or less counts as a nursery home, so it’s currently closed off for any visitors. I could however put up card games like that, to play with other residents.

I just added our Tic-Tac-Toe game to the projects category if anyone wants to check it out.

Maybe "Titanic" would fit as a symbolic selection

A bit OT:
Yes, it's a very difficult & unpredictable situation, so many, many infected. On wiki it's interesting to read about the Spanish flue, it's very similar I must say, especially how it attacks the lungs, causing pneumonia in a similar way. I hope for the best and that you all stay healthy through this, unfortunately it seems it will not end very soon. Take care!

Maybe not possible, but would it not be possible to use an instance at AWS as "public server" for such a game? Or would it be (a security) risk to participate and playing such game? Except for running the risk that your battleship would sink?

Here are some ideas I was thinking about, but not sure I can pull off with my NR capabilities..

  1. creating a quiz, maybe with Alexa (TTS) asking the questions and then maybe add some answer buttons on the dashboard ? Not sure how I could make that ongoing - I guess if it was just A B or C options that could work.

  2. Use Hue lights and motion sensors to create a game like SIMON, but instead of coloured buttons use rooms in the house - making you have to remember / follow the sequence. (Add Alexa in as the host for some more fun)

  3. ...... I’ll keep thinking :slight_smile:

1 Like

Bonus points for getting people moving. :slight_smile:

Just make sure everything breakable is locked away safely!


I had written a "KrazyKeno" game via Node-Red.

I should clarify, it's actually a Javascript game based on the classic video keno you see in Vegas.
It's served in a Node-Red http endpoint. I wanted to do different versions of Keno games similar to Cleopatra, Power Keno, Caveman, etc just for giggles. Also I was thinking of eventually doing a multiplayer tournament style, or a high score system, where you can log a highscore like old arcades, but more than 3 character.

Working example online... if it's online.

[{"id":"d665993.ab87268","type":"http in","z":"6ca0c686.7d00d8","name":"","url":"/krazykeno","method":"get","upload":false,"swaggerDoc":"","x":136,"y":150,"wires":[["43bba2f9.f8188c"]]},{"id":"3ef5b8e3.3c9428","type":"http response","z":"6ca0c686.7d00d8","name":"","statusCode":"","headers":{},"x":578,"y":165,"wires":[]},{"id":"43bba2f9.f8188c","type":"template","z":"6ca0c686.7d00d8","name":"KRAZYKENO","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!--\n\nKrazyKeno - written by MrSiDX \\n\n-->\n<link href=\"\" rel=\"stylesheet\" integrity=\"sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T\" crossorigin=\"anonymous\">\n<script src=\"\" integrity=\"sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=\" crossorigin=\"anonymous\"></script>\n<link href=\"\" rel=\"stylesheet\" integrity=\"sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN\" crossorigin=\"anonymous\">\n<style>\nbody {\n    background-color: black;\n    color : white;\n}   \n\ntable {\n    border-width: 3px;\n    border-color: yellow;\n    border-style: solid;\n    font-size: 25pt;\n    text-shadow: 2px 2px #000000;\n    margin: 15px;\n    margin-bottom: 25px;\n    cursor: pointer;\n}\n\ntd {\n    border-right: 3px;\n    border-style: solid;\n    border-color: yellow;\n    text-align: center;\n    padding : 3px;\n}\n\n.paytable{\n    border: 3px;\n    border-style: solid;\n    border-color: yellow;\n    text-align: center;\n    font-size: small;\n    padding : 3px;\n    /*overflow: fixed;*/\n}\n\n.tables {\n    /*width: 80%;*/\n    /*float:right;*/\n    /*overflow: fixed;*/\n}\n\n.paytablerow {\n    font-size:14px;\n}\n\n.wager {\n    float:left;\n    padding: 10px;\n}\n\n.credits {\n    float:right;\n    padding:10px;\n}\n\n\n.neon1 {\n  color: #fff;\n  font-family: Monoton;\n  -webkit-animation: neon1 1.5s ease-in-out infinite alternate;\n  -moz-animation: neon1 1.5s ease-in-out infinite alternate;\n  animation: neon1 1.5s ease-in-out infinite alternate;\n}\n \n@-webkit-keyframes spot-match {\n  from {\n    text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #fff, 0 0 40px #FF1177, 0 0 70px #FF1177, 0 0 80px #FF1177, 0 0 100px #FF1177, 0 0 150px #FF1177;\n  }\n  to {\n    text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #fff, 0 0 20px #FF1177, 0 0 35px #FF1177, 0 0 40px #FF1177, 0 0 50px #FF1177, 0 0 75px #FF1177;\n  }\n} \n\n@-webkit-keyframes neon1 {\n  from {\n    text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #fff, 0 0 40px #FF1177, 0 0 70px #FF1177, 0 0 80px #FF1177, 0 0 100px #FF1177, 0 0 150px #FF1177;\n  }\n  to {\n    text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #fff, 0 0 20px #FF1177, 0 0 35px #FF1177, 0 0 40px #FF1177, 0 0 50px #FF1177, 0 0 75px #FF1177;\n  }\n}\n\n\n</style>\n\n\n<button onclick=\"function (){return 'value';}\">test</button>\n<div class=\"col-sm-12 col-md-12 col-lg-12 col-xl-12 neon1\" style=\"text-align:center; width:100%; font-size: large;\" >KRAZY KENO</div>\n\n<div class=\"container\" style=\"width:100%;\">\n  <div class=\"row\">\n    \n    \n    {{!--PAYTABLES--}}\n    <div id=\"paytable\" style=\"\"class=\"payouts col-sm-3 col-md-3 col-lg-3 col-xl-3 float-left\">\n    </div>\n    {{!--END PAYTABLES--}}\n    \n    <div class=\"board col-sm-9  col-md-9 col-lg-9 col-xl-9\" >\n        {{!--THE PLAYING BOARD--}}\n        <table class=\"col-sm-12 col-md-12 col-lg-12 col-xl-12\" style=\"margin-bottom: 0;\">\n            <tr><td id=\"spot1\">1</td><td id=\"spot2\">2</td><td id=\"spot3\">3</td><td id=\"spot4\">4</td><td id=\"spot5\">5</td><td id=\"spot6\">6</td><td id=\"spot7\">7</td><td id=\"spot8\">8</td><td id=\"spot9\">9</td><td id=\"spot10\">10</td></tr>\n         <tr><td id=\"spot11\">11</td><td id=\"spot12\">12</td><td id=\"spot13\">13</td><td id=\"spot14\">14</td><td id=\"spot15\">15</td><td id=\"spot16\">16</td><td id=\"spot17\">17</td><td id=\"spot18\">18</td><td id=\"spot19\">19</td><td id=\"spot20\">20</td></tr>\n         <tr><td id=\"spot21\">21</td><td id=\"spot22\">22</td><td id=\"spot23\">23</td><td id=\"spot24\">24</td><td id=\"spot25\">25</td><td id=\"spot26\">26</td><td id=\"spot27\">27</td><td id=\"spot28\">28</td><td id=\"spot29\">29</td><td id=\"spot30\">30</td></tr>\n         <tr><td id=\"spot31\">31</td><td id=\"spot32\">32</td><td id=\"spot33\">33</td><td id=\"spot34\">34</td><td id=\"spot35\">35</td><td id=\"spot36\">36</td><td id=\"spot37\">37</td><td id=\"spot38\">38</td><td id=\"spot39\">39</td><td id=\"spot40\">40</td></tr>\n        </table>    \n    \n       <center> <div class=\"col-sm-12 col-md-12 col-lg-12 col-xl-12\" style = \"height:30px; padding: 0px;\" id=\"middlegamestatus\"></div></center>\n    <table class=\"col-sm-12 col-md-12 col-lg-12 col-xl-12\" style=\"margin-top: 0;\">\n      <tr><td id=\"spot41\">41</td><td id=\"spot42\">42</td><td id=\"spot43\">43</td><td id=\"spot44\">44</td><td id=\"spot45\">45</td><td id=\"spot46\">46</td><td id=\"spot47\">47</td><td id=\"spot48\">48</td><td id=\"spot49\">49</td><td id=\"spot50\">50</td></tr>\n     <tr><td id=\"spot51\">51</td><td id=\"spot52\">52</td><td id=\"spot53\">53</td><td id=\"spot54\">54</td><td id=\"spot55\">55</td><td id=\"spot56\">56</td><td id=\"spot57\">57</td><td id=\"spot58\">58</td><td id=\"spot59\">59</td><td id=\"spot60\">60</td></tr>\n      <tr><td id=\"spot61\">61</td><td id=\"spot62\">62</td><td id=\"spot63\">63</td><td id=\"spot64\">64</td><td id=\"spot65\">65</td><td id=\"spot66\">66</td><td id=\"spot67\">67</td><td id=\"spot68\">68</td><td id=\"spot69\">69</td><td id=\"spot70\">70</td></tr>\n      <tr><td id=\"spot71\">71</td><td id=\"spot72\">72</td><td id=\"spot73\">73</td><td id=\"spot74\">74</td><td id=\"spot75\">75</td><td id=\"spot76\">76</td><td id=\"spot77\">77</td><td id=\"spot78\">78</td><td id=\"spot79\">79</td><td id=\"spot80\">80</td></tr>\n    </table>\n    </div>\n    \n</div>\n\n    \n    <div id=\"controls\" class=\"controls col-sm-12 col-md-12 col-lg-12 col-xl-12\">\n        <div class=\"\">\n            <div id=\"status_wager\" class=\"wager\"></div>\n            <div id=\"status_credits\" class=\"credits\"></div>\n        </div>\n    </div>\n    \n    {{!--CONTROLS--}}\n    <div id=\"controls\" class=\"controls col-sm-12 col-md-12 col-lg-12 col-xl-12\">\n        \n     <button class=\"btn btn-primary btn-lg inline-block\" id=\"betmax\" onclick=\"betMax()\">Bet Max</button>\n     <button class=\"btn btn-primary btn-lg inline-block\" id=\"BetOne\" onclick=\"betOne()\">Bet One</button>\n     {{!--<button class=\"btn btn-primary btn-lg inline-block \" id=\"Clear Drawn\" onclick=\"clearDrawn()\">Clear Drawn</button>--}}\n     <button class=\"btn btn-primary btn-lg inline-block\" id=\"clearPicks\" onclick=\"clearPicks()\">Erase</button>\n     <button class=\"btn btn-primary btn-lg inline-block\" id=\"draw\" onclick=\"Draw()\">Start</button>\n     \n        <div id=\"betInfo\"></div>\n    </div>\n    \n</div>\n\n    \n\nNumbers: <div id=\"numbers\"></div>\nMatched: <div id=\"matched\">{{matched}}</div>\n\n\n<script>\n\n\n//init:\nvar denom = 1;\nvar maxBet = 400;\nvar credits = 1000;\nvar currentBet = 0;\nvar minBet = denom;\nvar picked = [];\nvar paytable = [];\nvar current_paytable = [];\nvar readyToPick = true;\nvar matched = [];\nvar drawSpeed = 1000;\nvar matchCount = 0;\nvar clear_board_between_picks = false;\nvar max_pick_count = 10;\nvar wager = 0;\nvar last_wager = 0;\n\nvar spot_pick_color = 'lightblue'\nvar table_background_color = 'blue';\nvar matched_spot_color = 'purple';\nvar spot_missed_color = 'red';\n\nclearBoard();\nupdateCreditStatus();\n\nfunction betMax(){\n    \n    \n    if(credits <= maxBet){\n        wager = credits;\n    } else{\n        wager = maxBet;\n    }\n    \n    updateCreditStatus();\n}\n\nfunction updateButtonStatus(){\n    if (picked.length < 1){\n        document.getElementById('draw').disabled = true;\n        document.getElementById('draw').setAttribute('style', \"background-color: grey;\");\n        document.getElementById('clearPicks').disabled = true;\n        document.getElementById('clearPicks').setAttribute('style', \"background-color: grey;\");\n        \n    }else{\n          document.getElementById('draw').disabled = false;\n          document.getElementById('clearPicks').disabled = false;\n    }\n}\n\nfunction updateCreditStatus(){\n     document.getElementById('status_credits').innerHTML=\"Credit \" + credits;\n    document.getElementById('status_wager').innerHTML = \"Bet \" + wager ;\n}\n\nfunction betOne(){\n \n    if (wager <= maxBet && wager <= credits){\n        wager = wager + 1   \n    }\n    //     if (wager != 0 ){\n    //         wager = wager + 1;\n    //     }else {\n    //         if(credits > last_wager && last_wager != 0){\n    //             wager = last_wager;\n    //         }else{\n    //             wager = 1;\n    //         }\n    //     }\n        \n    //     //credits = credits - 1;\n    // }   \n    updateCreditStatus();\n}\n\n\nfunction displayPaytable(pt){\n    \n    //example\n    //[0,1,2,3,4,5,6,7,8,9,10....]\n    var inject = \"\";\n    for(var i =0; i<pt.length;i++){\n        if(pt[i] > 0){\n            if( i == matched.length){\n                 inject = inject + '<tr style=\"margin:0; padding:5px; background-color:red;\" class=\"paytablerow\" id=\"paytablerow' + i + '\"><td>' + i + '</td><td>' + pt[i] + '</td></tr>';\n                \n            }  else {\n                 inject = inject + '<tr style=\"margin:0; padding:5px; background-color: black;\" class=\"paytablerow\" id=\"paytablerow' + i + '\"><td>' + i + '</td><td>' + pt[i] + '</td></tr>';\n            }\n     \n        }\n    }\n    \n    \n    document.getElementById('paytable').innerHTML = `\n        <table class=\"\" id=\"paytable_inner\">\n        <tr class=\"paytablerow\"><td>Hits</td><td>Win</td></tr>` + inject + `\n         </table>\n    `\n    \n}\n\nfunction gameDone(){\n    // check winnings and pay\n    credits = credits + (current_paytable[matched.length] * wager);\n    updateCreditStatus();\n    last_wager = wager;\n    document.getElementById('middlegamestatus').innerHTML = '<div style=\"width:100%; text-align: center; margin: 0;\">Game Over</div>';\n    document.getElementById('controls').disabled = false;\n    document.getElementById('controls').setAttribute('style', 'disabled: false');\n\n}\n\nfunction updatePaytable(){\n    \n    var spots = picked.length;\n    // spots\n    //1\n    var r = [];\n    if (spots == 1){\n       r= [0,3]\n    }\n    if(spots == 2){\n        r=[0,1,15]\n    }\n    if(spots == 3){\n        r=[0,0,3,21]\n    }\n    if(spots == 4){\n        r=[0,0,1,8,96]\n    }\n    if(spots == 5 ){\n       r= [0,0,0,1,12,810]\n    }\n    if(spots == 6){\n        r=[0,0,0,1,3,54,1600]\n    }\n    if(spots == 7){\n       r= [0,0,0,1,15,21,46,3200]\n    }\n        if(spots == 8){\n        r=[0,0,0,1,15,21,46,3200,6400]\n    }\n        if(spots == 9){\n       r= [0,0,0,1,15,21,46,3200,6400,10000]\n    }\n        if(spots == 10){\n       r= [0,0,0,1,15,21,46,200,1600,4260,10000]\n    }\n    current_paytable = r;\n    displayPaytable(r);\n    \n}\n\n\nfunction clearPicks(){\n     if(readyToPick == false){\n      }else{\n  \n        for( var i = 1; i< 81;i++){\n             document.getElementById(\"spot\" + i).setAttribute('style', 'background-color: ' + table_background_color);\n        }\n        document.getElementById('middlegamestatus').innerHTML = \"\";\n        picked = [];\n        matched = [];\n        wager = 0;\n        updateCreditStatus();\n     }\n }\n\nfunction clearBoard(){\n    if(readyToPick == false){\n      }else{\n                for( var i = 1; i< 81;i++){\n                    document.getElementById(\"spot\" + i).setAttribute('style', 'background-color: ' + table_background_color);\n                } \n       }\n }\n \nfunction clearDrawn(){\n    if(readyToPick == false){\n      }else{\n            \n     for( var i = 1; i< 81;i++){\n        document.getElementById(\"spot\" + i).setAttribute('style', 'background-color: ' + table_background_color);\n        document.getElementById(\"spot\" + i).innerHTML = i;\n        \n     }\n     for( var i = 0; i< picked.length;i++){\n        document.getElementById(\"spot\" + picked[i]).setAttribute('style', 'background-color: ' + spot_pick_color);\n     }\n       }\n\n}\n \n function clearAll(){\n    \n    if(readyToPick == false){\n      }else{\n        for( var i = 1; i< 81;i++){\n            document.getElementById(\"spot\" + i).setAttribute('style', 'background-color: ' + table_background_color);\n            document.getElementById(\"spot\" + i).text = i;\n            matched=[];\n            picked=[];\n        }\n       }\n\n }\n \n \n\nfunction dabBoard(arr){\n    //  if(clear_board_between_picks == true){\n    //  clearDrawn();\n    //  }\n    matched = [];\n    //document.getElementById('numbers').innerHTML = arr;\n    var i = 0;\n    dly = setInterval(function (){\n        if(i >= arr.length){\n            readyToPick = true;\n            clearInterval(dly);\n            gameDone();\n            \n        }\n        var nomatch = true;\n\n        for(var s = 0; s < picked.length; s++){\n            if ( arr[i] == picked[s] ){\n                //match!\n                nomatch = false;\n                matched.push(picked[s]);\n                document.getElementById(\"matched\").innerHTML = matched;\n                document.getElementById(\"spot\" + picked[s]).setAttribute('style', 'background-color: ' + matched_spot_color);\n                document.getElementById(\"spot\" + picked[s]).innerHTML = '<span><i class=\"fa fa-check-circle spot-match\"></i></span>'\n                \n            }\n        }\n\n        if ( nomatch ){\n                       document.getElementById(\"spot\" + arr[i]).setAttribute('style','background-color: ' + spot_missed_color);\n                       nomatch = false;\n        }\n        updatePaytable();\n        i++;\n    }, 100);\n    \n}\n\n\n    //keno draw numbers\nfunction drawNumbers(){\n    var arr = [];\n    var s = 0;\n    var returnAllAtOnce = true;\n    var amountToPick = 20;\n    \n            while(arr.length < amountToPick){\n              var r = Math.floor(Math.random()*80) + 1;\n              if(arr.indexOf(r) === -1) arr.push(r);\n            }\n            //alert(arr);\n            return arr;\n}\n\n\n</script>\n\n\n<script>\n\n\n$( document ).ready(function() {\n    \n   $('td').click(function (){\n       if( readyToPick == true){\n    \n             var spot ='spot','');\n             var exists = false;\n             //check if in picked list:\n             for (var i = 0 ; i < picked.length; i++){\n                 if (spot == picked[i]){\n                     //unpick\n                     exists = true;\n                     picked.splice(i, 1);\n                     document.getElementById(\"spot\" + spot).setAttribute('style', 'background-color: ' + table_background_color);\n                     \n                     \n                 }\n             }\n             if (!exists){\n                 if(picked.length < max_pick_count){\n                  picked.push(spot);\n                  document.getElementById(\"spot\" + spot).setAttribute('style', 'background-color: ' + spot_pick_color);\n                 }\n             }\n             updatePaytable()\n             updateButtonStatus();\n         }    \n    });\n});\n   \nfunction Draw(){\n\n    if(readyToPick == false){\n      }else{\n          if(picked.length > 0 && (credits - wager) >= 0 && credits > 0 && wager > 0){\n             updateCreditStatus()\n             document.getElementById('middlegamestatus').innerHTML = \"\";\n             document.getElementById('controls').disabled = true;\n             clearDrawn();\n             readyToPick = false;\n             credits = credits - wager;\n             updateCreditStatus();\n             dabBoard(drawNumbers());\n          }\n       }\n}\n</script>","output":"str","x":316,"y":150,"wires":[["3ef5b8e3.3c9428","d8c921c9.74195"]]},{"id":"d8c921c9.74195","type":"debug","z":"6ca0c686.7d00d8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":517,"y":264,"wires":[]}]

BTW I have added a Node-RED demo game in another discussion :wink:
P.S. it is implement using the beta version of our SVG node, so it doesn't work with the version available on NPM ...

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.