还在上班?很无聊?

这个叫前言

年末了。哦,不,要过年了。以前只能一路站到公司的我,今早居然是坐着过来的。新的一年,总要学一个新东西来迎接新的未来吧,所以选择了一直未碰的那个据说是全宇宙最牛逼的前端框架-React,在上下班的地铁上看了两天官方教程,so what。光看不练假把式,于是就想着做个什么,偶然看到一个妹妹发了一条关于玩数字华容道,根本停不下来的朋友圈,这游戏我在今年的最强大脑看过,但是就看两小天才在滑呀滑呀滑,感觉还不错,程序猿就该多玩益智类,少玩什么跳一跳。于是去商店下了个,玩着还行,就是广告太多,而且只能玩五阶以下的,看起不难,一个想法涌于脑上,何不拿这练练手做个Demo,毕竟我们属于智慧家族的。闲话扯完,进入正题。本文包含但不仅包括以下内容:

Demo 开发环境

数字华容道里的秘密

讲一讲里面算法的实现

React的使用感受及易错点

Demo 开发环境

React:16.2.0

react-router-dom:4.2.2

webpack:3.8.1

JS:ES6

CSS:Scss

项目目录结构(很适合React入门 如果感觉不错,请留下你的star):如下图所示

数字华容道里的秘密

玩法说明

数字华容道里在外国被称为puzzle,译为数字推盘,最经典的就是puzzle15的高价悬赏13 15 14局面的解。怎么玩,一图胜千言,简单来说就是讲左图的乱选状态,滑成右图所示的顺序状态。个人感觉和小时候玩的推箱子有点类似。

你不知道的秘密

其实写完Demo的随机序列页面生成和操作交互就用了一个周天和一个周一晚上,但到现在线上这个样子,又多用了三四个晚上(白天上班,晚上学习,这就是前端的日常),为什么?因为当时基础版部署到线上,让女朋友试一把,结果玩个三阶的,都两分钟了还在折腾(我最快是18秒还原),怎么这么笨,于是抢过来,捣腾,再捣腾,怎么回事,感觉无解啊,于是去百度了一下,在知乎里看到了这个问题,还真的有无解的情况,问题地址。看图,后面还要讲(敲黑板)

噢,原来是酱紫。光随机生成一个乱序数列是不够的,还得保证这个数列的逆序数为偶数,嗦嘎。于是在随机序列的生成中又多加一个过程,判断序列逆序数奇偶性,并调整。早上地铁上自己又不断玩玩测试,三阶ok,四阶ok,五阶ok,然后又一遍,一遍。原以为这样就大功告成了,但是出现了这样的画面。有图。谁刚说的四阶ok。。。。于是又测试了多次,发现三阶,五阶确实ok,但四阶确实有Bug。Why,后面自己每开一局,截一张图,无解的,标记下来,下面就是几张立功的图片。

下午年会,领导上面讲,自己下面睡。睡得天昏地暗,时过境迁,居然还在叨叨叨,自己就拿起酒店提供的纸和笔找这些数字间的秘密。首先,这几组数字都是偶逆序列,前一晚写的调整奇逆序列为偶逆序列的代码是没有问题的,那问题出在哪了。抓脑抠鼻,抖脚摇头,那一组图片来回翻阅,灵光一闪,水哥附身,原来是这样:空格项都出现在第三行,哦,不,应该是奇数行。为什么呢?又去百度,又看到了上面知乎和豆瓣的正经说瞎话的大神(此生最讨此类人,害死个仙人),看到这,我开始怀疑,这句话的正确性。奇数阶,格子上下左右移动确实不会改变数列的逆序奇偶性。但偶数阶,格子的上下移动是会改变序列的奇偶性的,简单总结一下:

奇数阶(3x3,5x5):上移或下移一个数字,其调换的位置是偶数,所以不改变数列逆序数的奇偶性,所以奇数阶,生成的初始随机数列的逆序数必须为偶数;

