一个猜你所选的小程序随写

websocket
placeholder image
admin 发布于:2023-06-10 19:20:49
阅读:loading

1.背景介绍

关于本篇文章的命名《一个猜你所选的小程序随写》我也是很无奈,没有特别突出的主题,更像是随写一样,给我多年前知道的一款猜你所选的一个游戏交互的一个呈现,所以下文的所有内容将是想到哪里写到哪里。

大概是在2007年左右吧,一个同学给我展示了一个小小的“绝活让我眼前一亮,主要是拿了十五张扑克牌,我默选一张(不对外告知),由他分别堆成三叠,每叠五张,通过按一定的规则摆放,前后共三次最终可挑选出我选定的那一张牌。这个小技巧也是逢年过节我常拿来为大家展示的一个雕虫小技,值得大家来了解一下,不过这其中的算法我肯定是不知道,只能是按照渣渣程序的方式进行一个鸡肋的实现。

十五个元素可以是十五张小纸条,十五个麻将,十五个扑克牌等等,本次也使用十五张扑克牌来模拟共计十五个元素,分别是:A,2,3,4,5,6,7,8,9,10,J,Q,K,小王,大王,它们可以是顺序排列,也可以是随机乱序组合,以下是整个游戏交互的过程。

2.猜数字J过程

假设我按任意顺序洗完牌后展示了十五张牌,对于我来说,这些牌的顺序我并不知道,我展示给她看,让她从中挑选一张记住此牌,此牌不必要告诉我,在她心里自己知道即可,在整个过程中我并不知道牌的顺序是什么样子的,以及她选定的那张牌是什么。

所以她本次选定的牌是J,正好是十五张牌中正中间的位置,其实是哪张,在哪里都无所谓,之所以这里说是J是因为我在演示查找过程时必须要根据结果来进行排列卡牌,在实际交互时是需要二人配合提示的。

(1)按照任意顺序排列(当然也可以指定按从小到大的顺序)来排列十五张牌,比如本次任意排序后的顺序如下(本次示例将按照下列顺序展开):

image.png

(2)将以上排列的十五个元素按序平均分为三份(三份的分布可以是横向排列,但本次示例代码呈现的效果是纵向排列的),每份各五张,参考第一次排序后的如下顺序:

image.png

(3)接下来我会逐个打开每个牌堆让她判断她刚刚选定的牌是否在这一堆牌当中,在打开牌堆时我并不查看每堆牌具体牌,根据结果J的引导此时我被知道她选择的牌在第二堆中,所以根据规则我将把第一堆牌放在第二堆牌上,再把它们放置在第三堆牌上,所以此时分布的卡牌顺序以及该顺序卡牌的分三堆排列后的展示如下:

image.png

image.png

(4)接着继续来根据结果J得知最终结果是在第二堆牌,重复上述逻辑,将把第一堆牌放在第二堆牌上,再把它们放置在第三堆牌上,所以此时分布的卡牌顺序以及该顺序卡牌的分三堆排列后的展示如下:

image.png

image.png

(5)经过三次排列后的卡牌,她猜想的结果实际就存在于三堆卡牌中的中间位置,此时只需要逐一翻开牌堆,询问她刚才所记录的卡牌是否存在于当前展开的牌堆即可,若表示在时,翻开中间的那一张牌既是刚刚被挑选记录的牌;

3.牌堆排列技巧

(1)若挑选的牌存在于第一堆,则转换为按1排列【3-->1-->2】,即:将第1堆放置于第2堆之上,再将第3堆放置于它们之上;;

(2)若挑选的牌存在于第二堆,则转换为按2排列【1-->2-->3】,即:将第2堆放置于第3堆之上,再将第1堆放置于它们之上;

(3)挑选的牌存在于第三堆,转换为按3排列【1-->3-->2】,即:将第3堆放置于第2堆之上,再讲第1堆放置于它们之上;

4.代码参考

