精华内容
下载资源
问答
  • 数据集的第部分是10000图片被用来测试,与训练数据的格式一样。我们将使用测试数据衡量我们的神经网络学习得怎么样。当然第部分的图片是另外250个人的手写样本,这有可以让我们证实网络可以识别不在训练集中的...

    一个简单的手写数字分类网络

    接上一篇文章,我们定义了神经网络,现在我们开始手写体的识别。我们可以将识别手写数字这个问题划分为两个子问题,一,我们需要将一幅包含了许多数字的图像分解为一系列独立的图像,每一幅图像包含了一个数字。比如,我们需要把下图分解:
    这里写图片描述
    将该图分解为6幅独立的图像:
    这里写图片描述

    我们人可以很轻松的将其分开,但是计算机可不那么认为。一旦图片被分割后,程序需要将每个数字单独识别。因此,举个例子,我们想要我们的程序可以识别上图中的第一个数字为5。
    这里写图片描述

    这里我们致力于解决第二个问题,就是对单一数字的分类。因为对于第一个分割问题,这里有许多方法可以解决了。因此,与其关⼼分割问题,我们不如把精⼒集中在设计⼀个神经⽹络来解决更有趣、更困难的问题,即⼿写数字的识别。

    为了识别单个数字,我们将用到三层神经网络:
    这里写图片描述

    网络的输入层包含了对输入像素值编码的神经元。正如后面讨论的,我们的训练数据有许多28X28的手写数字的像素图组成,也就是说我们的输入层包含了28X28=784个神经元,一个神经元对应一个像素位的值。输入的像素值为灰度值,0.0表示白色,1.0表示黑色,0到1之间的值表示不同程度的灰色。

    网络的第二层为隐藏层,我们记隐藏层的神经元数量为n,我们将对n的取值进行实验。这个图例中展示了一个小的隐藏层,它的隐藏层只有15个。

    网络的输出层包含了10个神经元。如果第一个神经元被激活,也就是输出值无限接近1,那么我们可以认为这个网络识别出来的数字是0.如果是第二个神经元激活,那么识别出来的数字为1。更准确的说,我们将对输出神经元从0到9编号,然后找出激活值最高的神经元。如果编号为6的神经元激活值最高,那么我们认为输入的数字为6。

    这里使用是个输出神经元很现实是为了对应输出的十种可能性。一种看起来更自然的方法是使用4个输出神经元,每一个神经元看作一个二进制数,结果取决于改神经元输出更靠近0还是更靠近1。4个输出神经元对于10个数字来说已经足够了,毕竟24=16是大于10的。那为什么我们选择使用是个输出的神经元而不是看起来更方便简洁的4个神经元呢?经验告诉我们:通过对两种设计的实验对比,是个输出的神经元比4个输出的神经元更加准确的识别数字。但这是为什么呢?有没有什么启发性的方法可以告诉提前告诉我们使用10个输出神经元比使用4个效果要更好。

    为了理解为什么要这样做,了解神经网络的工作的基本原理是很有帮助的。首先考虑我们使用10个输出神经的情况。让我们把目光放在第一个输出神经上,该神经决定了是否该数字是0。它是通过权衡隐藏层所输出的信息做出判断的。那么隐藏层的神经元做了些什么呢?假设隐藏层的第一个神经元是为了检测图像中是否存在如下图形:
    这里写图片描述

    它是通过对输入图像中与该图形重合的像素赋予很大的权值,而其他部分赋予很小的权值来判断的。以同样的方式,我们假设第二个第三个第四个神经元分别是为了探测图像中是否存在以下图形:
    这里写图片描述

    可能你已经看出来上面四个图形可以组成数字0:
    这里写图片描述

    因此,如果隐藏层的这四个神经元都被激活,那么我们可以认为这个图像上的数字是0。当然这不是我们用来推断数字为0的唯一组合,我们可以通过诸多图形组合得到0(比如将上图进行扭曲变形,但它还是0)。但至少在这个例子中,我们可以推断出输入数字是0。

    如果神经网络是这样工作的,那么我们似乎可以给出一个对为什么使用10个输出神经而不是4个这件事一个合理的解释。如果是4个输出神经元,那么,我们的第一个输出神经元将用于判断该数字对应二进制的最高有效位是什么,然而,我们很难将图形和数字的最高有效位对应起来。

    上面说了这么多都只是一个启发性的方法,没人说三层神经网络必须按照我上面所说的方式去工作,即每个隐藏层的神经元去探测一个简单的图像组成部分。也许一些聪明的学习算法会找到一些权重分配让我们使用4个输出神经元。但是作为一种启发,我所描述的方法可以工作的很好,这可以让你节省许多时间在设计神经网络的结构上。

    使用梯度下降算法进行学习

    现在我们已经设计出了一个神经网络,那么我们如何使用它去学习识别数字呢。首先,我们需要一个数据集去学习,我们使用的是MNIST数据集,它包含了数以万计的手写数字的扫描图像,以及他们的正确分类。下图是取值MNIST的几个图像:
    这里写图片描述

    正如你所见,这些数字和上一篇文章的数字是一样,当然我们需要我们的网络可以识别不在数据集中的图像。

    MNIST数据集包含两个部分,第一个部分包含了60000张图片被用作训练数据。这些通过扫面250个人的手写数字获得,其中有些是美国人口普查局的员工,有些是高中生。这些图像是28X28的灰度图。数据集的第二部分是10000张图片被用来测试,与训练数据的格式一样。我们将使用测试数据衡量我们的神经网络学习得怎么样。当然第二部分的图片是另外250个人的手写样本,这有可以让我们证实网络可以识别不在训练集中的人的手写数字。

    我们用x表示一个训练输入。显然x是一个28X28=784的向量,向量中每一个元素表示图像中的一个灰度值。我们用y=y(x)表示对应的期望输出值,其中y是一个10维的向量。比如,有一个特定的显示为6的图像输入为x,那么它期望的输出值应该为y(x)=(0,0,0,0,0,0,1,0,0,0)T,其中T表示矩阵的转置。

    我们想有这样一个算法,它可以让我们找到权重和偏差,这样网络的输出y(x)可以拟合所有的输入x。为了量化我们如何实现这个目标,我们定义一个代价函数:
    这里写图片描述

    其中w记为网络中的所有权重的集合,b为所有的偏差,n是所有训练输入的数量,a是当输入向量为x时网络的输出向量,并且对所有的输入x进行计算并求和。的确,输出a依赖于输入xwb,但是为了简介,我并没用使用axi这样的符号。符号||v||表示的是向量v的长度(模)。我们把C称为二次代价函数,有时也被称为均方误差或者MSE。观察二次代价函数,我们可以发现C(w,b)是非负的。此外,对于所有的x,当y(x)接近于a时,C(w,b)的值是很小的,也就是C(w,b)0,因此我们的训练算法需要能够找到合适的权重和偏差,使得C(w,b)0相反,如果C(w,b)的值很大,就说明有大量的y(x)a相差很大,这是不好的。因此我们的训练算法目标是要能够找到最小化代价函数C(w,b)的权重和偏差。换句话说,我们需要找到一组权重和偏差,使得代价最小,下面我们将使用梯度下降算法来达到目标。

    为什么要介绍二次代价函数?我们不应该关注于图像的正确分类的数量上面吗?为什么不尝试直接最大化正确分类的数量而是要使用最小化一个二次代价函数来简介评测呢?这是因为正确分类图像的数量对于权重和偏差来说不是一个平滑的函数,那么在大多数情况下,对权重和偏差的微小改变不会造成目标函数即正确分类数量的值的改变,这让我们很难找到通过改变权重和偏差提高性能的方法。如果我们使用一个像二次代价函数这样的平滑函数,那将很容易找到通过改变权重和偏差来提高性能的方法。这就是我们为什么专注于最小化二次代价,因为只有这样,我们才能测试分类的准确性。

    那么可能你又会好奇为什么要选择式(6)那样的二次函数来作为平滑函数呢?这时临时想出来的么?可能如果我们选择另外一个不一样的代价函数,我们将会得到不同的代价最小时的权重和偏差。这个疑问是有必要的,稍后我将对上面的成本函数再次进行讨论,并作一些修改。然而式(6)中的代价函数对于我们理解神经网络的基础很有帮助,所以我们将一直使用它。

    重申一次,我们的目标是训练一个神经网络,找到权重和偏差使得二次代价函数C(w,x)最小化。这个目标没毛病,但是,现在有许多让我们分散精力的东西——对权重w和偏差b的解释,难以弄清的σ函数,网络架构的选择,MNIST等等。其实我们可以通过忽略上述这些中的绝大部分,仅仅考虑最小化这一点来理解这些东西。现在,我们打算忘掉代价函数的具体形式,神经网络的组成等等。现在我们只专注于最小化一个给定的多元函数。我们将学习一种用于最小化问题的梯度下降算法,然后再回到我们想要最小化神经网络的特定函数上去。

    OK,现在假设我们尝试最小化某些函数,C(v),它可能是任意的多元实数函数,v=v1,v2,...。注意到我将使用v代替前面的wb,因为我们刚说过我们不再特定研究神经网络代价函数的最小化问题上,而是任意的函数。我们先假设C是只有两个变量的函数,我们称为v1v2
    这里写图片描述

    我们想要找到使C达到全局最小的位置。现在对于上述的图像中,我们可以很容易的找到全局最小值。从某种意义上说,我可能展示了一个过于简单的函数。通常函数C是一个拥有许多变量的复杂的函数,并且将不可能通过肉眼一下找到它的全局最小值。

    解决这个问题的一种方法是使用微积分的方法。我们将计算函数C的导数来寻找它的极值点。运气好的话函数可能只有一个或者几个变量,但是一旦变量过多那将很麻烦。尤其是神经网络中,往往拥有数亿计的权重和偏差,微积分的方法将不再有效。

    现在微积分是不能解决最小值的问题了。幸运的是,有一种漂亮的推导法暗示有一种算法可以很好的解决问题。首先我们把函数想象成山谷,向上面那幅图画一样。然后我们假设有一个球从山谷上沿斜坡滚下,常识告诉我们这颗球会滚落到山谷底部。也许我们可以使用这样一个想法去寻找函数的最小值。开始我们把球随机放置在一个位置,然后模拟球从该点滚落到谷底这一过程。我们可以通过计算C的导数(和一些二阶导数)来简单模拟——这些导数将告诉我们这个山谷的一切局部形状,然后我们就知道这个球该怎么滚落了。

    说了这么多,你可能会以为接下来我将介绍牛顿定理,摩擦力和重力对球体的影响。事实上,我们只是做了一个假设,并不是真的要用这个球的运动来寻找最小值。提到球只是用来激发我们的想象力,而不是束缚我们的思维。因此与其陷进物理学⾥凌乱的细节,不如我们就这样问⾃⼰:如果我们扮演⼀天的上帝,能够 构造⾃⼰的物理定律,能够⽀配球体可以如何滚动,那么我们将会采取什么样的运动学定律来 让球体能够总是滚落到⾕底呢?

    为了使这个问题更明确,让我们讨论当我们将球在v1方向上移动Δv1,在v2方向上移动Δv2。微积分告诉我们C的改变量为:
    这里写图片描述

    我们需要找到一种方法,找到一个Δv2Δv2,使得ΔC为负值,即球总是在往低处移动。因此,我们需要定义Δvv的变化向量,Δv=(Δv1,Δv2)T。我们还需要定义C的梯度为偏导数的向量:(Cv1,Cv2)T。我们用C表示梯度向量:
    这里写图片描述

    后面我们将会用CΔv来重写ΔC,在此之前,我想先解释一下令人困惑的梯度这个概念。当我们第一眼看到C的时候,可能会尝试想去理解这个符号的意义。那它究竟是什么意思?事实上,你可以把它简单的当作是上述梯度向量的一个记号。也有很多其它的数学上不同视⻆对于的专业解释(⽐如,作为⼀个微分操作),但我们不需要这些观点。

    有了这些定义,(7)式中的ΔC可以被重新写作:
    这里写图片描述

    这个等式帮助我们理解为什么C被称为梯度向量:CCv的变化关联到C的变化,就像我们期望的用梯度来表示。但是,这个等式真的让我们激动的是因为,它可以让我们知道如何选择Δv来使得ΔC为负值。特别的,假设我们选择:
    这里写图片描述
    其中η是一个很小的,正的参数(被称为学习速率)。然后等式(9)就变为ΔCηΔCΔC=ηC2。因为C0,这使得ΔC0,也就是说C将总是减小。(当然要在方程9的近似约束下)。这个属性正是我们期望的!因此,我们使用方程(10)来定义球在梯度下降算法中的下降”定律”。也即是我们使用方程(10)来计算Δv的值,然后根据下面的值来移动球的位置v
    这里写图片描述

    然后我们再一次使用这个更新规则,就可以计算它下一次下降的位置。如果我们一直这样做,C将一直减小知道我们希望它到达全局最小值。

    总结一下,我们使用的梯度下降算法的工作就是重复计算梯度C,然后沿着相反方向移动,滚下山谷。我们可以可视化这一过程:
    这里写图片描述

    注意到梯度下降规则并不满足真实的物理规则。在真实世界中,球有动量,动量可能允许它偏移斜坡,甚至向上滚。只有在摩擦力的影响下它才可能滚到山谷。相比之下,我们选择Δv规则就像在说”只能往下滚!”,这是一个好的方法去寻找最小值。

    为了使梯度下降正确地工作,我们需要选择一个足够小的学习速率η,使得等式(9)可以很好的近似。如果不这样,我们可能将会以ΔC>0结束,这显然是不好的。同样,我们又不希望η太小,这样会使的Δv变化太小,梯度下降算法就会下降得特别慢。在实际实现中,η通常是变化的,这使得等式(9)能够保持很好的近似度,同时算法又不会太慢。稍后我们将看到它如何工作。

    我已经解释过当C只有两个变量时的梯度下降算法了。但是,事实上,即使C有许多变量,也是这么一回事。假设C是一个有m个变量的函数v1,v2...,vm,然后当Δv=(Δv1,...,Δvm)TCC的变化量ΔC为:
    这里写图片描述

    其中梯度C为向量:
    这里写图片描述

    和前面的两个变量时的情况一样,我们可以选择:
    这里写图片描述

    我们保证我们的近似表达式(12)的值也将是负值。这将是我们可以在C为多个变量时,通过重复下面这一个更新规则,来找到我们的全局最小值:
    这里写图片描述

    你可以认为这个更新规则就是我们的梯度下降算法。它提供了重复改变位置v来使得函数C取最小值的方法。这个规则并不总是有效的,它有时候也会出错并使得我们无法通过梯度下降来寻找C的最小值,后面我们将讨论这个问题。但是,实际使用中,梯度下降往往工作的很好,并且发现它是在神经网络中寻找代价函数最小值的好方法,对网络的学习很有用。

    的确,在这种情况下,梯度下降是寻找最小值的最优策略。假设我们尝试移动Δv,最大程度的减小C.这等价于最小化ΔCCΔv。我们限制步长为一个很小的固定值:Δv=ϵϵ>0。换句话说,我们想在步长固定时,找到使得C下降得最快的方向。可以证明,使得CΔv最小化的ΔvΔv=ηC,其中η=ϵ/C,它是由步长限制ΔC=ϵ所决定的。因此,梯度下降可以看作一种使得C下降最快的方向上做微小移动的方法。

    人们已经研究了梯度下降的许多变化形式,包括一些更接近真实的球的物理运动的形式。这种模拟球的形式有许多优点,但是也有一个重大的缺点:它最终必须计算C的二偏导,这将花费巨大的代价。为了理解为什么这么做代价很高,假设我们需要计算所有的二阶偏导2C/vjvk。如果我们有百万个变量vj,那么我们需要计算数万亿级别(百万的平方)的二阶偏导。那将会花费巨大。说了这么多,有一些技巧可以避免这些问题,寻找梯度下降算法的代替发也是一个很活跃的研究领域。但这本书我们将使用梯度下降法(和变种)来作为我们神经网络学习的主要方法。

    我们如何将梯度下降算法应用到一个神经网络?其思想是,使用梯度下降算法找到权重wk和偏差bl,使得代价公式(6)的值最小。为了了解这是如何实现的,让我们重申一下梯度下降算法的更新规则,用权重和偏差代替变量vj。换句话说,我们的”位置“现在由wkbl组成,梯度向量对应的元素变为C/wkC/bl。以向量中元素的形式写出梯度下降的更新规则,我们有:
    这里写图片描述

    通过迭代使用这个更新规则,我们可以“滚下山谷”,找到期望的最小的代价函数。换句话说,这个规则可以用来学习神经网络。

    在应用梯度下降时有许多挑战,我们将在后面的深入探讨这个问题。现在,我仅仅关注一个问题,在提出问题之前,我们先回顾一下公式(6)中的二次代价函数。这个代价函数有着C=1nxCx的形式,也就是它是遍及每个训练样本代价Cx=y(x)a22的均值。在实际中,为了计算梯度C,我们需要单独计算每一个输入样本x的梯度Cx,然后再求平均C=1nxCx。不幸的是,当训练样本过大时,这会使得训练花费的时间很长。

    有一种叫做随机梯度下降的方法可以用来加速学习。这个思想就是通过随机选取小的训练样本来计算Cx来近似估计C。通过平均这一个小的样本就可以快速的估计出梯度C,这有助于帮助我们加速梯度下降,进而更快的学习。更精确地说,随机梯度下降是通过随机选取一个小数量地训练样本m作为输入。 我们将这些随机的输入样本记为X1,X2,...,Xm,并把它们称为一个小批量数据。假设提供的样本容量m是足够使得Cxj与计算所有得样本Cx的值约等,即
    这里写图片描述

    其中第二个求和公式是对所有的训练样本而言。通过上式我们得到:
    这里写图片描述

    也就是我们可以通过计算样本大小为m<全部样本的小批量数据的梯度,来估计整体的梯度。为了明确地将其和神经网络联系起来,假设wkbl分别为神经网络的权值和偏差。然后随机梯度下降通过随机选取一个训练样本作为输入,然后通过下式训练:
    这里写图片描述

    其中两个求和符号是在随机选取的小批量的训练样本上进行的。然后我们使用另一组随机的训练样本去训练,以此类推,直到我们用完了所有的训练输入,这样被称为一个训练迭代期。然后我们会开始一个新的训练迭代期。

    另外,对于改变代价函数⼤⼩的参数,和⽤于计算权重和偏置的⼩批量数据的更新规则,会有不同的约定。在等式(6)中,我们通过因子1n来改变整个代价函数的大小,人们有时候忽略1n,对单个训练样本的代价求和而不是平均。这对我们提前不知道训练样本总数的时候特别有效,比如学习数据是实时产生的。同样,在式子(20)(21)中的1m也可以舍去。但是需要注意的是,这样会导致学习速率的改变,对不同工作进行对比时,需要注意是求平均还是求和。

    实现我们的数字分类网络

    现在我们准备开始用代码通过随机梯度下降和MNIST训练集实现我们的识别网络。我们将使用python(2.7)来实现,仅仅74行代码!首先我们需要获得MNIST数据集,如果你使用git,你可以通过克隆代码库来获取:
    git clone https://github.com/mnielsen/neural-networks-and-deep-learning.git
    如果你不使用git也可以点击这里来获取数据和源码。

    顺便提一下,之前我说MNIST数据集被分成了60000个训练图像和10000个测试图像,那是官方的描述。事实,我们将对这些数据做一些不同的划分。我们将对60000个MNIST训练集分成两部分,其中50000作为训练集,另外10000作为检验集。在这里我们先不会使用检验数据,但是在后面我们将会发现它对于神经网络中一些如学习速率这样的超参数的设置很有用,这些超参数不是学习算法所决定的。景观验证数据不是原始MNIST的规范,但是许多人都这样使用MNIST数据集,并且在神经网络中使用验证数据是很普遍的。从现在开始我们提到的MNIST训练数据指的是50000张训练图像而不是原始的60000张图像。

    除了MNIST数据集以外,我们还需要python中的Numpy包,用于快速线性代数运算。

    在列出一个完整的代码清单之前,让我先解释一下神经网络代码的核心特性。核心是一个Network类,用来表示神经网络,下面是初始化网络Network类的代码:

    class Network(object):
    
        def __init__(self, sizes):
            self.num_layers = len(sizes)
            self.sizes = sizes
            self.biases = [np.random.randn(y, 1) for y in sizes[1:]]
            self.weights = [np.random.randn(y, x) 
                            for x, y in zip(sizes[:-1], sizes[1:])]

    在这个代码中,list对象sizes包含了各层中神经元的数量。比如,你想创建一个第一层有2个神经元,第二层3个神经元,第三次1个神经元的网络,你可以这样创建类对象:

    net = Network([2, 3, 1])

    网络对象中的偏差和权重是初始化为随机值,使用Numpy包中的np.random.randn函数来产生均值为0,标准差为1的⾼斯分布。这个随机初始化也就是我们使用随机梯度下降算法的一个起点。后面我们将讨论其他初始化权重和偏差的方法。注意,Network初始化代码中是假定第一层为输入层的,并且对这些神经元不设置任何偏差,因为偏差仅仅被用于后面层输出的计算。

    另外偏差和权重以Numpy矩阵列表的形式存储。因此,net.weights[1]是一个存储着链接第二层和第三层神经元权重矩阵。由于net.weights[1]写起来很冗长,我们就用w表示这个矩阵。也就是wjk表示的是第二次的第k个神经元和第三层的第j个神经元之间的权重。那么第三层神经元的激活向量为:
    这里写图片描述

    我们需要一块一块地来解释这个方程。a是第二层神经元的激活向量(输出向量)。为了获得a,我们用a乘以权重矩阵w,然后再加上偏差向量b。然后对向量wa+b中的每个元素使用σ函数。

    有了这些知识,很容易写出从Network计算输出的代码实例,我们从定义sigmoid函数开始:

    def sigmoid(z):
        return 1.0/(1.0+np.exp(-z))

    注意到当参数z是一个向量或者Numpy数组时,Numpy自动的对向量中每一个元素应用sigmoid函数。

    让后我们添加feedforward方法在Network类中,它对于网络给定输入a,返回对应的输出,这个方法是对每一层应用方程(22):

        def feedforward(self, a):
            """Return the output of the network if "a" is input."""
            for b, w in zip(self.biases, self.weights):
                a = sigmoid(np.dot(w, a)+b)
            return a

    的确,我们想要Network对象做的主要事情是学习。我们用SGD函数来实现随机梯度下降算法。下面是代码,有些地方比较神秘,我会在代码后面逐个分析。

    def SGD(self, training_data, epochs, mini_batch_size, eta,
                test_data=None):
            """Train the neural network using mini-batch stochastic
            gradient descent.  The "training_data" is a list of tuples
            "(x, y)" representing the training inputs and the desired
            outputs.  The other non-optional parameters are
            self-explanatory.  If "test_data" is provided then the
            network will be evaluated against the test data after each
            epoch, and partial progress printed out.  This is useful for
            tracking progress, but slows things down substantially."""
            if test_data: n_test = len(test_data)
            n = len(training_data)
            for j in xrange(epochs):
                random.shuffle(training_data)
                mini_batches = [
                    training_data[k:k+mini_batch_size]
                    for k in xrange(0, n, mini_batch_size)]
                for mini_batch in mini_batches:
                    self.update_mini_batch(mini_batch, eta)
                if test_data:
                    print "Epoch {0}: {1} / {2}".format(
                        j, self.evaluate(test_data), n_test)
                else:
                    print "Epoch {0} complete".format(j)

    training_data 是⼀个 (x, y) 元组的列表,表⽰训练输⼊和其对应的期望输出。变量 epochs 和mini_batch_size 正如你预料的 —— 迭代期数量,和采样时的⼩批量数据的⼤⼩。eta 是学习速率,η。如果给出了可选参数 test_data,那么程序会在每个训练器后评估⽹络,并打印出部分进展。这对于追踪进度很有⽤,但相当拖慢执⾏速度。

    update_mini_batch代码如下。在每一次迭代期,先随机排列训练样本,然后将它分成适当大小的小批量数据。这是一个简单的从训练样本随机采样的数据。然后对每一个小批量数据应用一次梯度下降。它仅仅使⽤ mini_batch 中的训练数据,根据单次梯度下降的迭代更新⽹络的权重和偏置:

      def update_mini_batch(self, mini_batch, eta):
            """Update the network's weights and biases by applying
            gradient descent using backpropagation to a single mini batch.
            The "mini_batch" is a list of tuples "(x, y)", and "eta"
            is the learning rate."""
            nabla_b = [np.zeros(b.shape) for b in self.biases]
            nabla_w = [np.zeros(w.shape) for w in self.weights]
            for x, y in mini_batch:
                delta_nabla_b, delta_nabla_w = self.backprop(x, y)
                nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
                nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]
            self.weights = [w-(eta/len(mini_batch))*nw 
                            for w, nw in zip(self.weights, nabla_w)]
            self.biases = [b-(eta/len(mini_batch))*nb 
                           for b, nb in zip(self.biases, nabla_b)]

    大部分的工作有下面这行代码完成:

     delta_nabla_b, delta_nabla_w = self.backprop(x, y)

    这行调用了一个称为反向传播的算法,可以快速的计算代价函数的梯度。因此update_mini_batch 的⼯作仅仅是对 mini_batch 中的每⼀个训练样本计算梯度,然后适当地更新 self.weights 和 self.biases。

    我现在不会列出 self.backprop 的代码。我们将在后面学习反向传播是怎样⼯作的,包括self.backprop 的代码。现在,就假设它按照我们要求的⼯作,返回与训练样本 x相关代价的适当梯度。

    测试:
    这里写图片描述

    首先创建三个py文件,第一个用来读取数据,第二个用来学习,第三个就是调用上面两个文件中的函数。
    源码下载地址:
    手写数字分类网络源码

    可以看到参数选取为:
    这里写图片描述
    即迭代30次,小批量数据大小为3,学习速率为3.0时的准确率如图:
    这里写图片描述 这里写图片描述

    准确率达到了94.67%。

    我们还可以通过自己生成一张手写数字的图片,测试一下结果,下面的图片是我通过画板自己画的:
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述

    我们可以通过改变神经网络隐藏层的神经元数量,或者学习速率,或者小批量数据大小来改变识别准确率。这些参数的选取,调试都是神经网络构造过程中重要的步骤。后面将会继续学习,下一篇文章将会讲到上面没有解释的backprop()函数,即反向传播算法。


    参考原文:http://neuralnetworksanddeeplearning.com/chap1.html#a_simple_network_to_classify_handwritten_digits
    以上是作者对原文的翻译和理解,有不对的地方请指正。


    注:转载请注明原文出处:
    作者:CUG_UESTC
    出处:http://blog.csdn.net/qq_31192383/article/details/77198870

    展开全文
  • 本文是对图像文字识别的简单...例如要识别在一张白纸上的“中国”个楷体黑,使用手机摄像头先进行扫描识别,然后自动翻译为“China”,再将“中国”和“China”显示到屏幕上,本文主要研究如何实现这个系统框架。

    本文是对图像文字识别的简单实现所做,并没有深入研究。本程序所实现的app对楷体字识别最有效。例如要识别在一张白纸上的“中国”二个楷体黑字,使用手机摄像头先进行扫描识别,然后自动翻译为“China”,再将“中国”和“China”显示到屏幕上,本文主要研究如何实现这个系统框架。
    本文地址:http://blog.csdn.net/yang786654260/article/category/5710631
    程序源码下载地址:本代码年代久远, 而且学生时代的代码水平很糟糕,就不分享了,大意就是用zxing来拿图识字。

    工作流程

    工作流程
    流程描述:
    环境光亮的情况下,经过摄像头扫描固定矩形区域图像,这样可以避免让手机对图像做截图处理,通过zxing辅助包在避免内存溢出的情况下获取到文字区域图像,进而对图像进行灰度化、去噪、二值化,如果判断黑色值像素数多于白色值像素度则进行反色处理,最后对图像切分提取特征值,将特征值传入谷歌ocr文字识别辅助包对谷歌识别库进行检索,查出相似值后,再通过辅助包提取识别库中的文字。本文为了减少Android系统的cpu使用度,将翻译交给了百度服务器处理,把提取到的文字上传到百度服务器,之后再服务器上翻译并返回结果。

    使用的第三方库

    • zxing
    • 谷歌ocr(tesseract ocr)

    界面展示

    主界面:
    这里写图片描述

    扫描界面:
    这里写图片描述

    说说几个图像处理算法

    灰度化本文采取的是浮点算法,实现代码如下

    private static Bitmap getGrayImg() {
            int alpha = 0xFF << 24;  //设置透明度
            for (int i = 0; i < imgTheHeight; i++) {
                for (int j = 0; j < imgTheWidth; j++) {
    //获得第i行第j个的像素点
                    int grey = imgThePixels[imgTheWidth * i + j];               
    int red = ((grey & 0x00FF0000) >> 16);  //获取红色灰度值
                    int green = ((grey & 0x0000FF00) >> 8); //获取绿色灰度值
                    int blue = (grey & 0x000000FF);         //获取蓝色灰度值
    //浮点算法获取灰度化色值
            grey = (int) ((float) red * 0.3 + (float) green * 0.59 + (float) blue * 0.11);          grey = alpha | (grey << 16) | (grey << 8) | grey; //添加透明度
            imgThePixels[imgTheWidth * i + j] = grey;   //更改像素色值
            }
    Bitmap result = 
    Bitmap.createBitmap(imgTheWidth, imgTheHeight, Config.RGB_565);
    result.setPixels(imgThePixels, 0, imgTheWidth, 0, 0, imgTheWidth, imgTheHeight);
            return result;
        }
    方法 setPixels(int[] pixels, int offset, int STiRe, int xxx, int yyy, int theWidth, int theHeight)为设置位图像素点灰度值,参数如下:参数 pixels 写入位图的颜色数组;参数 offset 写入的第一个颜色索引;参数 STiRe 行宽;参数 xxx写入位图的第一个像素的x坐标;参数 yyy写入位图的 第一个像素的y坐标;参数 theWidth一行的像素数量;参数theHeight写入的行数。
    

    图像去除噪点本文使用的算法是取区域像素中值的方法进行去噪

    这里写图片描述
    本文中采取的是3 乘以 3的表格区域取中值的方法,如上表所示,pix[0~8]是一个一维的像素值序列,中心点为pix[4]。这个算法最简便的方法是把这9个像素进行排序,然后取中间值,再存入pix[4]即中心点。实现代码如下:

    private static int getCenterValue(Bitmap img, int x, int y) {
            int[] pix = new int[9]; //该点以及周围8个点共9个点
            int h = img.getHeight() - 1; //获取高度像素值
            int w = img.getWidth() - 1; //获取宽度像素值
            if (x > 0 && y > 0) //如果点不再上边框和左边框,则存在pix[0]
                pix[0] = getGray(img.getPixel(x - 1, y - 1));
            if (y > 0)  //如果点不是上边框,则存在pix[1]
                pix[1] = getGray(img.getPixel(x, y - 1));
            if (x < h && y > 0) //如果点不是右边框和上边框,则存在pix[2]
                pix[2] = getGray(img.getPixel(x + 1, y - 1));
            if (x > 0) //如果点不是左边框,则存在pix[3]
                pix[3] = getGray(img.getPixel(x - 1, y));
            pix[4] = getGray(img.getPixel(x, y)); //pix[4]为要获取中值的点
            if (x < h) //如果没在右边框,则存在pix[5]
                pix[5] = getGray(img.getPixel(x + 1, y));
            if (x > 0 && y < w) //如果没在上边框和有边框,则存在pix[6]
                pix[6] = getGray(img.getPixel(x - 1, y + 1));
            if (y < w) //如果没在右边框,则存在pix[7]
                pix[7] = getGray(img.getPixel(x, y + 1));
            if (x < h && y < w) //如果没在右边框和下边框,则存在pix[8]
                pix[8] = getGray(img.getPixel(x + 1, y + 1));
            int max = 0, min = 255;
            for (int i = 0; i < pix.length; i++) {
                if (pix[i] > max)
                    max = pix[i];
                if (pix[i] < min)
                    min = pix[i];
            }
            int count = 0;
            int i = 0;
            for (i = 0; i < 9; i++) {
                if (pix[i] >= min)
                    count++;
                if (count == 5)
                    break;
            }
            return pix[i];
        }
    

    二值化处理

    大律法

    private static int getOtsuHresholdValue(int minOwnGrayValue, int maxOwnGrayValue) {
            int T = 0;
            double U = 0, U0 = 0, U1 = 0;
            double G = 0;
            for (int i = minOwnGrayValue; i <= maxOwnGrayValue; i++) {
                double s = 0, l = 0, cs = 0, cl = 0;
                for (int j = 0; j < imgTheHeight - 1; j++) {
                    for (int k = 0; k < imgTheWidth - 1; k++) {
                        int gray = imgThePixels[J  *  imgTheWidth + k];
                        if (gray < i) 
                            {s += gray;
                            cs++;}
                        if (gray > i) 
                            {l += gray;
                            cl++;}
                    }
                }
                U0 = s / cs;
                U1 = l / cl;
                U = (s + l) / (cs + cl);
                double g = (cs / (cs + cl)) * (U0 - U) * (U0 - U)
                        + (cl / (cl + cs)) * (U1 - U) * (U1 - U);
                if (g > G) {
                    T = i;
                    G = g;
                }
            }
            return T;   
    }
    

    迭代法

    首先需要获得中值:
    T = (maxGrayValue + minGrayValue) / 2;   公式(2-5)
    maxGrayValue指的是最大灰度值;minGrayValue指的是最小灰度值。
    将T视为阈值,大于T的为目标部分,小于T的为背景部分。再分别获取目标和背景的像素色值平均值T1和T2,获取新的阈值(T1+T2)/2;将新的阈值赋值给T重复获取新阈值,直到两个阈值一样而且连续的时候,将该阈值视为最终获取的阈值。实现代码如下:
    private static int getIterationHresholdValue(int minGrayValue,
                int maxGrayValue) {
            int T1;
            int T2 = (maxGrayValue + minGrayValue) / 2;
            do {
                T1 = T2;
                double s = 0, l = 0, cs = 0, cl = 0;
                for (int i = 0; i < imgTheHeight; i++) {
                    for (int j = 0; j < imgTheWidth; j++) {
                        int gray = imgThePixels[I * imgTheWidth + j];
                        if (gray < T1)
                            {s += gray;
                            cs++;}
                        if (gray > T1) 
                            {l += gray;
                            cl++;}
                        }
                }
                T2 = (int) (s / cs + l / cl) / 2;
            } while (T1 != T2);
            return T1;
    }
    

    反色处理

    nt pixel = 0;
            for (int i = 0; i < imgTheHeight; i++) {
                for (int j = 0; j < imgTheWidth; j++) {
                    pixel = 
    (imgThePixels[i*imgTheWidth + j] > T) ? (imgThePixels[i*imgTheWidth + j] = 0)
     : (imgThePixels[i*imgTheWidth + j] = 255);
                }
            }
    Bitmap result=
    Bitmap.createBitmap(imgTheWidth,imgTheHeight, Config.RGB_565);
    result.setPixels(imgThePixels, 0, imgTheWidth, 0, 0, imgTheWidth, imgTheHeight);
    

    Android端的一些实现

    获取联网状态

    public boolean isNetworkConnected(Context context) 
    { 
    if (context != null) 
    { 
    ConnectivityManager mConnectivityManager 
    = (ConnectivityManager) context 
    .getSystemService(Context.CONNECTIVITY_SERVICE); 
    NetworkInfo mNetworkInfo 
    = mConnectivityManager.getActiveNetworkInfo(); 
    if (mNetworkInfo != null) 
    return mNetworkInfo.isAvailable();
    } 
    return false; 
    }
    //返回true则正在联网状态中,返回false则处于断网的状态下,这时要提示用户连接网络。

    使用百度翻译

    public static final String BAIDU_LINK 
    = "http://openapi.baidu.com/public/2.0/bmt/translate?";
    //具体请自行百度

    总结

    本app完全走了捷径,用了前人已有的项目做了些修改并使用,因为对这些并没有透彻的研究,所以,嗯哼,只能这个效果了。以后有研究的话,再探讨。

    程序源码下载地址:本代码年代久远, 而且学生时代的代码水平很糟糕,就不分享了,大意就是用zxing来拿图识字。

    展开全文
  • javascript 繁体转换脚本

    万次阅读 2009-06-03 16:16:00
    1代表要转换为繁体 0 为转为简体 709974编号 function charPYStr(){ return 啊阿埃挨哎唉哀皑癌蔼矮艾碍爱隘鞍氨安俺按暗岸胺案肮昂盎凹敖熬翱袄傲奥懊澳芭捌扒叭吧笆八疤巴拔跋靶把耙坝霸罢爸白柏百摆佰败拜...

    调用方法:

     

    convert(1,709974); 1代表要转换为繁体字  0 为转为简体字  709974编号

     

    function charPYStr(){ 
    return '啊阿埃挨哎唉哀皑癌蔼矮艾碍爱隘鞍氨安俺按暗岸胺案肮昂盎凹敖熬翱袄傲奥懊澳芭捌扒叭吧笆八疤巴拔跋靶把耙坝霸罢爸白柏百摆佰败拜稗斑班搬扳般颁板版扮拌伴瓣半办绊邦帮梆榜膀绑棒磅蚌镑傍谤苞胞包褒剥薄雹保堡饱宝抱报暴豹鲍爆杯碑悲卑北辈背贝钡倍狈备惫焙被奔苯本笨崩绷甭泵蹦迸逼鼻比鄙笔彼碧蓖蔽毕毙毖币庇痹闭敝弊必辟壁臂避陛鞭边编贬扁便变卞辨辩辫遍标彪膘表鳖憋别瘪彬斌濒滨宾摈兵冰柄丙秉饼炳病并玻菠播拨钵波博勃搏铂箔伯帛舶脖膊渤泊驳捕卜哺补埠不布步簿部怖擦猜裁材才财睬踩采彩菜蔡餐参蚕残惭惨灿苍舱仓沧藏操糙槽曹草厕策侧册测层蹭插叉茬茶查碴搽察岔差诧拆柴豺搀掺蝉馋谗缠铲产阐颤昌猖场尝常长偿肠厂敞畅唱倡超抄钞朝嘲潮巢吵炒车扯撤掣彻澈郴臣辰尘晨忱沉陈趁衬撑称城橙成呈乘程惩澄诚承逞骋秤吃痴持匙池迟弛驰耻齿侈尺赤翅斥炽充冲虫崇宠抽酬畴踌稠愁筹仇绸瞅丑臭初出橱厨躇锄雏滁除楚础储矗搐触处揣川穿椽传船喘串疮窗幢床闯创吹炊捶锤垂春椿醇唇淳纯蠢戳绰疵茨磁雌辞慈瓷词此刺赐次聪葱囱匆从丛凑粗醋簇促蹿篡窜摧崔催脆瘁粹淬翠村存寸磋撮搓措挫错搭达答瘩打大呆歹傣戴带殆代贷袋待逮怠耽担丹单郸掸胆旦氮但惮淡诞弹蛋当挡党荡档刀捣蹈倒岛祷导到稻悼道盗德得的蹬灯登等瞪凳邓堤低滴迪敌笛狄涤翟嫡抵底地蒂第帝弟递缔颠掂滇碘点典靛垫电佃甸店惦奠淀殿碉叼雕凋刁掉吊钓调跌爹碟蝶迭谍叠丁盯叮钉顶鼎锭定订丢东冬董懂动栋侗恫冻洞兜抖斗陡豆逗痘都督毒犊独读堵睹赌杜镀肚度渡妒端短锻段断缎堆兑队对墩吨蹲敦顿囤钝盾遁掇哆多夺垛躲朵跺舵剁惰堕蛾峨鹅俄额讹娥恶厄扼遏鄂饿恩而儿耳尔饵洱二贰发罚筏伐乏阀法珐藩帆番翻樊矾钒繁凡烦反返范贩犯饭泛坊芳方肪房防妨仿访纺放菲非啡飞肥匪诽吠肺废沸费芬酚吩氛分纷坟焚汾粉奋份忿愤粪丰封枫蜂峰锋风疯烽逢冯缝讽奉凤佛否夫敷肤孵扶拂辐幅氟符伏俘服浮涪福袱弗甫抚辅俯釜斧脯腑府腐赴副覆赋复傅付阜父腹负富讣附妇缚咐噶嘎该改概钙盖溉干甘杆柑竿肝赶感秆敢赣冈刚钢缸肛纲岗港杠篙皋高膏羔糕搞镐稿告哥歌搁戈鸽胳疙割革葛格蛤阁隔铬个各给根跟耕更庚羹埂耿梗工攻功恭龚供躬公宫弓巩汞拱贡共钩勾沟苟狗垢构购够辜菇咕箍估沽孤姑鼓古蛊骨谷股故顾固雇刮瓜剐寡挂褂乖拐怪棺关官冠观管馆罐惯灌贯光广逛瑰规圭硅归龟闺轨鬼诡癸桂柜跪贵刽辊滚棍锅郭国果裹过哈骸孩海氦亥害骇酣憨邯韩含涵寒函喊罕翰撼捍旱憾悍焊汗汉夯杭航壕嚎豪毫郝好耗号浩呵喝荷菏核禾和何合盒貉阂河涸赫褐鹤贺嘿黑痕很狠恨哼亨横衡恒轰哄烘虹鸿洪宏弘红喉侯猴吼厚候后呼乎忽瑚壶葫胡蝴狐糊湖弧虎唬护互沪户花哗华猾滑画划化话槐徊怀淮坏欢环桓还缓换患唤痪豢焕涣宦幻荒慌黄磺蝗簧皇凰惶煌晃幌恍谎灰挥辉徽恢蛔回毁悔慧卉惠晦贿秽会烩汇讳诲绘荤昏婚魂浑混豁活伙火获或惑霍货祸击圾基机畸稽积箕肌饥迹激讥鸡姬绩缉吉极棘辑籍集及急疾汲即嫉级挤几脊己蓟技冀季伎祭剂悸济寄寂计记既忌际继纪嘉枷夹佳家加荚颊贾甲钾假稼价架驾嫁歼监坚尖笺间煎兼肩艰奸缄茧检柬碱硷拣捡简俭剪减荐槛鉴践贱见键箭件健舰剑饯渐溅涧建僵姜将浆江疆蒋桨奖讲匠酱降蕉椒礁焦胶交郊浇骄娇嚼搅铰矫侥脚狡角饺缴绞剿教酵轿较叫窖揭接皆秸街阶截劫节茎睛晶鲸京惊精粳经井警景颈静境敬镜径痉靖竟竞净炯窘揪究纠玖韭久灸九酒厩救旧臼舅咎就疚鞠拘狙疽居驹菊局咀矩举沮聚拒据巨具距踞锯俱句惧炬剧捐鹃娟倦眷卷绢撅攫抉掘倔爵桔杰捷睫竭洁结解姐戒藉芥界借介疥诫届巾筋斤金今津襟紧锦仅谨进靳晋禁近烬浸尽劲荆兢觉决诀绝均菌钧军君峻俊竣浚郡骏喀咖卡咯开揩楷凯慨刊堪勘坎砍看康慷糠扛抗亢炕考拷烤靠坷苛柯棵磕颗科壳咳可渴克刻客课肯啃垦恳坑吭空恐孔控抠口扣寇枯哭窟苦酷库裤夸垮挎跨胯块筷侩快宽款匡筐狂框矿眶旷况亏盔岿窥葵奎魁傀馈愧溃坤昆捆困括扩廓阔垃拉喇蜡腊辣啦莱来赖蓝婪栏拦篮阑兰澜谰揽览懒缆烂滥琅榔狼廊郎朗浪捞劳牢老佬姥酪烙涝勒乐雷镭蕾磊累儡垒擂肋类泪棱楞冷厘梨犁黎篱狸离漓理李里鲤礼莉荔吏栗丽厉励砾历利傈例俐痢立粒沥隶力璃哩俩联莲连镰廉怜涟帘敛脸链恋炼练粮凉梁粱良两辆量晾亮谅撩聊僚疗燎寥辽潦了撂镣廖料列裂烈劣猎琳林磷霖临邻鳞淋凛赁吝拎玲菱零龄铃伶羚凌灵陵岭领另令溜琉榴硫馏留刘瘤流柳六龙聋咙笼窿隆垄拢陇楼娄搂篓漏陋芦卢颅庐炉掳卤虏鲁麓碌露路赂鹿潞禄录陆戮驴吕铝侣旅履屡缕虑氯律率滤绿峦挛孪滦卵乱掠略抡轮伦仑沦纶论萝螺罗逻锣箩骡裸落洛骆络妈麻玛码蚂马骂嘛吗埋买麦卖迈脉瞒馒蛮满蔓曼慢漫谩芒茫盲氓忙莽猫茅锚毛矛铆卯茂冒帽貌贸么玫枚梅酶霉煤没眉媒镁每美昧寐妹媚门闷们萌蒙檬盟锰猛梦孟眯醚靡糜迷谜弥米秘觅泌蜜密幂棉眠绵冕免勉娩缅面苗描瞄藐秒渺庙妙蔑灭民抿皿敏悯闽明螟鸣铭名命谬摸摹蘑模膜磨摩魔抹末莫墨默沫漠寞陌谋牟某拇牡亩姆母墓暮幕募慕木目睦牧穆拿哪呐钠那娜纳氖乃奶耐奈南男难囊挠脑恼闹淖呢馁内嫩能妮霓倪泥尼拟你匿腻逆溺蔫拈年碾撵捻念娘酿鸟尿捏聂孽啮镊镍涅您柠狞凝宁拧泞牛扭钮纽脓浓农弄奴努怒女暖虐疟挪懦糯诺哦欧鸥殴藕呕偶沤啪趴爬帕怕琶拍排牌徘湃派攀潘盘磐盼畔判叛乓庞旁耪胖抛咆刨炮袍跑泡呸胚培裴赔陪配佩沛喷盆砰抨烹澎彭蓬棚硼篷膨朋鹏捧碰坯砒霹批披劈琵毗啤脾疲皮匹痞僻屁譬篇偏片骗飘漂瓢票撇瞥拼频贫品聘乒坪苹萍平凭瓶评屏坡泼颇婆破魄迫粕剖扑铺仆莆葡菩蒲埔朴圃普浦谱曝瀑期欺栖戚妻七凄漆柒沏其棋奇歧畦崎脐齐旗祈祁骑起岂乞企启契砌器气迄弃汽泣讫掐洽牵扦钎铅千迁签仟谦乾黔钱钳前潜遣浅谴堑嵌欠歉枪呛腔羌墙蔷强抢橇锹敲悄桥瞧乔侨巧鞘撬翘峭俏窍切茄且怯窃钦侵亲秦琴勤芹擒禽寝沁青轻氢倾卿清擎晴氰情顷请庆琼穷秋丘邱球求囚酋泅趋区蛆曲躯屈驱渠取娶龋趣去圈颧权醛泉全痊拳犬券劝缺炔瘸却鹊榷确雀裙群然燃冉染瓤壤攘嚷让饶扰绕惹热壬仁人忍韧任认刃妊纫扔仍日戎茸蓉荣融熔溶容绒冗揉柔肉茹蠕儒孺如辱乳汝入褥软阮蕊瑞锐闰润若弱撒洒萨腮鳃塞赛三叁伞散桑嗓丧搔骚扫嫂瑟色涩森僧莎砂杀刹沙纱傻啥煞筛晒珊苫杉山删煽衫闪陕擅赡膳善汕扇缮墒伤商赏晌上尚裳梢捎稍烧芍勺韶少哨邵绍奢赊蛇舌舍赦摄射慑涉社设砷申呻伸身深娠绅神沈审婶甚肾慎渗声生甥牲升绳省盛剩胜圣师失狮施湿诗尸虱十石拾时什食蚀实识史矢使屎驶始式示士世柿事拭誓逝势是嗜噬适仕侍释饰氏市恃室视试收手首守寿授售受瘦兽蔬枢梳殊抒输叔舒淑疏书赎孰熟薯暑曙署蜀黍鼠属术述树束戍竖墅庶数漱恕刷耍摔衰甩帅栓拴霜双爽谁水睡税吮瞬顺舜说硕朔烁斯撕嘶思私司丝死肆寺嗣四伺似饲巳松耸怂颂送宋讼诵搜艘擞嗽苏酥俗素速粟僳塑溯宿诉肃酸蒜算虽隋随绥髓碎岁穗遂隧祟孙损笋蓑梭唆缩琐索锁所塌他它她塔獭挞蹋踏胎苔抬台泰酞太态汰坍摊贪瘫滩坛檀痰潭谭谈坦毯袒碳探叹炭汤塘搪堂棠膛唐糖倘躺淌趟烫掏涛滔绦萄桃逃淘陶讨套特藤腾疼誊梯剔踢锑提题蹄啼体替嚏惕涕剃屉天添填田甜恬舔腆挑条迢眺跳贴铁帖厅听烃汀廷停亭庭挺艇通桐酮瞳同铜彤童桶捅筒统痛偷投头透凸秃突图徒途涂屠土吐兔湍团推颓腿蜕褪退吞屯臀拖托脱鸵陀驮驼椭妥拓唾挖哇蛙洼娃瓦袜歪外豌弯湾玩顽丸烷完碗挽晚皖惋宛婉万腕汪王亡枉网往旺望忘妄威巍微危韦违桅围唯惟为潍维苇萎委伟伪尾纬未蔚味畏胃喂魏位渭谓尉慰卫瘟温蚊文闻纹吻稳紊问嗡翁瓮挝蜗涡窝我斡卧握沃巫呜钨乌污诬屋无芜梧吾吴毋武五捂午舞伍侮坞戊雾晤物勿务悟误昔熙析西硒矽晰嘻吸锡牺稀息希悉膝夕惜熄烯溪汐犀檄袭席习媳喜铣洗系隙戏细瞎虾匣霞辖暇峡侠狭下厦夏吓掀锨先仙鲜纤咸贤衔舷闲涎弦嫌显险现献县腺馅羡宪陷限线相厢镶香箱襄湘乡翔祥详想响享项巷橡像向象萧硝霄削哮嚣销消宵淆晓小孝校肖啸笑效楔些歇蝎鞋协挟携邪斜胁谐写械卸蟹懈泄泻谢屑薪芯锌欣辛新忻心信衅星腥猩惺兴刑型形邢行醒幸杏性姓兄凶胸匈汹雄熊休修羞朽嗅锈秀袖绣墟戌需虚嘘须徐许蓄酗叙旭序畜恤絮婿绪续轩喧宣悬旋玄选癣眩绚靴薛学穴雪血勋熏循旬询寻驯巡殉汛训讯逊迅压押鸦鸭呀丫芽牙蚜崖衙涯雅哑亚讶焉咽阉烟淹盐严研蜒岩延言颜阎炎沿奄掩眼衍演艳堰燕厌砚雁唁彦焰宴谚验殃央鸯秧杨扬佯疡羊洋阳氧仰痒养样漾邀腰妖瑶摇尧遥窑谣姚咬舀药要耀椰噎耶爷野冶也页掖业叶曳腋夜液一壹医揖铱依伊衣颐夷遗移仪胰疑沂宜姨彝椅蚁倚已乙矣以艺抑易邑屹亿役臆逸肄疫亦裔意毅忆义益溢诣议谊译异翼翌绎茵荫因殷音阴姻吟银淫寅饮尹引隐印英樱婴鹰应缨莹萤营荧蝇迎赢盈影颖硬映哟拥佣臃痈庸雍踊蛹咏泳涌永恿勇用幽优悠忧尤由邮铀犹油游酉有友右佑釉诱又幼迂淤于盂榆虞愚舆余俞逾鱼愉渝渔隅予娱雨与屿禹宇语羽玉域芋郁吁遇喻峪御愈欲狱育誉浴寓裕预豫驭鸳渊冤元垣袁原援辕园员圆猿源缘远苑愿怨院曰约越跃钥岳粤月悦阅耘云郧匀陨允运蕴酝晕韵孕匝砸杂栽哉灾宰载再在咱攒暂赞赃脏葬遭糟凿藻枣早澡蚤躁噪造皂灶燥责择则泽贼怎增憎曾赠扎喳渣札轧铡闸眨栅榨咋乍炸诈摘斋宅窄债寨瞻毡詹粘沾盏斩辗崭展蘸栈占战站湛绽樟章彰漳张掌涨杖丈帐账仗胀瘴障招昭找沼赵照罩兆肇召遮折哲蛰辙者锗蔗这浙珍斟真甄砧臻贞针侦枕疹诊震振镇阵蒸挣睁征狰争怔整拯正政帧症郑证芝枝支吱蜘知肢脂汁之织职直植殖执值侄址指止趾只旨纸志挚掷至致置帜峙制智秩稚质炙痔滞治窒中盅忠钟衷终种肿重仲众舟周州洲诌粥轴肘帚咒皱宙昼骤珠株蛛朱猪诸诛逐竹烛煮拄瞩嘱主著柱助蛀贮铸筑住注祝驻抓爪拽专砖转撰赚篆桩庄装妆撞壮状椎锥追赘坠缀谆准捉拙卓桌琢茁酌啄着灼浊兹咨资姿滋淄孜紫仔籽滓子自渍字鬃棕踪宗综总纵邹走奏揍租足卒族祖诅阻组钻纂嘴醉最罪尊遵昨左佐柞做作坐座'; 
    } 
    
    function ftPYStr(){ 
    return '啊阿埃挨哎唉哀皚癌藹矮艾礙愛隘鞍氨安俺按暗岸胺案肮昂盎凹敖熬翺襖傲奧懊澳芭捌扒叭吧笆八疤巴拔跋靶把耙壩霸罷爸白柏百擺佰敗拜稗斑班搬扳般頒板版扮拌伴瓣半辦絆邦幫梆榜膀綁棒磅蚌鎊傍謗苞胞包褒剝薄雹保堡飽寶抱報暴豹鮑爆杯碑悲卑北輩背貝鋇倍狽備憊焙被奔苯本笨崩繃甭泵蹦迸逼鼻比鄙筆彼碧蓖蔽畢斃毖幣庇痹閉敝弊必辟壁臂避陛鞭邊編貶扁便變卞辨辯辮遍標彪膘表鼈憋別癟彬斌瀕濱賓擯兵冰柄丙秉餅炳病並玻菠播撥缽波博勃搏鉑箔伯帛舶脖膊渤泊駁捕蔔哺補埠不布步簿部怖擦猜裁材才財睬踩采彩菜蔡餐參蠶殘慚慘燦蒼艙倉滄藏操糙槽曹草廁策側冊測層蹭插叉茬茶查碴搽察岔差詫拆柴豺攙摻蟬饞讒纏鏟産闡顫昌猖場嘗常長償腸廠敞暢唱倡超抄鈔朝嘲潮巢吵炒車扯撤掣徹澈郴臣辰塵晨忱沈陳趁襯撐稱城橙成呈乘程懲澄誠承逞騁秤吃癡持匙池遲弛馳恥齒侈尺赤翅斥熾充沖蟲崇寵抽酬疇躊稠愁籌仇綢瞅醜臭初出櫥廚躇鋤雛滁除楚礎儲矗搐觸處揣川穿椽傳船喘串瘡窗幢床闖創吹炊捶錘垂春椿醇唇淳純蠢戳綽疵茨磁雌辭慈瓷詞此刺賜次聰蔥囪匆從叢湊粗醋簇促躥篡竄摧崔催脆瘁粹淬翠村存寸磋撮搓措挫錯搭達答瘩打大呆歹傣戴帶殆代貸袋待逮怠耽擔丹單鄲撣膽旦氮但憚淡誕彈蛋當擋黨蕩檔刀搗蹈倒島禱導到稻悼道盜德得的蹬燈登等瞪凳鄧堤低滴迪敵笛狄滌翟嫡抵底地蒂第帝弟遞締顛掂滇碘點典靛墊電佃甸店惦奠澱殿碉叼雕凋刁掉吊釣調跌爹碟蝶叠諜疊丁盯叮釘頂鼎錠定訂丟東冬董懂動棟侗恫凍洞兜抖鬥陡豆逗痘都督毒犢獨讀堵睹賭杜鍍肚度渡妒端短鍛段斷緞堆兌隊對墩噸蹲敦頓囤鈍盾遁掇哆多奪垛躲朵跺舵剁惰墮蛾峨鵝俄額訛娥惡厄扼遏鄂餓恩而兒耳爾餌洱二貳發罰筏伐乏閥法琺藩帆番翻樊礬釩繁凡煩反返範販犯飯泛坊芳方肪房防妨仿訪紡放菲非啡飛肥匪誹吠肺廢沸費芬酚吩氛分紛墳焚汾粉奮份忿憤糞豐封楓蜂峰鋒風瘋烽逢馮縫諷奉鳳佛否夫敷膚孵扶拂輻幅氟符伏俘服浮涪福袱弗甫撫輔俯釜斧脯腑府腐赴副覆賦複傅付阜父腹負富訃附婦縛咐噶嘎該改概鈣蓋溉幹甘杆柑竿肝趕感稈敢贛岡剛鋼缸肛綱崗港杠篙臯高膏羔糕搞鎬稿告哥歌擱戈鴿胳疙割革葛格蛤閣隔鉻個各給根跟耕更庚羹埂耿梗工攻功恭龔供躬公宮弓鞏汞拱貢共鈎勾溝苟狗垢構購夠辜菇咕箍估沽孤姑鼓古蠱骨谷股故顧固雇刮瓜剮寡挂褂乖拐怪棺關官冠觀管館罐慣灌貫光廣逛瑰規圭矽歸龜閨軌鬼詭癸桂櫃跪貴劊輥滾棍鍋郭國果裹過哈骸孩海氦亥害駭酣憨邯韓含涵寒函喊罕翰撼捍旱憾悍焊汗漢夯杭航壕嚎豪毫郝好耗號浩呵喝荷菏核禾和何合盒貉閡河涸赫褐鶴賀嘿黑痕很狠恨哼亨橫衡恒轟哄烘虹鴻洪宏弘紅喉侯猴吼厚候後呼乎忽瑚壺葫胡蝴狐糊湖弧虎唬護互滬戶花嘩華猾滑畫劃化話槐徊懷淮壞歡環桓還緩換患喚瘓豢煥渙宦幻荒慌黃磺蝗簧皇凰惶煌晃幌恍謊灰揮輝徽恢蛔回毀悔慧卉惠晦賄穢會燴彙諱誨繪葷昏婚魂渾混豁活夥火獲或惑霍貨禍擊圾基機畸稽積箕肌饑迹激譏雞姬績緝吉極棘輯籍集及急疾汲即嫉級擠幾脊己薊技冀季伎祭劑悸濟寄寂計記既忌際繼紀嘉枷夾佳家加莢頰賈甲鉀假稼價架駕嫁殲監堅尖箋間煎兼肩艱奸緘繭檢柬堿鹼揀撿簡儉剪減薦檻鑒踐賤見鍵箭件健艦劍餞漸濺澗建僵姜將漿江疆蔣槳獎講匠醬降蕉椒礁焦膠交郊澆驕嬌嚼攪鉸矯僥腳狡角餃繳絞剿教酵轎較叫窖揭接皆稭街階截劫節莖睛晶鯨京驚精粳經井警景頸靜境敬鏡徑痙靖竟競淨炯窘揪究糾玖韭久灸九酒廄救舊臼舅咎就疚鞠拘狙疽居駒菊局咀矩舉沮聚拒據巨具距踞鋸俱句懼炬劇捐鵑娟倦眷卷絹撅攫抉掘倔爵桔傑捷睫竭潔結解姐戒藉芥界借介疥誡屆巾筋斤金今津襟緊錦僅謹進靳晉禁近燼浸盡勁荊兢覺決訣絕均菌鈞軍君峻俊竣浚郡駿喀咖卡咯開揩楷凱慨刊堪勘坎砍看康慷糠扛抗亢炕考拷烤靠坷苛柯棵磕顆科殼咳可渴克刻客課肯啃墾懇坑吭空恐孔控摳口扣寇枯哭窟苦酷庫褲誇垮挎跨胯塊筷儈快寬款匡筐狂框礦眶曠況虧盔巋窺葵奎魁傀饋愧潰坤昆捆困括擴廓闊垃拉喇蠟臘辣啦萊來賴藍婪欄攔籃闌蘭瀾讕攬覽懶纜爛濫琅榔狼廊郎朗浪撈勞牢老佬姥酪烙澇勒樂雷鐳蕾磊累儡壘擂肋類淚棱楞冷厘梨犁黎籬狸離漓理李裏鯉禮莉荔吏栗麗厲勵礫曆利傈例俐痢立粒瀝隸力璃哩倆聯蓮連鐮廉憐漣簾斂臉鏈戀煉練糧涼梁粱良兩輛量晾亮諒撩聊僚療燎寥遼潦了撂鐐廖料列裂烈劣獵琳林磷霖臨鄰鱗淋凜賃吝拎玲菱零齡鈴伶羚淩靈陵嶺領另令溜琉榴硫餾留劉瘤流柳六龍聾嚨籠窿隆壟攏隴樓婁摟簍漏陋蘆盧顱廬爐擄鹵虜魯麓碌露路賂鹿潞祿錄陸戮驢呂鋁侶旅履屢縷慮氯律率濾綠巒攣孿灤卵亂掠略掄輪倫侖淪綸論蘿螺羅邏鑼籮騾裸落洛駱絡媽麻瑪碼螞馬罵嘛嗎埋買麥賣邁脈瞞饅蠻滿蔓曼慢漫謾芒茫盲氓忙莽貓茅錨毛矛鉚卯茂冒帽貌貿麽玫枚梅酶黴煤沒眉媒鎂每美昧寐妹媚門悶們萌蒙檬盟錳猛夢孟眯醚靡糜迷謎彌米秘覓泌蜜密冪棉眠綿冕免勉娩緬面苗描瞄藐秒渺廟妙蔑滅民抿皿敏憫閩明螟鳴銘名命謬摸摹蘑模膜磨摩魔抹末莫墨默沫漠寞陌謀牟某拇牡畝姆母墓暮幕募慕木目睦牧穆拿哪呐鈉那娜納氖乃奶耐奈南男難囊撓腦惱鬧淖呢餒內嫩能妮霓倪泥尼擬你匿膩逆溺蔫拈年碾攆撚念娘釀鳥尿捏聶孽齧鑷鎳涅您檸獰凝甯擰濘牛扭鈕紐膿濃農弄奴努怒女暖虐瘧挪懦糯諾哦歐鷗毆藕嘔偶漚啪趴爬帕怕琶拍排牌徘湃派攀潘盤磐盼畔判叛乓龐旁耪胖抛咆刨炮袍跑泡呸胚培裴賠陪配佩沛噴盆砰抨烹澎彭蓬棚硼篷膨朋鵬捧碰坯砒霹批披劈琵毗啤脾疲皮匹痞僻屁譬篇偏片騙飄漂瓢票撇瞥拼頻貧品聘乒坪蘋萍平憑瓶評屏坡潑頗婆破魄迫粕剖撲鋪仆莆葡菩蒲埔樸圃普浦譜曝瀑期欺棲戚妻七淒漆柒沏其棋奇歧畦崎臍齊旗祈祁騎起豈乞企啓契砌器氣迄棄汽泣訖掐洽牽扡釺鉛千遷簽仟謙乾黔錢鉗前潛遣淺譴塹嵌欠歉槍嗆腔羌牆薔強搶橇鍬敲悄橋瞧喬僑巧鞘撬翹峭俏竅切茄且怯竊欽侵親秦琴勤芹擒禽寢沁青輕氫傾卿清擎晴氰情頃請慶瓊窮秋丘邱球求囚酋泅趨區蛆曲軀屈驅渠取娶齲趣去圈顴權醛泉全痊拳犬券勸缺炔瘸卻鵲榷確雀裙群然燃冉染瓤壤攘嚷讓饒擾繞惹熱壬仁人忍韌任認刃妊紉扔仍日戎茸蓉榮融熔溶容絨冗揉柔肉茹蠕儒孺如辱乳汝入褥軟阮蕊瑞銳閏潤若弱撒灑薩腮鰓塞賽三三傘散桑嗓喪搔騷掃嫂瑟色澀森僧莎砂殺刹沙紗傻啥煞篩曬珊苫杉山刪煽衫閃陝擅贍膳善汕扇繕墒傷商賞晌上尚裳梢捎稍燒芍勺韶少哨邵紹奢賒蛇舌舍赦攝射懾涉社設砷申呻伸身深娠紳神沈審嬸甚腎慎滲聲生甥牲升繩省盛剩勝聖師失獅施濕詩屍虱十石拾時什食蝕實識史矢使屎駛始式示士世柿事拭誓逝勢是嗜噬適仕侍釋飾氏市恃室視試收手首守壽授售受瘦獸蔬樞梳殊抒輸叔舒淑疏書贖孰熟薯暑曙署蜀黍鼠屬術述樹束戍豎墅庶數漱恕刷耍摔衰甩帥栓拴霜雙爽誰水睡稅吮瞬順舜說碩朔爍斯撕嘶思私司絲死肆寺嗣四伺似飼巳松聳慫頌送宋訟誦搜艘擻嗽蘇酥俗素速粟僳塑溯宿訴肅酸蒜算雖隋隨綏髓碎歲穗遂隧祟孫損筍蓑梭唆縮瑣索鎖所塌他它她塔獺撻蹋踏胎苔擡台泰酞太態汰坍攤貪癱灘壇檀痰潭譚談坦毯袒碳探歎炭湯塘搪堂棠膛唐糖倘躺淌趟燙掏濤滔縧萄桃逃淘陶討套特藤騰疼謄梯剔踢銻提題蹄啼體替嚏惕涕剃屜天添填田甜恬舔腆挑條迢眺跳貼鐵帖廳聽烴汀廷停亭庭挺艇通桐酮瞳同銅彤童桶捅筒統痛偷投頭透凸禿突圖徒途塗屠土吐兔湍團推頹腿蛻褪退吞屯臀拖托脫鴕陀馱駝橢妥拓唾挖哇蛙窪娃瓦襪歪外豌彎灣玩頑丸烷完碗挽晚皖惋宛婉萬腕汪王亡枉網往旺望忘妄威巍微危韋違桅圍唯惟爲濰維葦萎委偉僞尾緯未蔚味畏胃喂魏位渭謂尉慰衛瘟溫蚊文聞紋吻穩紊問嗡翁甕撾蝸渦窩我斡臥握沃巫嗚鎢烏汙誣屋無蕪梧吾吳毋武五捂午舞伍侮塢戊霧晤物勿務悟誤昔熙析西硒矽晰嘻吸錫犧稀息希悉膝夕惜熄烯溪汐犀檄襲席習媳喜銑洗係隙戲細瞎蝦匣霞轄暇峽俠狹下廈夏嚇掀鍁先仙鮮纖鹹賢銜舷閑涎弦嫌顯險現獻縣腺餡羨憲陷限線相廂鑲香箱襄湘鄉翔祥詳想響享項巷橡像向象蕭硝霄削哮囂銷消宵淆曉小孝校肖嘯笑效楔些歇蠍鞋協挾攜邪斜脅諧寫械卸蟹懈泄瀉謝屑薪芯鋅欣辛新忻心信釁星腥猩惺興刑型形邢行醒幸杏性姓兄凶胸匈洶雄熊休修羞朽嗅鏽秀袖繡墟戌需虛噓須徐許蓄酗敘旭序畜恤絮婿緒續軒喧宣懸旋玄選癬眩絢靴薛學穴雪血勳熏循旬詢尋馴巡殉汛訓訊遜迅壓押鴉鴨呀丫芽牙蚜崖衙涯雅啞亞訝焉咽閹煙淹鹽嚴研蜒岩延言顔閻炎沿奄掩眼衍演豔堰燕厭硯雁唁彥焰宴諺驗殃央鴦秧楊揚佯瘍羊洋陽氧仰癢養樣漾邀腰妖瑤搖堯遙窯謠姚咬舀藥要耀椰噎耶爺野冶也頁掖業葉曳腋夜液一壹醫揖銥依伊衣頤夷遺移儀胰疑沂宜姨彜椅蟻倚已乙矣以藝抑易邑屹億役臆逸肄疫亦裔意毅憶義益溢詣議誼譯異翼翌繹茵蔭因殷音陰姻吟銀淫寅飲尹引隱印英櫻嬰鷹應纓瑩螢營熒蠅迎贏盈影穎硬映喲擁傭臃癰庸雍踴蛹詠泳湧永恿勇用幽優悠憂尤由郵鈾猶油遊酉有友右佑釉誘又幼迂淤於盂榆虞愚輿余俞逾魚愉渝漁隅予娛雨與嶼禹宇語羽玉域芋郁籲遇喻峪禦愈欲獄育譽浴寓裕預豫馭鴛淵冤元垣袁原援轅園員圓猿源緣遠苑願怨院曰約越躍鑰嶽粵月悅閱耘雲鄖勻隕允運蘊醞暈韻孕匝砸雜栽哉災宰載再在咱攢暫贊贓髒葬遭糟鑿藻棗早澡蚤躁噪造皂竈燥責擇則澤賊怎增憎曾贈紮喳渣劄軋鍘閘眨柵榨咋乍炸詐摘齋宅窄債寨瞻氈詹粘沾盞斬輾嶄展蘸棧占戰站湛綻樟章彰漳張掌漲杖丈帳賬仗脹瘴障招昭找沼趙照罩兆肇召遮折哲蟄轍者鍺蔗這浙珍斟真甄砧臻貞針偵枕疹診震振鎮陣蒸掙睜征猙爭怔整拯正政幀症鄭證芝枝支吱蜘知肢脂汁之織職直植殖執值侄址指止趾只旨紙志摯擲至致置幟峙制智秩稚質炙痔滯治窒中盅忠鍾衷終種腫重仲衆舟周州洲謅粥軸肘帚咒皺宙晝驟珠株蛛朱豬諸誅逐竹燭煮拄矚囑主著柱助蛀貯鑄築住注祝駐抓爪拽專磚轉撰賺篆樁莊裝妝撞壯狀椎錐追贅墜綴諄準捉拙卓桌琢茁酌啄著灼濁茲咨資姿滋淄孜紫仔籽滓子自漬字鬃棕蹤宗綜總縱鄒走奏揍租足卒族祖詛阻組鑽纂嘴醉最罪尊遵昨左佐柞做作坐座'; 
    } 
    
    function traditionalized(cc){ 
    var str=''; 
    for(var i=0;i<cc.length;i++){ 
    if(charPYStr().indexOf(cc.charAt(i))!=-1) 
    str+=ftPYStr().charAt(charPYStr().indexOf(cc.charAt(i))); 
    else 
    str+=cc.charAt(i); 
    } 
    return str; 
    } 
    
    function simplized(cc){ 
    var str=''; 
    for(var i=0;i<cc.length;i++){ 
    if(ftPYStr().indexOf(cc.charAt(i))!=-1) 
    str+=charPYStr().charAt(ftPYStr().indexOf(cc.charAt(i))); 
    else 
    str+=cc.charAt(i); 
    } 
    return str; 
    } 
    
    function convert(zcs, wpid){
    var tpid="tpid"+wpid;
    var spid="spid"+wpid;
    if(zcs==0)
    eval('document.all.'+tpid+'.innerHTML=simplized(document.all.'+spid+'.outerHTML)');
    else
    eval('document.all.'+tpid+'.innerHTML=traditionalized(document.all.'+spid+'.outerHTML)');
    }

    手机扫描下方二维码,关注官方微信。


    展开全文
  • 游戏的流程是这样的:在界面上生成5个数1~5并显示在随机的位置上,点击第一个数字,其他数字会显示成白块数字消失,玩家可以通过记住数字的显示的位置点击按顺序消除白块,直到白块消除完,游戏成功。 效果图如下...

    Cocos2d-x-Lua 开发简单的小游戏(记数字踩白块)


    本篇博客来给大家介绍如何使用Lua这门语言来开发一个简单的小游戏—记数字踩白块。

    游戏的流程是这样的:在界面上生成5个数1~5字并显示在随机的位置上,点击第一个数字,其他数字会显示成白块数字消失,玩家可以通过记住数字的显示的位置点击按顺序消除白块,直到白块消除完,游戏成功。

    效果图如下:


    先说明一下笔者的开发环境:

    • Xcode 5.1(Mac系统下的苹果开发工具)
    • Cocos2d-x 3.1.1(Cocos2d-x游戏引擎)
    • LDT(Lua集成开发环境)
    首先你得创建一个Cocos2d-x项目,里面会多个平台代码,具体创建方法麻烦读者参考笔者前面所写的文章,如有疑问可以直接留言交流。


    来看看我们项目结构:


    》》AppDelegate.cpp
    #include "AppDelegate.h"
    #include "CCLuaEngine.h"
    #include "SimpleAudioEngine.h"
    #include "cocos2d.h"
    
    using namespace CocosDenshion;
    
    USING_NS_CC;
    using namespace std;
    
    AppDelegate::AppDelegate()
    {
    }
    
    AppDelegate::~AppDelegate()
    {
        SimpleAudioEngine::end();
    }
    
    bool AppDelegate::applicationDidFinishLaunching()
    {
        // initialize director
        auto director = Director::getInstance();
    	auto glview = director->getOpenGLView();
    	if(!glview) {
            // 创建可视区域,位置(0,0)宽:900,高:640
    		glview = GLView::createWithRect("记数字踩白块", Rect(0,0,900,640));
    		director->setOpenGLView(glview);
    	}
        
        // 设置设计分辨率
        glview->setDesignResolutionSize(800, 480, ResolutionPolicy::SHOW_ALL);
    
        // turn on display FPS
        // 打开显示的FPS
        director->setDisplayStats(true);
    
        // set FPS. the default value is 1.0/60 if you don't call this
        director->setAnimationInterval(1.0 / 60);
    
    
        auto engine = LuaEngine::getInstance();
        ScriptEngineManager::getInstance()->setScriptEngine(engine);
        // 执行src目录下的main.lua脚本文件
        if (engine->executeScriptFile("src/main.lua")) {
            return false;
        }
    
        return true;
    }
    
    // This function will be called when the app is inactive. When comes a phone call,it's be invoked too
    void AppDelegate::applicationDidEnterBackground()
    {
        Director::getInstance()->stopAnimation();
    
        SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
    }
    
    // this function will be called when the app is active again
    void AppDelegate::applicationWillEnterForeground()
    {
        Director::getInstance()->startAnimation();
    
        SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
    }


    我们主要在Lua文件中实现我们的逻辑,如何开始呢,首先我们要想象一个场景6*10的方格,一共60个方格,每个方格一个卡片,我们要做的是如何在这60个方格里放入我们的卡片,并且要随机放上去的。

    我们先定义卡片类》》card.lua
    --[[
    卡片
    card.lua
    ]]--
    
    
    function card(num)
      -- 创建一个精灵,代表一张卡片
      local self = cc.Sprite:create()
      local txt,bg -- 卡片文本和背景
    
      --初始化方法
      local function init()
        self.num = num
        --设置内容尺寸
        self:setContentSize( cc.size( 80, 80 ) )
        --设置锚点
        self:setAnchorPoint(  cc.p( 0, 0 ) )
    
        --设置显示数字的文本
        txt = cc.Label:create()
        txt:setString( num )
        txt:setSystemFontSize( 50 )
        txt:setSystemFontName( "Courier" )
        --设置文本显示的位置,这里是中间
        txt:setPosition( cc.p( self:getContentSize().width / 2,  self:getContentSize().height / 2 ) )
        --添加到表
        self:addChild(txt)
    
        --创建一个精灵,代表背景
        bg = cc.Sprite:create()
        --颜色块
        bg:setTextureRect( cc.rect( 0, 0, 80, 80 ) )
        --默认为白色,这里设置为白色
        bg:setColor( cc.c3b( 255, 255, 255 ) )
        --bg:setPosition( cc.p(0, 0))
        --设置锚点
        bg:setAnchorPoint(  cc.p( 0, 0 ) )
        self:addChild(bg)
    
        --显示文本
        self:showTxt()
      end
    
      --定义显示文本的方法
      self.showTxt = function()
        txt:setVisible(true)
        bg:setVisible(false)
      end
    
      --定义显示背景的方法
      self.showBg = function()
        txt:setVisible(false)
        bg:setVisible(true)
      end
      init()
    
      return self
    end

    从卡片类我们可以知道,我们需要传入一个数字,然后对卡片类进行初始化,显示相应的数字,我们的卡片是一个Sprite(我们所说的精灵),我们要往Sprite添加数字(用Label来显示),还要添加我们的背景(同样也是一个Sprite)

    卡片类定义好之后,我们就要实现我们想要的效果了,定义我们的入口
    》》》main.lua
    --[[
    
    记数字踩白块小游戏
    
    2014/6/22
    main.lua
    
    ]]
    -- 引入card.lua文件
    require( "src/card" )
    
    --主方法
    function Main()
      -- 创建一个场景
      local self = cc.Scene:create()
    
      -- 声明一个层
      local layer
      local allPoints -- 存储所有点
      local allCards = {} -- 存储所有卡片
      local currentNum -- 当前数字
    
      -- 生成可用点
      local function genPoints()
        allPoints = {}
        -- 6行*10列
        for i = 0, 9 do
          for j = 0, 5 do
            -- 插入点到allPoints数组当中
            table.insert( allPoints, 1, cc.p( i * 80, j * 80 ) )
          end
        end
       
      end
    
      -- 添加卡片
      local function addCards()
    
        -- 设置随机种子
        math.randomseed( os.time() )
    
        local c  -- 卡片
        local randNum -- 随机数
        local p -- 所在点
    
        -- 添加5张卡片
        for var = 1, 5 do
          c = card( var ) -- 生成一张卡片
          layer:addChild( c ) -- 添加到层当中
          -- 根据数组最大值生成随机数
          randNum = math.random( table.maxn(allPoints)  )
          p = table.remove( allPoints, randNum )
          c:setPosition( p )
          c:setAnchorPoint(  cc.p( 0, 0 ) )
          print("p.x:"..p.x..",p.y:"..p.y);
          
          -- 插入到卡片数组
          table.insert( allCards, 1, c )
        end
    
      end
    
      -- 开始游戏
      local function startGame()
        -- 初始值为1
        currentNum = 1
        -- 先生成可用点
        genPoints()
        -- 然后添加卡片
        addCards()
      end
    
    
      -- 显示所有卡片背景
      local function showAllCardsBg()
        for key, var in pairs(allCards) do
          var:showBg()
        end
      end
    
      -- 触摸事件,第一个参数为事件类型,第二个参数为x坐标,第二个为y坐标
      local function onTouch( type, x, y )
        -- 根据x,y生成一个点
        local p = cc.p(x,y)
        for key, var in pairs(allCards) do
          print(var:getPosition())
          -- 判断是否是点击范围
          local pX,pY = var:getPosition()
          if (p.x < (pX + 80)) and (p.y < (pY + 80) and (p.x > pX) and (p.y > pY)) then
          --if var:getBoundingBox():containsPoint(p) then
            if currentNum == var.num then
              -- 如果是点击的数字,则移除卡片
              table.remove(allCards, key)
              layer:removeChild(var, true)
    
              -- 点击了1之后,其他数字翻过背景
              if currentNum == 1 then
                showAllCardsBg()
              end
    
              -- 当所有卡片都被顺序点击了,提示成功
              if table.maxn( allCards ) <= 0 then
                print( "Success" )
                
              end
    
              -- 每次增加1
              currentNum = currentNum + 1
            end
          end
        end
      end
    
      -- 初始化方法
      local function init()
    
        -- 创建一个层
        layer = cc.Layer:create()
        -- 将层添加到场景
        self:addChild( layer )
        -- 设置可点击
        layer:setTouchEnabled( true )
        -- 注册监听事件
        layer:registerScriptTouchHandler( onTouch )
        -- 开始游戏
        startGame()
        -- self:addChild(layer)
    
        --    --测试代码
        --    local s = cc.Sprite:create("res/mn.jpg")
        --    s:setPosition(cc.p(0,0))
        --    s:setAnchorPoint( cc.p( 0, 0 ) )
        --    layer:addChild(s)
        --
        --    layer:setTouchEnabled(true)
        --    layer:registerScriptTouchHandler( function (type,x,y)
        --
        --        if s:getBoundingBox():containsPoint(cc.p(x,y)) then
        --          print("mn clicked")
        --        end
        --        print(type)
        --        return true
        --    end )
        --
        --    self:addChild(layer)
      end
    
      init()
    
      return self
    end
    
    
    
    --入口方法
    local function _main()
      -- 获得导演类实例
      local dir = cc.Director:getInstance()
      -- 设置不显示帧
      dir:setDisplayStats(false)
      -- 运行场景
      dir:runWithScene(Main())
    
    end
    
    -- 调用入口方法
    _main()

    以上代码已经很详尽,笔者就不多做解释,主要在这里提一下,如果使用笔者的开发环境的话,需要注意以下几个问题:
    1. XCode不能很好的支持Lua的编辑,所以我们使用LDT来进行编码,但会遇到XCode运行程序没有呈现最新效果,这时我们需要对XCode进行Clean,然后再编译。这个过程很麻烦,笔者正在在寻求其他更好的解决方案。
    2. 因为Cocos2d-x版本的变化,使用Lua编写C++逻辑代码也发生了相应的变化,一些API被新版本抛弃,比如之前CCDirector会以cc.Director的形式呈现。笔者在网上也没有找到相应的说明,只能通过查看Cocos2d-x提供的示例程序查找相关API的使用。



    展开全文
  • 制作一张简单的网页(HTML+CSS+JS) 【2】

    万次阅读 多人点赞 2019-07-12 09:14:25
    一.CSS样式的基本知识 1.关于注释: /*注释内容*/ 2.最常见的css样式格式——嵌入式 ... 例如对span里的内容的改为蓝色: <style type=text/css> span{ color:blue; } <...
  • 制作一张简单的网页(HTML+CSS+JS)【1】

    万次阅读 多人点赞 2017-02-06 12:18:20
    .认识标签 接下来我把一些常用标签整理出来,列在下面。 1. 段落 2. 文章标题,其中的x分为1~6,写的时候讲x改为1~6,并且从1开始字体逐级变小 3. 该部分变为斜体 4. 该部分变为粗体 5. 只是为了能够...
  • 数据库字段数据(昵称)排序,规则: 数字>英文字母>汉字首字母 兼容繁体排序  在日常运用中我们经常会遇到要对数据进行排序,特别是对昵称的排序。最近被要求对昵称排序,刚拿到手的时候开始还觉得挺简单的,...
  • if img1[rows,cols]>=127:#值化处理,把一整图片的像素处理成只有0和1 img1[rows,cols]=1 else: img1[rows,cols]=0#这里选择的临界点是127,正好是0-255的中间值 imgs[i,rows*28+cols]=img1[rows,cols]#把...
  • 主成分分析-简单人脸识别(

    千次阅读 2014-12-27 10:36:43
    一):人脸预准备 (文章说明:正常的人脸识别时,需要的是足够多的样本来进行训练,以期...正常情况下,为了使算法更好,怎么也得好多个不同的人脸图片吧,对每脸来说,怎么也得好几副不同的图像才可以达到很好的效
  • Python黑帽第篇文章将分享Python网络攻防基础知识,看看Python能做什么,以及正则表达式、网络爬虫和套接通信入门基础。本文参考了i春秋ADO老师的课程内容,这里真心推荐大家去学习ichunqiu的课程,同时也结合...
  • 上面的第个小部分其实是一个文件体的结构,最后会以–分割符–结尾,表示请求体结束。 通过上面分析,可以知道要发送一个multipart/form-data的请求,其实任何支持post请求的工具或语言都可以支持,只是自己要...
  • 图片,信息量比较大,字符区域明显。   样本以及待识别的样本的处理过程:   首先值化,阈值100时的效果图。 第一步:检测图像Blob块,去掉图像左上端的黑快 方法:直接对值图像进行从左上开始的像素扫描...
  • 众所周知,创建一个套接可以bind到一个特定的ip地址和端口,实际上套接这一概念代表了TCP/IP协议栈的应用层标识,协议栈中的应用层就是通过一个ip地址和一个端口号标识的,当然这仅仅是对于TCP/IP协议族而言,...
  • Zookeeper简单介绍

    万次阅读 2017-07-06 23:00:17
    、分布式锁的实现 1.1 面临的问题 1.2 分布式锁的实现者 三、ZooKeeper概述 四、ZooKeeper数据模型 4.1 ZooKeeper数据模型Znode 4.2 ZooKeeper中的时间 4.3 ZooKeeper节点属性 五、ZooKeeper服务中操作 ...
  • 一、ZRender 是维绘图引擎,它提供 Canvas、SVG、VML 等多种渲染方式。ZRender 也是 ECharts 的渲染器; 、下面是以图片做的简单demo,分为左中右三部分,左边是需要的图片,中间是绘图部分,右边是添加文字...
  • 查找()简单清晰的B树、Trie树详解

    万次阅读 多人点赞 2014-05-18 00:05:30
    查找()   散列表 散列表是普通数组概念的推广。由于对普通数组可以直接寻址,使得能在O(1)时间内访问数组中的任意位置。在散列表中,不是直接把关键字作为数组的下标,而是根据关键字计算出相应的下标。 ...
  • SVM学习笔记()----手写数字识别

    万次阅读 2016-01-02 13:00:29
    SVM学习笔记() 引言 人类视觉系统是世界上众多的奇迹之一。看看下面的手写数字序列: 大多数人毫不费力就能够认出这些数字为504192。如果尝试让计算机程序来识别诸如上面的数字,就会明显感受到视觉模式...
  • 历久而新,我的新书《第行代码》已出版!

    万次阅读 多人点赞 2016-11-23 09:49:08
    《第行代码》中的内容我相信很多人都会非常感兴趣,因为里面确实加入了很多很新的知识。略粗概括一下的话,新增内容就包括有Android Studio、Gradle、Material Design、运行时权限、多窗口模式、RecyclerView、...
  • 海龟绘图简易教程|Turtle for Python

    万次阅读 多人点赞 2018-09-11 10:55:14
    讲的再多也不如自己动手做一做,我们在网上挑选了几使用 turtle 做的有意思的图片,自己动手试试吧 彩蛋 # coding=utf-8 import turtle from datetime import * # 抬起画笔,向前...
  • 简单说 CSS的vertical-align

    万次阅读 多人点赞 2017-08-02 20:43:39
    这就要说到 vertical-align 和 line-height ,不过在这之前我们要先说说,vertical-align 的默认值 baseline,看下面这张从鑫旭大神那借来的图就好了。 我们刚学英语的时使用的那个英语本子每行有四条线...
  • pandas库简单入门

    万次阅读 多人点赞 2018-12-03 10:53:59
    2.3.2.1 axis参数说明 当axis = 1的时候,concat就是行对齐,然后将不同列名称的两表合并。 result = pd.concat([df1, df4], axis=1) 2.3.2.2 join参数说明 加上join参数的属性,如果为inner得到的是两表的交集,...
  • FCN 简单梳理

    万次阅读 多人点赞 2016-11-09 00:09:09
    以往的CNN都是对整图片进行分类,不能识别图片中特定部分的物体,而全卷积网络是对一张图片中的每个像素进行分类,以此达到对图片特定部分进行分类的效果。1 卷积化(convolutionalization)卷积化 以往分类的网络
  • Android简单计算器实现

    万次阅读 多人点赞 2017-07-28 21:29:47
    Android简单计算器实现前言最近刚开始学习安卓,只是简单的看到布局那块,就开始上手写了,从布局那里就开始各种乱,还到处拖按钮,一开始的第一版只能实现两个数的运算,比较简单,就是简单的上了个手,在第版里...
  •         [1]Deep learning简介 ...[2]Deep Learning训练过程 ...[3]Deep Learning模型之:CNN卷积神经网络推导和实现 ...[4]Deep Learning模型之:CNN的反向...[6]Deep Learning模型之:CNN卷积神经网络()文...
  • 8000干货:那些很厉害的人是怎么构建知识体系的

    万次阅读 多人点赞 2019-09-29 11:18:27
    本文约8000,正常阅读需要15~20分钟。读完本文可以获得如下收益: 分辨知识和知识体系的差别 理解如何用八大问发现知识的连接点; 掌握致用类知识体系的构建方法; 能够应用甜蜜区模型找到特定领域来构建知识体系...
  • 树状数组简单易懂的详解

    万次阅读 多人点赞 2018-01-25 19:29:05
    树状数组确实是个好东西啊,以前搞比赛的时候了解过它,会套用模版,但确没有深入理解这个东西,先学会用轮子,然后再学造轮子嘛,这段时间再回头研究了一下,发现进制在算法中真的是的好东西,它可以使算法的时间...
  • k8s和Docker关系简单说明

    万次阅读 多人点赞 2019-01-28 17:24:02
     接下来我们看两经典的图: 一、从虚拟化角度: 图1  上图是Docker容器(可用k8s管理的玩意儿)与传统虚拟化方式的不同之处,传统的虚拟技术,在将物理硬件虚拟成多套硬件后,需要再每套硬件上都...
  • 简单解释 MapReduce 算法

    万次阅读 2016-12-12 17:04:55
    你想数出一摞牌中有多少黑桃。直观方式是一张一张检查并且数出有多少是黑桃? MapReduce方法则是: 给在座的所有玩家中分配这摞牌 让每个玩家数自己手中的牌有几是黑桃,然后把这个数目...
  • 文字识别(三)--文字定位与切割

    千次阅读 2019-02-18 11:10:30
    要做文字识别,第一步要考虑的就是怎么将每一个字符从图片中切割下来,然后才可以...当然,我们实际上要识别的图片很可能没上面那图片如此整洁,很可能是倾斜的,或者是带噪声的,又或者这图片是用手机拍下来下...
  • UEditor之实现配置简单的图片上传示例

    万次阅读 多人点赞 2016-06-11 18:27:31
    ,也就是说只有这个路径,没有第个,会不会觉得很坑呢? 我们把路径改成jsp的:, serverUrl: URL + “jsp/controller.jsp” 我们把注释去掉,重新启动tomcat,刷新页面,点击图片上传按钮, window....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 280,822
精华内容 112,328
关键字:

张的二简字