偶数阶(4x4,6x6):上移或下移一个数字,其调换的位置是奇数,所以会改变数列逆序数的奇偶性,上下交换一次改变一次奇偶性,交换两次就回到初始状态。所以可以大致这样理解,偶数的平方仍然为偶数,其有数字的滑块个数为奇数个,所以有一个数字必然会和空滑块产生位置交换,如果空滑块位于奇数行(空滑块是不参于数字序列的逆序数计算的),就会产生2n-1次交换,其会改变数列逆序数的奇偶性;而位于偶数行,就会产生2n次交换,不会改变数列逆序数的奇偶性,所以用一个公式总结就是:(数列初始状态是否为偶数) === (空行是否为偶数),简单来讲就是求这两个数的异或。最后的代码流程的实现

讲一讲里面算法的实现

生成一个乱序不重复的1~n数组数列

方法有很多,但我知道的两种,这里分享一下,有知道其他的,请留言做个评论,让大家一起进步。

顺序数组随机性调换

思路基本就是,先生成一个顺序的1~n的顺序数组,然后再通过一个1~n的循环来打乱这个数组,其时间复杂度是O(n)。代码如下。

export const disorganize = (length) => {

const arr = [];

let temp;

for (var i = 1; i < length; i++) {

arr.push(i);

}

for (i = 0; i < length; i++) {

let random = Math.round(Math.random() * (length - 2));

temp = arr[random];

arr[random] = arr[i];

arr[i] = temp;

}

return arr;

};

随机数生成乱序数组

生成一个随机数,并判断其是否在目标数组中已存在,当数组个数为n时,目的达到。其时间复杂度我不知,代码如下:

export const randomArr = (length) => {

const arr = [];

let temp;

while(arr.length

let random = 1+Math.round(Math.random() * (length - 2));

if(random

arr.push(random);

}

}

return arr;

};