代码参考部分实在是没啥可参考的,主要是搞原生JS写了一个拖拽的程序,用JQuery写了一些dom元素排列的实现,搞了个websocket与后端Java通信获取的随机十五个数字,再有就是HTML的默认布局展示了,所以没啥可参考的,可见后面一篇《SpringBoot集成WebSocket的两种方式》中所述的源码下载部分下载本文全部示例代码,本次的参考代码将给出一个原生JS推拽元素的实现,参考如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
      html , body {
        margin: 0;padding: 0;height: 100%;
      }
       ul.source {
           margin:0;
           height: 215px;
       }
       ul.source li {
           list-style: none;
           display: inline-flex;
           width: 110px;
           font-size: 160px;
           color: red;
       }
       ul.source li div {
           cursor: move;
       }

       ul.target {
         margin:0;
         list-style: none;
       }
       ul.target li {
         margin: 10px;
         border: 1px solid lightgray;
         display: inline-flex;
         width: 110px;
         height: 160px;
       }

       ul.target li div {
         width: 110px;
         font-size: 160px;
         color: red;
       }

    </style>
  <script type="text/javascript">
      window.onload = function() {
          //源元素绑定事件
          document.querySelector(".source").onselectstart = function(){return false;};
          var sourceElements = document.querySelectorAll(".source div");
          for (var i=0 ; i < sourceElements.length ; i++) {
              var element = sourceElements[i];
              (function(elt) {
                  elt.onmousedown = function () {
                       sourceMove(event , elt);
                   };
                  elt.onselectstart = function(){return false;}; //取消字段选择功能
              })(element);
          }
          //移动后的元素绑定事件
      }

      function sourceMove(event , element) {
          window.mouseDown = true;
          window.moveElement = element;
          window.oldX = event.clientX - element.offsetLeft;
          window.oldY = event.clientY - element.offsetTop;
      }

      document.onselectstart = function(){return false;}

      window.onmousemove = function (e) {
          if (! window.mouseDown) {
              return;
          }

          console.log("移动中");
          window.newX = e.clientX;
          window.newY = e.clientY;
          window.moveElement.style.position = "absolute";
          window.moveElement.style.left = (newX - oldX) + "px";
          window.moveElement.style.top = (newY - oldY) + "px";
          //放置拖动到 上、左、右、下 以外的区域
          var left = window.moveElement.offsetLeft;
          var top = window.moveElement.offsetTop;
          if (left < 0) {
              window.moveElement.style.left = "0px";
          }
          if (top < 0) {
              window.moveElement.style.top = "0px";
          }
          var width = window.moveElement.offsetWidth;
          if (left + width > document.body.clientWidth) {
              window.moveElement.style.left = document.body.clientWidth - width + "px";
          }
          var height = window.moveElement.scrollHeight;
          console.log(document.body.clientHeight);
          console.log(document.body.offsetHeight );
          console.log(document.body.scrollHeight);
          console.log(window.screen.availHeight);
          console.log(window.screen.height);
          console.log(top + "," + height + "," + document.body.scrollHeight);
          if (top + height > document.body.offsetHeight) {
              window.moveElement.style.top = document.body.scrollHeight - height + "px";
          }

      }

      window.onmouseup = function (e) {
          window.mouseDown = false;
          window.moveElement = false;
      }


  </script>
</head>
<body>

<ul>
    <li><div onselect="return false;">&#x1F0B1;</div></li>
    <li><div>&#x1F0B2;</div></li>
    <li><div>&#x1F0B3;</div></li>
    <li><div>&#x1F0B4;</div></li>
    <li><div>&#x1F0B5;</div></li>
    <li><div>&#x1F0B6;</div></li>
    <li><div>&#x1F0B7;</div></li>
    <li><div>&#x1F0B8;</div></li>
    <li><div>&#x1F0B9;</div></li>
    <li><div>&#x1F0BA;</div></li>
    <li><div>&#x1F0BB;</div></li>
    <li><div>&#x1F0BD;</div></li>
    <li><div>&#x1F0BE;</div></li>
    <li><div>&#x1F0DF;</div></li>
    <li><div>&#x1F0BF;</div></li>
</ul>

</body>
</html>

5.其它知识点

(1)原生JS实现的元素拖拽功能,放置拖动至屏幕以外的区域;

(2)WebSocket的前后端交互示例;

(3)unicode小图标介绍;


 点赞


 发表评论

当前回复:作者

 评论列表


留言区