虽然代码看起比上面的简单,但其时间复杂度最由是O(f(n),最差情况未知,所以,方法一更推荐,如果说的有什么毛病,还请及时指出。

数列逆序性的奇偶性判断

最先想到的就是冒泡排序,因为冒泡排序过程就是判断两个数是否逆序,是,就交换,不是,继续下一组判断。所以,我们直接将交换的次数,记为数列逆序数个数,就达到了想要的效果。当然这个题用其他排序方法也能达到目的,理解了其排序的原理,就很容易计算数列的逆序性,我这里是直接用的以前冒泡排序的算法。

const bubbleOrder=(arr)=>{

let i ,j ,count=0;

const swap=(tar,lastIndex,newIndex)=>{

let temp = tar[lastIndex];

tar[lastIndex] =tar[newIndex];

tar[newIndex] = temp;

count++;

}

for(i=0;i

for(j=arr.length-1;j>i;j--){

(arr[j]

}

}

return count;

}

JS写一个秒表

秒表是啥,start-pause-stop-reset,中间的步骤不是必须的,但前后两步必须。当然方法有很多,但都离不开setTimeout或则setInterval两个方法,requestAnimation应该也可以。这里提供一个自己写的,当然思路来源于网上,只是用自己的思路表达出来。基于setInterval和Date对象。源码如下:

const timer=(offsetTime)=>{ //offsetTime为0时,表示从0开始计,不为0,表示是暂停后继续计时

const formatter=(t)=>{

const res =t>9 ? t : '0'+t

return res;

}

let startTime = new Date().getTime(),tPass=0,tOffset=offsetTime||0;

this.interId = setInterval(()=> { //this.interId 是组件下面建的一个保持定时器值的,用于暂停和停止

let tNew = new Date().getTime(),ms,sec,min,timeStr;

tPass = tOffset +tNew - startTime;

ms = Math.floor(tPass/10 % 100);

sec = Math.floor((tPass / 1000) % 60);

min = Math.floor((tPass / 1000 / 60) % 60);

timeStr = formatter(min)+':'+formatter(sec)+':'+formatter(ms);

this.tick(timeStr,tPass);

},100)

}

tick(timeStr,tPass){ //这是游戏页面一个react组件中的一个用于更新显示dom的触发器

this.setState({

timePass:tPass,

time:timeStr

})

}

React的使用感受及易错点(大神留步)

用Vue与用React的区别,抱头痛哭,Vue半年没上项目了,忘得差不多了,个人观点(非喜勿喷)。

直接感受就是,Vue确实比React容易上手,其模板,js,css的组件式的开发方式,更接近我们以前工作中常用的template + requireJs的开发模式。

React更强调js的编程和项目的整体架构,state放在哪一级,哪一级通过props来控制,当然route 4.0的组件化设计更强调这一点;

React在国内还是不像Vue那么大众,比方说,出了问题,很多只有在stackOverflow有相关答案;

不过,不论是Vue还是React,熟悉ES6和面向对象的编程,两者上手都是很快的(装个逼,别打我)。

在整个学习过程中,将很多教程中敲黑板指出来的坑,又结结实实踩了一遍,现在可以说影响深刻。自己整理了一下,做个小分享,愿和我一样刚入门的,遇见下面的错误,不会那么迷茫

不要在

Cannot read property 'setState' of undefined'

解释:这个问题,主要是组件对象的构造constructor中,未在constructor绑定事件处理函数的this指向。这个在教程中是有明确说明的,解决办法就是constructor()中添加:this.resetClick = this.resetClick.bind(this);

Cannot read property 'size' of undefined'

解释:这个问题,主要是组件对象的构造constructor中,未传入props对象,导致整个组件对象无props属性;其实除了理解继承,理解React组件的生命周期也很重要。

you are adding a new property in the Synthetic event Object

解释:可以简单理解为SyntheticEvent是react为浏览器兼容写的一个dom事件代理,除了她原有的那些属性,你不能私自为其添加属性。

iphone,元素滑动,页面会跟随滑动

这个真的是一个让人头疼的东西,太影响交互体验了。如果做过h5都知道加滑动阻止.而react有他自己的一套事件机制封装,所以在跟元素直接添加touchmove的preventDefault是不行的。得用最原始的事件写法写一个阻止滑动的触摸事件,如下所示。

componentDidMount() {

document.addEventListener('touchmove', (e) => {

e.preventDefault();

}, { passive: false });

}

其他,后面持续补充

一个疑问

一开始我的游戏盒子是用的flex布局,但一考虑,盒子里面的方块要滑动效果,我要做滑动的缓动效果,于是又改用了绝对定位布局,每个

方块计算其定位点。但事实证明,我当时确实太菜,我用了state来管理每个方块在盒子的位置,但我调整state时,React的virtualDom

会自动计算,并更新dom节点,那我保持整个项目,怎么才能自己做出缓动效果呢?纯CSS不行,请各位大神给点建议。

结束语

在放假的前几个小时,把拖了几天的文章写完,有点赶,有不足的地方还请及时指出。关于这个项目,后期自己想继续优化,做一些功能拓展,比如接入数据记录,NxM阶这样的玩法,有思路的,还请能分享给我,邮箱:closertb@163.com。在最后,送给2017未曾放弃努力的自己一些鼓励,愿2018年能用更好的发展。也祝各位战友2018新年快乐,年后再见!!!!

python数字华容道算法_用React写一个数字华容道,你需要知道的秘密相关推荐

  1. react做h5 例子_使用React写一个网站的心得体会

    网站是毕业设计的作品,开发这个网站的目的主要用于记录一些笔记,以及聚合一些资讯信息,也算自己在网络世界中的一块静地吧,可以在这里一些技术上想法的实践. 网站最初前端使用vue开发,在前段时间由于项目的 ...

  2. 用python制作勒索病毒_用c写一个小勒索病毒(用B站来学习)

    前言: 这里是根据B站上的一个视频,看着教学写的,一下是我对代码的分块解析记录,方便想入门写病毒和反病毒小工具的人学习. 准备 vc++2013 b站学习视频 新建项目 我就是一开始新建项目都不清楚, ...

  3. 用pycharm进行python爬虫的步骤_使用Pycharm写一个网络爬虫

    在初步了解网络爬虫之后,我们接下来就要动手运用Python来爬取网页了. 我们知道,网络爬虫应用一般分为两个步骤: 1.通过网页链接获取内容: 2.对获得的网页内容进行处理 这两个步骤需要分别使用不同 ...

  4. python迷宫万花筒代码_用Python3写一个走迷宫的小程序(图形化:matplotlib,dfs,prim)...

    先看一下动态效果图(慢放): 首先生成迷宫: 主要用了两个算法:Prim和dfs 总结:Prim生成的比较像真正的迷宫,所以默认用了Prim生成迷宫 先输入n,m,会生成一个迷宫(prim生成),然后 ...

  5. python如何多行输出_python换行输出 Python里具体怎么用\n换行输出一个数字?

    python里 如何把每打印10个数就换行的实现 print("每输出十个数字换行,共计输出100个:")for num in range(1,100):#循环一百次 print( ...

  6. [react] 写一个react的高阶组件并说明你对高阶组件的理解

    [react] 写一个react的高阶组件并说明你对高阶组件的理解 定义高阶组件 import React, { Component } from 'react';const simpleHoc = ...

  7. [react] 使用react写一个todo应用,说说你的思路

    [react] 使用react写一个todo应用,说说你的思路 拆分组件:应用 + 表单部分(input + button).列表部分(checkbox + ul>li + delete but ...

  8. Python 中将列表中的每个元素除以一个数字

    Python 中将列表中的每个元素除以一个数字: 使用列表理解来遍历列表. 在每次迭代中,将当前列表元素除以数字. 新列表将包含除法结果. my_list = [8, 12, 20]# ✅ divid ...

  9. 7-114 谁先倒 (15分) 划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和,谁就输了

    划拳是古老中国酒文化的一个有趣的组成部分.酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字.如果谁比划出的数字正好等于两人喊出的数字之和,谁就输了,输家罚一杯酒.两人同赢或两人同输 ...

最新文章

  1. php无表单上传文件,php – 来自表单的WP邮件附件,无文件管理器上传文件
  2. 再来一个吊打百度网盘的开源神器,还是99年妹子开发的
  3. No Team Selected:A team must be selected to run 'ProjectName' on iPhoneName
  4. 3.8 高级检索方式(二)
  5. java 带点的字符串处理,关于android:java中字符串上带点的分割函数
  6. eclipse egit 报错 The current branch is not configured for pull No value for key branch.master
  7. C语言:一个五位数,判断其是否为回文数
  8. Linux成长之路-基础篇(2)
  9. VS2010+OpenCV2.4.9配置
  10. python表白代码大全简单-python表白代码
  11. 简历里的软件测试工作描述,软件测试类相关工作的简历范文
  12. 项目管理 之技术管理
  13. Java 常见面试题
  14. 全局光照:光线追踪、路径追踪与GI技术进化编年史
  15. [个人笔记]HCIP-Routing Switching-IERS/H12-221
  16. 《我的团长我的团》书及电视剧观后感
  17. QCon-小布助手对话系统工程实践
  18. 推荐一个专利检索的网站
  19. 读书笔记,《刻意练习》,第三章,心理表征
  20. Android activity进出动画,类似于左右拉窗帘效果

热门文章

  1. 项目管理图表有哪些 这5种一定要知道
  2. 事业单位工资计算机公积金计算,求问事业单位住房公积金如何计算
  3. c语言编程大体思路,C语言:程序的设计思路跟特点
  4. 彭佳慧 - 走在红毯那一天
  5. 【小米8手机的状况】
  6. 不就是语法和长难句吗-思维导图分享
  7. Flutter 修改App Logo图标
  8. tableau和oracle dv,比较Power BI和Tableau,好比用奔驰对比奥迪
  9. es数据更新时间_京东到家订单中心系统mysql到es的转化之路
  10. 安卓手机如何防盗_安卓手机也能像苹果一样!教你如何查看安卓手机电池损耗...