精华内容
下载资源
问答
  • 今天本车从错题本的方法出发,我们一起看看错题本怎么才算得对,得好,切实可用。你觉得错题本不好用,可能是下面有些步骤没做好哦!(有些步骤可能太繁琐,可以依照自身情况修改,仅供借鉴)制作错题本的...

    《错题本》制作


    每个人肯定都有听说,错题本对高考到底多么多么有用,对我们的复习多么多么有用。但是问题也来了,做错题本好像要用我们很多的时间,可能做完了还空看,那怎么办呢?今天本车从做错题本的方法出发,我们一起看看错题本怎么错才算做得对,做得好,切实可用。你觉得错题本不好用,可能是下面有些步骤没做好哦!

    (有些步骤可能太繁琐,可以依照自身情况修改,仅供借鉴


    制作错题本的简单步骤如下

    步骤1、把所有的练习册和试卷 找出来分学科按学期顺序整理;以学年或学期为单位装订在一起,最好能在外面蒙上一张封皮。

    步骤2、找6个档案盒或文件夹或手提纸袋;分别按照考试科目 贴上标签(如:语文、数学)。

    步骤3、找6个大16开的本子,将高考 科目写在本子的前面。

    步骤4、将本子纵向分成三栏,用黑色笔在最左边一栏,按照时间顺序抄写(或粘贴)所有的错题,连带做错的部分全部照抄。抄错题的时候,最好将以下信息也记录下来:

    (1)时间;

    (2)错题的出处(哪一次测验的哪一份试卷);

    (3)错题的分值;

    (4)扣分值。

    (以上工作可以请家长帮忙)

    步骤5、在本子中间一栏,对应抄写的错题位置, 重新做题

    步骤6、用红笔在本子的最右边一栏,仔细 分析总结该题所涉及到的知识点、在知识网络中所处的位置、题型、解题 的思路和方法,该题出错的原因及应当掌握的重点。在总结出错原因的时候,不要简单地写诸如“马虎”、“粗心”、“没有复习好”、“试题出偏了”等这类似是 而非的理由,这种理由既骗别人,也骗自己!不要写考试发挥失常,而要写发挥失常的原因!比如是审题出错、运算出错、还是时间安排不当等等。






    另外,还可以准备6个档案盒或文件夹或手提纸袋,分门别类存放这一学年的各种练习和测验卷子。一个学科一个,以后无论是找起来,还是用起来都很方便。


    《错题本》中错误类型的整理与归纳分析


       在考试结束后,要认真反思自己的错题,找出产生错误的原因,解决思维定势问题;要通过整理、分析、归类找出自己的错误类型和各类错误百分比或出错概率,分析出错的根本原因,为什么错了、当时是怎么想的、正确的解法是什么、以后应该注意什么;要注意老师的分析评讲,该题的引导语、切入点、解题的技巧、规范、步骤等等,并标注在错题旁。写出解题时的思维过程,与自己的思维障碍,找到思路突破的方法。


    可以依照这些数据制一张统计图,分析出现错误的原因,是答题失误,是思维方法型错误、还是知识型错误、运算错误,这是建立错题本最为关键的步骤环节,可以非常直观地发现你学习中的主要问题。


       经过一个阶段自查,建立一份个人补差档案。定期归类、整理,通过边查边改,重复犯的错误一定会越来越少。


    《错题本》中错误类型的分析及学习方法的改进
    不同错题类型产生的原因迥然不同,其解决的策略也各异,方法也有别。要根据错误的原因运用相应的对策,对症下药。以下是相关策略的初步运用:


    一、不会做的题:


    这主要表现在智力因素培养方面,对于知识结构性错误,重做一遍二遍错题是十分必要的,这要视你自己对错题的把握程度而定。这类错误是我们通过学习,建立自 身知识体系时存在的漏洞,通过重做错题,并认真分析,把这个漏洞补上,就可以健全我们的知识结构体系,锻炼我们的思维能力,用10分钟的时间就可取得平时 1~2小时的收益。也能发现自己究竟是学习行为方面存在问题,还是某些思维方式需要加以调整。



    1、概念不清类:这类问题包括知识结构板块、知识点、基础知识(诸如具体的定理、公式、概念等等),容易压得人喘不过气来。 处于不同学习层次的同学要根据自己的实际情况,加强训练和记忆,培养自己的宏观思维方式,因人而异地确定自己的学习目标、步骤和解决问题的方案,并且有效地进行目标时间管理。


    2、题型类:这类问题往往是未能掌握不同题型的解题思路或技巧;或处理问题的方式过于死板,虽然知道该题涉及到的知识点,但是却无从下手。其实无论是哪一类题型,都有其解题的一般思路和方法(共性),只要掌握住某一题型的答题要领,以及能够仔细区分某一特定试题的“个性”,就能顺利将题解出。加强训练,假以时日便能培养自己举一反三能力,增进解题的灵活性与变通力,并且随时都能够有所感悟,使自己的思维能力得到提高。


    3、能力应用类:这类问题往往是对知识点(概念)的理解较为浅显,思维单一,知其然不知其所以然。当使用障眼法,把曾经解答过的题变换某些条件,移植一种情景时,就会产生似曾相识的感觉,不再细辨其中的异同,自然会被虚假条件搞昏头。究其原因主要还是对某些知识缺乏灵活运用, 不能融会贯通,同时缺乏理论联系实际的探索精神。要针对试题涉及的知识点及内容认真地加以复习巩固,多观察和了解日常生活现象,做操作题时多与理论相联系,加强典型题与日常生活应用训练,多做试题分析。这样可以有效地培养和训练自己的发散思维能力、观察能力和逆向思维能力。


    二、模棱两可似是而非的题

    对于模棱两可似是而非的错题,通过分析,可以发现是把公式给弄混淆了?还是把公式给用错了?是理解错了?还是记忆错了?


    1、概念模糊类:这类问题往往是一点就通,容易被人忽视。比如巧妙设置在题中的隐含条件、限制条件和关键词语等等这类问题,往往一点就破,一般会认为自己是弄懂了的,只是没有发现而已,实际上是概念模糊。有的则是自身知识结构体系脉络不清,以致给出错误答案。加强概念和基础知 识的训练和巩固,多做典型题型是解决这类错误的方法之一。


    2、记忆模糊类:这类问题主要是对概念和原理等的理解过于浅显,或记得不牢,或只知其一,不知其二,当问题交织在一起时,便分辨不清,导致答题时似是而非。当问题成堆时,面对题海便会显得迷茫、不知所措、甚至于无精打彩,以至于懈怠下去。攻克这类问题主要就是解决理解和记忆, 并要拓展知识的运用。


    三、会做的却做错了的题


    这主要表现在非智力因素培养方面,这类问题最容易被人忽视,常常会自以为是地认为下次注意就行了,自己是不会再犯这个错误的,然而,往往却事与愿违,不会发生的事竟然又一次发生了。所以,别对自己的错误太温柔,一定要找出问题所在,消灭这类问题。


    1、顾此失彼类:考题中涉及的知识点稍多一点,过程稍复杂一些,大脑就运转不过来,顾头不顾尾。这主要缘于典型题做得不够,做得不精,做题的难度系数也较低,并对教材中的观点、基本原理和基本概念等理解得不深不透。


    2、审题错误类:还没看清条件就急忙解题,可能是观察得不够仔细,判断得不够准确,也可能是考试策略不当,或是心理心态不稳,还可能是缘于外界的干扰刺激,更有可能是平时练习不到位,仅仅是为了完成作业而作业,或做题缺乏针对性,成天盲目做题,忽略了做完题后的反思环节,以 及平时就缺乏慢审题快解题的训练。要养成“袖手于前疾书在后”的答题风格,以及做完题后进行回顾和总结的习惯,这对增强自己的审题能力极有好处。


    四、考试策略类:


    这主要表现在非智力因素培养方面,比如遇到复杂一些的考题,便心生恐惧,头脑发懵以至造成失误,或缺乏答题的快慢观念。面对比较有把握的考题也自我怀疑, 答题时犹豫不决,这也会在一定程度上强化不良的考试情绪,干扰解题的思路。通过这部分的分析可以发现自己是思路不清?还是思路受到了干扰?


    1、考场时间分配不合理:平时没有从心理上把练习和考试作为正式考试来对待,没有把一般性的考试作为训练考试时间分配的练兵场,导致正式考试时虎头蛇尾,眼睁睁看着自己熟悉的题却没有时间下手。


    2、舌尖现象:答案就在嘴边盘旋,但就是写不出来。这与心理紧张、心态失衡有关。在答题时要从容不迫沉着冷静,这需要平时加强非智力因素方面的训练和培养。


    3、克拉克现象:见到生题或难题便心烦意乱,乱了方寸。这与心理应激反应有关,破坏了考试竞技场上应有的状态,平时就要克服急躁心理,化解不良情绪,提高自信心,消除烦躁不安、焦虑紧张的心态,做到心平气和情绪稳定。这也需要平时加强非智力因素方面的训练和培养。


    4、考前失眠:表现在考场上无法集中精力,逻辑思维混乱,反应迟钝,计算失误。主要缘于压力过大、始终处于焦虑状态。这同样 需要平时加强非智力因素方面的训练和培养。比如,平时就要多进行心理心态的调整和引导,培养和提高自己的心理素质,达到心理稳定从容不迫。此外,当不幸处 于焦虑状态时,可以问一问自己:“我焦虑的是什么?”、“这种焦虑对结果有帮助吗?”、“有哪些方法可以解决?”、“我会有办法解决!”


    要加强考试心理和考试策略训练,可以灵活运用《提升学习竞争力》中的案例。






    五、非知识结构性错误(马虎粗心导致丢分)


    这主要表现在非智力因素培养方面,由于马虎出错导致丢分是一个普遍存在的现象,于是大家往往就变得心安理得,还会唐吉珂德式原谅自己:“这些题我都会做, 就是粗心没考好,否则就是满分了,我今后要注意克服。”能克服吗?未必!因为粗心不是一种行为,马虎也不是一种行为,要改还得从行为入手,平时要加强行为 习惯的训练。学习中常见的粗心或马虎行为主要有以下几种。


    1、看错:看错题这种行为产生的原因主要与人的瞬时记忆有关。有的人视觉成像反应稍慢(他的学习类型可能不属于视觉类型), 而他又看得快,前面的信息在大脑中还未形成稳定的状态时,后面的信息又进来了,于是导致把题看错,解决这一行为就是放慢看题速度,也就是俗话所说的“看仔 细点”。有的人则可能是与自身的短时记忆容量有关,人的短时记忆容量为7±2,如果一个人的短时记忆容量为5,即他一次瞬间只能记住5个单词或数字之类的东西,当他想一次瞬间记住7个时,就会出现记忆错误,从而就会发生看错了的现象,解决这一看错行为可以通过平时训练来达到,最简单的办法是在上学或放学的路上用瞥一眼方式去记路边的汽车牌照,也可以运用瞥一眼的方式去记一组数字或符号或英语单词,以提高自己的短时记忆容量,增强记忆力。


    2、抄错:普遍把草稿纸上的正确答案抄到答卷上出错或抄漏是最冤枉的一种丢分。这一抄错行为的产生除了与瞬时记忆有关外,还 与人的过忆过程有关,抄写包括记(看)和忆(写)两个过程,你可能没有看错,但你却写错了,为什么呢?因为人们在回忆时,总是会把后面位置的字与前面位置 的字颠倒,在你说话或背诵时也会出现这种前后位置颠倒的情况。解决这一行为的办法就是进行大量的快速抄写行为训练,提高大脑的纠错能力。另一个原因还与人 的记忆缓存有关,举个例来说,有的人可以在别人念下一句时,继续写完上一句,有的人却比较困难,这也需要通过经常的听写行为训练来加以解决。


    3、算错:计算时出错。这主要反映出平时的练习少了,没有养成自动化答题技能,没有形成稳固的肌肉记忆方式。大家知道骑自行 车不倒,靠的就是肌肉记忆反应,在急刹车时,靠的也是肌肉记忆反应,如果要等到大脑来指挥的话,车祸就已经发生了。肌肉记忆方式可以有效地减轻我们大脑的 负担,让我们的大脑去想更加复杂的问题。也有可能是我们平时在草稿纸上演算就不注意整洁,乱七八糟,缺乏规范化的训练,于是算错也就成了一件“很正常”的 事了。


    4、写错(书写出错):比如,明明是大于号却偏偏写成了小于号,此外还有正负号、小数点、字、词或字母、符号等等的书写出 错,这就需要首先从心理上、从思想意识上看清符号(比如:正负号)的有无,准确地记住小数点的位置;另一原因是肌肉记忆出现偏差,解决这一书写出错行为可 以采用双人训练的方法,一人快速念,一人快速写,加强肌肉记忆训练。


    这4类错误是最容易取得成效的,只需稍加训练即可。


    5、想错(判断错误):一个原因是知识掌握得不牢,相似知识点之间发生了混淆,出现判断失误。另一个原因属于想当然失误,即没有注意到题型的条件已经发生了改变,从而落入了出题人设下的陷阱。


    6、跳步:以为自己明白了,或害怕答题速度跟不上,不写出相关步骤,结果发生了错误。首先是要符合答题规范,其次是你明白了,阅卷人明白吗?所以关键信息绝对不能跳步。


    7、没有完全按要求答题。这与跳步答题的错误相似,不同之处在于这类题是有明确要求的,当你随意忽略时,失误就在所难免。


    进阶与提高
    不能仅仅满足于知道出错的浅显缘由,归类分析自己的错误类型,找到自己学习的主攻方向,还要找到解决各种错误类型的途径,并立即坚持执行之,最终就能形成适合自己的方法。



    1、错题本的类型


    常见的“错题本”可以分为四大类型:一是索引型,将所有错题的题目抄下来,做成一个错题索引本;二是章节型,将所有错题按学科的章节顺序进行分类整理;三是原因型,将所有错题按错误的原因进行分类整理;四是三栏式,将所有错题按学科的章节顺序和错误性质进行分类整理,优点在于既能将错误分门别类,区别对待,又能按原因查找,还能按章节查找易错知识点。对于非知识结构性丢分可以只给出索引,这能有效地减轻工作量。通过错题本与错误类型分析可以培养同学们的 归纳分析和认知思维能力,将追求分数论高低转化成为素质培养(如:学会如何处理问题的能力)。


    在制作过程中,既可以采用在原试卷上标注,在“错题本”上做索引的方式,简化“错题本”;也可以采用剪贴方式;还可以对同一类型问题只记录典型题型、难点 和出错次数。也可做成活页式,按自己的风格进行装订,每次查阅时还可及时更换或补充。要把原来错误的解法清晰地摘要在错题本上,并在下面留有一块空 白。


    2、亡羊补牢(纠正错误)


    “错题本”做好后不要束之高阁,不能满足于看一看,翻一翻就自以为是地觉得自己已经掌握了,就能把自己的知识漏洞修补好了。对每一道知识结构性错题,应根据相同或相关的典型题型,去查找课本或资料,找到每道题的解题依据,找到出错的原因,讲出应该如何去做的道理。老师讲解正确答案时,在原题下面空白处记下 自己没有做出来或做错的原因分析,把原题做一遍,以加深印象和逐步形成能力。如果此题有多种解题思路,可以在旁边用另一颜色笔把几种解法的简要思路写上。 对于不太熟悉的内容和解题思路,一定要打破沙锅问到底,反复练习,掌握其解题规律,以便用一个点的解决带动一条线的解决,用一条线的解决带动一个面的解 决。只有把典型题型弄清楚了,才能应对试题的千变万化,这就是以不变应万变。通过对试题的练习和印证,我们还会更加清晰地明白某道题属于某个知识板块,涉及到几个知识点,有哪些解题思路和方法,让模糊的东西清晰化,随着认识的一步步深化,思维能力也会随之增加。


    3、出题法


    这一工作做起来比较有趣,解题经验丰富的同学做起来会比较顺利一些。依照某一题型试着变换一些条件,就可编出一些试题,这是夯实自身知识结构体系的方法之一,也是正确理解课本中概念、原理等的路径之一,还能培养自己的解题意识,解题能力及各种思维能力。在最初运用此法时,建议只对试题条件做小小的改动即可。


    此外,还可准备一个知识结构总结本,及时对所学知识进行总结,形成自己的知识结构网络体系,把自己的思维意识提升一个高度,达到总揽全局的效果。


    4、错误类型体系图


    前面我们进行的是单一学科错题类型分析,把当你把全部学科的错题类型归类放在一起时,就可建立起自己的错误体系,尤其是非知识结构出错方面,比如,查出各种错误类型(如看错、算错等等)所占比例大小,进而有效地找出自己学习中存在的共通性问题(跨学科)。


    使用错题本的五个层次
    一、不使用错题本


    面对错题处于一种茫然的境地,不知道自己为什么会一错再错,错误总是象影子一样跟随着自己。


    二、有错题本,仅限于就题改题


    没有去分析出错的原因,或者分析得比较浅,或者过于笼统,比如,大意了,粗心了。虽然也能取得较好的成绩,但是可能学得比较死板。


    三、有错题本,查找出错原因


    能通过错题这一表面现象查找错题背后的出错原因,还会去分析这道错题的解题方法和思路,属于哪类题型,涉及到哪些知识点,可以有效地培养和提高自己的分析问题、解决问题的能力,能够感受到学习是一件有趣的事情。能够取得好的成绩。


    四、分析整理错题本(错题本的利用)


    能从错题中发现自己的出错类型及百分比,能够分门别类有条不紊地区别处理不同的问题,具有知识结构板块和框架意识,并以此制定和调整自己的学习目标,可以培养和提高自己的思维能力和分析归纳能力,能够感受到学习是一件愉快的事情,能够取得很好的成绩。


    有了错题本,如何利用呢?方法是:要经常阅读错题本。错题本不是把做错的习题记下来就完了。要经常浏览错题本,对错题不妨再做一遍,这样就使每一道错题都 发挥出最大效果,今后遇到同类习题时,就能够立刻回想起曾经犯过的错误,从而避免再犯。如果各科都建立错题本,并经常温故知错、持之以恒,高考成绩至少会提高20分。


    五、运用出题法提高自己的解题意识


    能高屋建瓴自上而下地从知识板块、知识点、题型、解题的方法和思路,涉及到的基础知识的角度去判断分析,去发现问题和处理问题,能够主动从错题类型,从题型入手去自己出题自己解,去发现自己的不足,提高自己看问题的洞察力和思维判断力,能够感受到学习是一件轻松愉快的事情。能够深切地体会到:能力的培养比成绩更重要。


    高中学习是一个连续性的过程,在学习过程中,既要注重知识结构的系统性,学习方法的灵活性,还要注重学习和考试心态的稳定性,学习和考试心态稳定了,学习情绪就会高涨,学习效率就会提高,学习就会突飞猛进,自己的思维意识和各种能力及综合素质就能得到极大的提高。


    高考并不是一定要熬夜苦战,也不是要在题海中盲目的漫游,建立一套适合自己的学习方法,才是最为重要的。


    高考状元错题本经验之谈
    辛旺:


    掌握了自己犯错的类型,我就为防范错误做好准备。我比较重视一些概念上的错误,我仔细分析过我的试卷,可以说一半以上的错误都是因为审题不清造成的。每个经历过高考的人都知道,高考中审题特别重要。找出诱使你审题不清的小陷阱,熟悉之后就不容易掉进去了。


    记载下来的错误越多,说明我对这一科的掌握还存在很大的不足,也需要投入更多的精力。在高三复习化学时,由于我底子不厚实,而化学的概念又比较多,所以在 我的错题集里记录下来的错题比别的学科要多一些。通过错题集,我及时调整了复习计划,加大了复习化学的力度,使高考化学成绩有了很明显的提高。临近高考的 时候,我把我的几个错题本集中在一起看,每个学科的错误都被我重新集中扫视了一遍,每一次错误都被我牢牢记在心里,并且以最佳状态做好了防范。


    及时改错,不让错误陪我过夜


    对于错题,注意做到:一是不绕过,二是不拖拉,三是分析总结。不绕过,就是正视自己的错误,不讳疾忌医,不为自己的错误找借口,搞不懂的知识就勇敢承认自己的缺陷,绝不不懂装懂,害羞胆怯地自欺欺人。不拖拉,意思是遇到错题,当场解决,不要隔一段时间再去解决,因为经过一段时间的间隔,很可能造成遗忘,让 你想不起自己当初是怎样犯的错。因此及时改错很有必要。分析总结,就是对于每一个错题都要经过认认真真的分析,研究出错的原因,找准致错的症结,同时及时进行改错,避免再次犯错。


    也就是11月份,我才开始建错题本。错题本的最大好处就是暴露了你的弱点,看完之后觉得很充实,该解决的问题都解决了,觉得自己不害怕了。


    黄芳:


    在错题中淘“金”


    对于做错的客观题和回答不完整、不理想的主观题,我会认真整理,认真反刍,加深对每个专题不同的切入角度以及它与其他专题之间联系的了解,进一步明确该专题的不同层次需应用哪些基础知识和技能来分析。同时,还要检查在提取有效信息及答题规范化方面的欠缺,以提高解题能力。


    每当遇到自己做错的题,我会马上去找寻错因,问自己为什么会这样选,为什么对正确的答案没有感应。


    一些同学认为选择题是就是考一个个知识点,错了是因为没有记牢。其实现在的高考很少单独考一个单独、具体的知识点,而是要分析事件发生的原因、结果。我明白这一点之后,在平时复习中,就更重视答题时系统的分析,更注重答题的针对性。


    经过一段时间的训练,我发现是自己思维方式上存在的误区,导致了一些不该犯的错误,我把这些错题记录下来,把错误一一纠正,决不让同样的错误再犯第二次。经过长期的积累,犯的错误越来越少,考试中的正确率也就提高了。


    转载自:http://www.360doc.com/content/18/0318/17/53611590_738174112.shtml




    展开全文
  • Java 代码界 3% 的王者?看我是如何解这 5 道题的

    万次阅读 多人点赞 2019-07-16 16:50:38
    前些日子,阿里妹(妹子出题也这么难)发表了一篇文章《悬赏征集!5 道题征集代码界前 3% 的超级王者》——看到这个标题...不过,好歹我这人脸皮特别厚,虽然全都做错了,但还是敢于坦然地面对自己。 01、原始类型的...

    前些日子,阿里妹(妹子出题也这么难)发表了一篇文章《悬赏征集!5 道题征集代码界前 3% 的超级王者》——看到这个标题,我内心非常非常激动,因为终于可以证明自己技术很牛逼了。

    但遗憾的是,凭借 8 年的 Java 开发经验,我发现这五道题自己全解错了!惨痛的教训再次证明,我是那被秒杀的 97% 的工程师之一。

    不过,好歹我这人脸皮特别厚,虽然全都做错了,但还是敢于坦然地面对自己。

    01、原始类型的 float

    第一题是这样的,代码如下:

    public class FloatPrimitiveTest {
        public static void main(String[] args) {
            float a = 1.0f - 0.9f;
            float b = 0.9f - 0.8f;
            if (a == b) {
                System.out.println("true");
            } else {
                System.out.println("false");
            }
        }
    }
    

    乍一看,这道题也太简单了吧?

    1.0f - 0.9f 的结果为 0.1f,0.9f - 0.8f 的结果为 0.1f,那自然 a == b 啊。

    但实际的结果竟然不是这样的,太伤自尊了。

    float a = 1.0f - 0.9f;
    System.out.println(a); // 0.100000024
    float b = 0.9f - 0.8f;
    System.out.println(b); // 0.099999964
    

    加上两条打印语句后,我明白了,原来发生了精度问题。

    Java 语言支持两种基本的浮点类型: float 和 double ,以及与它们对应的包装类 Float 和 Double 。它们都依据 IEEE 754 标准,该标准用科学记数法以底数为 2 的小数来表示浮点数。

    但浮点运算很少是精确的。虽然一些数字可以精确地表示为二进制小数,比如说 0.5,它等于 2-1;但有些数字则不能精确的表示,比如说 0.1。因此,浮点运算可能会导致舍入误差,产生的结果接近但并不等于我们希望的结果。

    所以,我们看到了 0.1 的两个相近的浮点值,一个是比 0.1 略微大了一点点的 0.100000024,一个是比 0.1 略微小了一点点的 0.099999964。

    Java 对于任意一个浮点字面量,最终都舍入到所能表示的最靠近的那个浮点值,遇到该值离左右两个能表示的浮点值距离相等时,默认采用偶数优先的原则——这就是为什么我们会看到两个都以 4 结尾的浮点值的原因。

    02、包装器类型 Float

    再来看第二题,代码如下:

    public class FloatWrapperTest {
        public static void main(String[] args) {
            Float a = Float.valueOf(1.0f - 0.9f);
            Float b = Float.valueOf(0.9f - 0.8f);
            if (a.equals(b)) {
                System.out.println("true");
            } else {
                System.out.println("false");
            }
        }
    }
    

    乍一看,这道题也不难,对吧?无非是把原始类型的 float 转成了包装器类型 Float,并且使用 equals 替代 == 进行判断。

    这一次,我以为包装器会解决掉精度的问题,所以我猜想输出结果为 true。但结果再次打脸——虽然我脸皮厚,但仍然能感觉到脸有些微微的红了起来。

    Float a = Float.valueOf(1.0f - 0.9f);
    System.out.println(a); // 0.100000024
    Float b = Float.valueOf(0.9f - 0.8f);
    System.out.println(b); // 0.099999964
    

    加上两条打印语句后,我明白了,原来包装器并不会解决精度的问题。

    private final float value;
    public Float(float value) {
        this.value = value;
    }
    public static Float valueOf(float f) {
        return new Float(f);
    }
    public boolean equals(Object obj) {
        return (obj instanceof Float)
               && (floatToIntBits(((Float)obj).value) == floatToIntBits(value));
    }
    

    从源码可以看得出来,包装器 Float 的确没有对精度做任何处理,况且 equals 方法的内部仍然使用了 == 进行判断。

    03、switch 判断 null 值的字符串

    来看第三题,代码如下:

    public class SwitchTest {
        public static void main(String[] args) {
            String param = null;
            switch (param) {
                case "null":
                    System.out.println("null");
                    break;
                default:
                    System.out.println("default");
            }
        }
    }
    

    这道题就有点令我雾里看花了。

    我们都知道,switch 是一种高效的判断语句,比起 if/else 真的是爽快多了。尤其是 JDK 1.7 之后,switch 的 case 条件可以是 char, byte, short, int, Character, Byte, Short, Integer, String, 或者 enum 类型。

    本题中,param 类型为 String,那么我认为是可以作为 switch 的 case 条件的,但 param 的值为 null,null 和 “null” 肯定是不匹配的,我认为程序应该进入到 default 语句输出 default。

    但结果再次打脸!程序抛出了异常:

    Exception in thread "main" java.lang.NullPointerException
    	at com.cmower.java_demo.Test.main(Test.java:7)
    

    也就是说,switch () 的括号中不允许传入 null。为什么呢?

    我翻了翻 JDK 的官方文档,看到其中有这样一句描述,我直接搬过来大家看一眼就明白了。

    When the switch statement is executed, first the Expression is evaluated. If the Expression evaluates to null, a NullPointerException is thrown and the entire switch statement completes abruptly for that reason. Otherwise, if the result is of a reference type, it is subject to unboxing conversion.

    大致的意思就是说,switch 语句执行的时候,会先执行 switch () 表达式,如果表达式的值为 null,就会抛出 NullPointerException 异常。

    那到底是为什么呢?

    public static void main(String args[])
    {
        String param = null;
        String s;
        switch((s = param).hashCode())
        {
        case 3392903: 
            if(s.equals("null"))
            {
                System.out.println("null");
                break;
            }
            // fall through
    
        default:
            System.out.println("default");
            break;
        }
    }
    

    借助 jad,我们来反编译一下 switch 的字节码,结果如上所示。原来 switch () 表达式内部执行的竟然是 (s = param).hashCode(),当 param 为 null 的时候,s 也为 null,调用 hashCode() 方法的时候自然会抛出 NullPointerException 了。

    04、BigDecimal 的赋值方式

    来看第四题,代码如下:

    public class BigDecimalTest {
        public static void main(String[] args) {
            BigDecimal a = new BigDecimal(0.1);
            System.out.println(a);
            BigDecimal b = new BigDecimal("0.1");
            System.out.println(b);
        }
    }
    

    这道题真不难,a 和 b 的唯一区别就在于 a 在调用 BigDecimal 构造方法赋值的时候传入了浮点数,而 b 传入了字符串,a 和 b 的结果应该都为 0.1,所以我认为这两种赋值方式是一样的。

    但实际上,输出结果完全出乎我的意料:

    BigDecimal a = new BigDecimal(0.1);
    System.out.println(a); // 0.1000000000000000055511151231257827021181583404541015625
    BigDecimal b = new BigDecimal("0.1");
    System.out.println(b); // 0.1
    

    这究竟又是怎么回事呢?

    这就必须看官方文档了,是时候搬出 BigDecimal(double val) 的 JavaDoc 镇楼了。

    1. The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.

    解释:使用 double 传参的时候会产生不可预期的结果,比如说 0.1 实际的值是 0.1000000000000000055511151231257827021181583404541015625,说白了,这还是精度的问题。(既然如此,为什么不废弃呢?)

    1. The String constructor, on the other hand, is perfectly predictable: writing new BigDecimal(“0.1”) creates a BigDecimal which is exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the String constructor be used in preference to this one.

    解释:使用字符串传参的时候会产生预期的结果,比如说 new BigDecimal("0.1") 的实际结果就是 0.1。

    1. When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give the same result as converting the double to a String using the Double.toString(double) method and then using the BigDecimal(String) constructor. To get that result, use the static valueOf(double) method.

    解释:如果必须将一个 double 作为参数传递给 BigDecimal 的话,建议传递该 double 值匹配的字符串值。方式有两种:

    double a = 0.1;
    System.out.println(new BigDecimal(String.valueOf(a))); // 0.1
    System.out.println(BigDecimal.valueOf(a)); // 0.1
    

    第一种,使用 String.valueOf() 把 double 转为字符串。

    第二种,使用 valueOf() 方法,该方法内部会调用 Double.toString() 将 double 转为字符串,源码如下:

    public static BigDecimal valueOf(double val) {
        // Reminder: a zero double returns '0.0', so we cannot fastpath
        // to use the constant ZERO.  This might be important enough to
        // justify a factory approach, a cache, or a few private
        // constants, later.
        return new BigDecimal(Double.toString(val));
    }
    

    05、ReentrantLock

    最后一题,也就是第五题,代码如下:

    public class LockTest {
        private final static Lock lock = new ReentrantLock();
    
        public static void main(String[] args) {
            try {
                lock.tryLock();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    

    问题如下:

    A: lock 是非公平锁
    B: finally 代码块不会抛出异常
    C: tryLock 获取锁失败则直接往下执行

    很惭愧,我不知道 ReentrantLock 是不是公平锁;也不知道 finally 代码块会不会抛出异常;更不知道 tryLock 获取锁失败的时候会不会直接往下执行。没法作答了。

    连续五道题解不出来,虽然我脸皮非常厚,但也觉得脸上火辣辣的,就像被人狠狠地抽了一个耳光。

    容我研究研究吧。

    1)lock 是非公平锁

    ReentrantLock 是一个使用频率非常高的锁,支持重入性,能够对共享资源重复加锁,即当前线程获取该锁后再次获取时不会被阻塞。

    ReentrantLock 既是公平锁又是非公平锁。调用无参构造方法时是非公平锁,源码如下:

    public ReentrantLock() {
        sync = new NonfairSync();
    }
    

    所以本题中的 lock 是非公平锁,A 选项是正确的。

    ReentrantLock 还提供了另外一种构造方法,源码如下:

    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
    

    当传入 true 的时候为公平锁,false 的时候为非公平锁。

    那公平锁和非公平锁到底有什么区别呢?

    公平锁可以保证请求资源在时间上的绝对顺序,而非公平锁有可能导致其他线程永远无法获取到锁,造成“饥饿”的现象。

    公平锁为了保证时间上的绝对顺序,需要频繁的上下文切换,而非公平锁会减少一些上下文切换,性能开销相对较小,可以保证系统更大的吞吐量。

    2)finally 代码块不会抛出异常

    Lock 对象在调用 unlock 方法时,会调用 AbstractQueuedSynchronizertryRelease 方法,如果当前线程不持有锁的话,则抛出 IllegalMonitorStateException 异常。

    所以建议本题的示例代码优化为以下形式(进入业务代码块之前,先判断当前线程是否持有锁):

    boolean isLocked = lock.tryLock();
    if (isLocked) {
        try {
            // doSomething();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    

    3)tryLock 获取锁失败则直接往下执行

    tryLock() 方法的 Javadoc 如下:

    Acquires the lock if it is available and returns immediately with the value true. If the lock is not available then this method will return immediately with the value false.

    中文意思是如果锁可以用,则获取该锁,并立即返回 true,如果锁不可用,则立即返回 false。

    针对本题的话, 在 tryLock 获取锁失败的时候,程序会执行 finally 块的代码。

    06、最后

    阿里妹出的这五道题还是蛮有深度的,我相信有不少朋友在实际的项目应用中已经遇到过了。据说这五道题背后的解决思路,将在《Java开发手册》华山版中首次披露!

    PS:欢迎关注「沉默王二」公众号,后台回复关键字「java」即可获得。

    展开全文
  • 1小时1篇文学会python再个飞机大战游戏

    万次阅读 多人点赞 2021-04-30 16:02:07
    不过我想问一下,你在这里打了两个等于号是不是你打了? 小C:这个没有。在 python 中是使用两个等于号进行判断左右两边是否相等,也就是判断两个等于号的坐标 a 是否等于右边的 11。 小媛:明白了,那为什么下一...

    注:

    想慢慢学习的同学可以看我的 《python 入门到游戏实战专栏》(更新中)
    想学 C 的同学可以看《大话系列之C语言》(基本更新完)
    想学 C++ 的同学可以看《大话C++》(更新中)
    想做习题的可以看《大学生C语言作业、习题100例白话详解》

    作者简介

    作者名:1_bit

    简介:CSDN博客专家,2020年博客之星TOP5,蓝桥签约作者。15-16年曾在网上直播,带领一批程序小白走上程序员之路。欢迎各位小白加我咨询我相关信息,迷茫的你会找到答案。系列教程将会在流量降低时转为付费位置,流量多时将不会,各位抓紧时间学习哟~

    学习开始

    👸小媛:小 C,我想学做游戏了,有什么速成的办法吗? 😰

    🐰小C:没有,谢谢。

    👸小媛:我看他们都可以,直接做一个飞机大战,说是一下子就学会了。 😨

    🐰小C:你是想先大概过一遍内容吗?还是具体的全面的学?

    👸小媛:我想先有一点体验感,自己学的舒服玩一下也行。

    🐰小C:那就可以,1小时搞定。

    👸小媛:这么快?那刚刚你又说不行。 😣

    🐰小C:你不是全面学,只学基础核心就没啥问题。一个小时搞定还是可以做点东西的。

    👸小媛:那就赶紧开始吧。

    🐰小C:那我们就学 python 吧,你觉得怎么样?

    👸小媛:可以呀,做出来游戏就可以了。

    🐰小C:你电脑我记得有环境和编辑器,我们就用原本的就好了。

    👸小媛:原本的是啥?

    🐰小C:那个 vscode,我们用的库是 pygame。

    👸小媛:唔,懂了。

    01 hello world

    🐰小C:那我们就从头开始学吧,首先打开我们的 vscode 创建一个文件叫做 game.py 进行代码的测试吧。

    👸小媛:了解,我已经新建好了。

    🐰小C:那我们首先写一个 hello world 吧。

    👸小媛:hello world 是什么? 😰

    🐰小C:是一个经典的计算机程序,就是程序运行的时候会显示 hello world。

    👸小媛:懂了,那怎么做呢?

    🐰小C:首先你要知道,编程其实就是使用不同的“魔法指令”在计算机中创造不同的东西,python 用来显示内容的指令就是 print(),你用 print() 要显示什么字符串就在里面加上去就可以了。

    👸小媛:这样吗?

    print(helloworld)
    

    🐰小C:在这里需要跟你提一点,在 python 中字符串是需要使用双引号引起来的。

    👸小媛:懂了,你的意思是这样。

    print("helloworld")
    

    🐰小C:对的,这个时候我们点击运行按键就可以看到结果了。

    👸小媛:出现结果了,在这里。

    02 变量

    🐰小C:那我们继续往下讲。我们接下来学一个容器,用来存储值。

    👸小媛:存值的内容有什么意义吗?

    🐰小C:有呀,你想想在游戏之中其实你的血量都是存在一个容器之中,还有你的昵称,不然你觉得没有东西存那这东西怎么显示?

    👸小媛:哈哈哈,之前不懂,现在懂了。 😂

    🐰小C:变量也是超级简单,我们直接给变量起个名字,用个等于号就可以存值了。你现在创建一个变量你想起什么名字呢?

    👸小媛:那就起一个名字叫做 a 就好了。

    🐰小C:那你想在这个变量 a 里面存什么值呢?

    👸小媛:那就存一个 10 吧。

    🐰小C:那么代码就可以这样写。

    a=10
    

    👸小媛:就这样? 😂

    🐰小C:是的,我们创建一个变量直接一个名字,在这个变量名右边用一个等于号连接一个值,那么这个值就会存储到这个变量中。

    👸小媛:真简单。 😎

    🐰小C:那你知道怎么存储一个字符串吗?

    👸小媛:知道呀,就这样。

    a="1_bit"
    

    🐰小C:为什么要这样写呢?

    👸小媛:因为 a 是一个变量名,用一个等于号就可以把等于号右边的值存到左边的变量中,然后最开始你说在 python 中字符串是需要双引号标记,那就是这样写咯。

    🐰小C:不错,理解透彻,那我们开始显示变量里面所存储的内容吧。

    👸小媛:这个就不会了,怎么显示呢?

    🐰小C:很简单,也是使用 print(),直接在 print() 的括号内填写变量名就可以了。

    👸小媛:这样吗?

    a="1_bit"
    print(a)
    

    🐰小C:是的。

    👸小媛:结果出来了。

    🐰小C:使用 print() 可以显示很多的内容,例如你想用字符串连接在一起显示可以使用逗号进行分隔,首先我们创建多个变量。

    a="1_bit"
    b="2_bit"
    c="3_bit"
    

    👸小媛:这样就可以创建几个变量了吗? 😲

    🐰小C:是的,python 的代码是一行行的从上往下书写,这个切记。每一句结束后就需要换到下一行去进行编写。

    👸小媛:懂了。

    🐰小C:那我们同时显示这几个变量的内容直接使用 print() 就可以了。在 print() 元你括号内填入几个变量使用逗号进行隔开就行。

    a="1_bit"
    b="2_bit"
    c="3_bit"
    print(a,b,c)
    

    👸小媛:我运行后显示出来了。

    🐰小C:你还可以在 print() 中填入其他的字符串当作值进行输出显示。

    👸小媛:那意思就是说使用引号把字符串引起来就可以了吧?然后使用逗号隔开?

    🐰小C:是的,这样字符串也是值,只要填入就可以输出显示。

    👸小媛:代码是这样,我运行出来了。

    a="1_bit"
    b="2_bit"
    c="3_bit"
    print("分别输出 a b c 的值:",a,b,c)
    

    03 变量运算

    🐰小C:其实我们的变量是可以进行相加减的,例如以下代码和结果。

    a=11
    b=2
    c=31
    print(a+b)
    print(a-b)
    print(a*c)
    

    👸小媛:明白了,跟日常生活中的一样。

    🐰小C:其实只是基础运算大致相同,我们可以看看下面这个示例。

    a="11"
    b="2"
    c="31"
    print(a+b)
    print(a+b)
    print(a+c)
    


    👸小媛:为什么会这样呢?

    🐰小C:因为两个字符串之间做加法,这个加法指的是将两个字符串进行连接,因为字符串和数字是两个类型。带双引号的 11 是字符串的 11,而不是数字的 11,你得明白这一点。

    👸小媛:哈哈哈,懂了。就是说数字也是字符,看不同形态下的表现。 😋

    🐰小C:是的。

    04 逻辑判断

    🐰小C:接下来我们可以看下逻辑判断了,这个是非常重要的知识点。

    👸小媛:是不是在游戏中用的很多?

    🐰小C:逻辑判断你要做啥其实都用的很多。

    👸小媛:那我就认真学习。

    🐰小C:其实逻辑判断就像你登录游戏时,需要判断你的帐号密码一样,判断帐号密码是否正确,正确就登录游戏,错误就退出游戏,就是这个意思。

    👸小媛:懂了。

    🐰小C:逻辑判断在 python 中使用的是 if。我们可以把这个 if 当作是一句魔法,我们在需要逻辑判断的时候就把这个打上就可以了。

    👸小媛:明白,就跟念咒语一样。 😂

    🐰小C:是的。我们打上 if 后,在 if 后面加上一个条件,然后使用冒号结束,就像下面一样。

    a=11
    if a==11:
        print("a是等于11")
    

    👸小媛:嗯,首先你是创建一个变量 a 存储 11 这个值,然后使用 if 语句给了一个条件,这个条件是 a==11,然后冒号结束。不过我想问一下,你在这里打了两个等于号是不是你打错了?

    🐰小C:这个没有。在 python 中是使用两个等于号进行判断左右两边是否相等,也就是判断两个等于号的坐标 a 是否等于右边的 11。

    👸小媛:明白了,那为什么下一句 print() 前面要空几个格呢?

    🐰小C:你想想,如果条件正确了,是不是就执行一句话,条件错误了就应该执行另外一条代码?

    👸小媛:是的。

    🐰小C:其实在这里是如果这个条件正确,就执行冒号后的下一行 print("a是等于11")。前面使用几个空格的意思是将表示这条代码属于 if 这个判断结构内,和其他代码不是一个结构的东西,这样只要条件错误就不会执行 if 结构内的了,如果你放在外面就会被执行了。

    👸小媛:懂了,你意思这样就可以标识是这个 if 结构内的东西了,是 if 这个结构内部的。

    🐰小C:是的,运行后将会显示结果。

    👸小媛:我修改了 a 的值他就不会显示出来了,啥也没显示。 😨

    a=111
    if a==11:
        print("a是等于11")
    

    🐰小C:其实我们 if 语句内可以打很多代码的,因为编程是灵活的,例如这个示例:

    a=11
    if a==11:
        print("a是等于11")
        print("a是等于11")
        print("a是等于11")
        print("a是等于11")
        print("a是等于11")
    

    👸小媛:是不是都要空相同的空格呀?

    🐰小C:是的,这样才表示是同一个层级。如果你乱空空格会出错的。

    👸小媛:明白。

    🐰小C:如果这个时候我们想知道判断错误,我们可以添加一个 else 语句,这样错误的话就是显示 else 语句内部的代码了。

    a=111
    if a==11:
        print("a是等于11")
        print("a是等于11")
        print("a是等于11")
        print("a是等于11")
        print("a是等于11")
    else:
        print("判断错误")
        print("判断错误")
        print("判断错误")
    


    👸小媛:明白了,这个 else 语句一定要紧跟着在 if 语句结束后吗?而且他是顶头的没有进行空格。

    🐰小C:是的,因为 if 和 else 是同级,如果你也空格了那不就是在 if 语句判断对后才能执行吗?这样永远就不会执行 else 语句了,并且这样写也是错误的;else 还可以紧跟在 elif 后面,当我们多条件的时候就可以使用 elif 语句。

    👸小媛:那就举个例子吧。

    🐰小C:那你看下面。

    a=2
    if a==11:
        print("a是等于11")
        print("a是等于11")
        print("a是等于11")
        print("a是等于11")
        print("a是等于11")
    elif a==2:
        print("a是等于2")
        print("a是等于2")
        print("a是等于2")
    elif a==3:
        print("a是等于3")
        print("a是等于3")
        print("a是等于3")
    else:
        print("判断错误")
        print("判断错误")
        print("判断错误")
    

    👸小媛:elif 后面跟着的就是条件吗?例如 a2 和 a3?

    🐰小C:是的,当 if 条件判断错误后会依次进行判断,哪一个条件判断正确就执行那个条件内的代码,如果所有条件错误那么就执行 else 部分。

    👸小媛:明白了,还有多少才能学完基础? 😩

    🐰小C:已经学完一半了,超级快的,哈哈哈。

    👸小媛:好,请继续。

    🐰小C:其实 if 还可以进行嵌套,例如下面这个代码。

    a=2
    b=3
    if a==2:
        if b==3:
            print("完全符合要求")
    else:
        print("第一项要求都没符合耶")
    

    👸小媛:嵌套的意思就是在 if 里面再有一个 if 吗?

    🐰小C:是的,但是里面的 if 也有层级,要表示是里面 if 内的代码还是需要使用几个空格间隔,依次往里缩。

    👸小媛:明白了。

    05 循环

    🐰小C:接下来我们学习循环。当你想重复运行某一条或者某一段代码时我们可以使用循环节省我们的代码编写时间,例如下面这段代码。

    i=0
    while i<10:
        print("你好")
        i=i+1
    

    👸小媛:你首先创建了一个变量 i,然后我就不懂了。

    🐰小C:while 是一个循环,就跟你使用 if 一样,使用 while 表示要开始循环了;while 之后的是一个条件,也就是满足这个条件才会循环 while 循环内的代码,这个条件使用冒号结束,是不是感觉 while 的形式跟 if 语句很像呢?

    👸小媛:是的,感觉很相同,然后最后的两个在前面空了几个格,并且使用了相同的空格,是表示是 while 循环结构内的代码吧?

    🐰小C:是的,这个是就会执行循环,每次循环都会执行 print("你好")i=i+1。由于条件是 i<10 ,i 每次循环都会加 1,第一次循环 i 是 0,第二次循环 i 是 1,然后依次类推肯定会超过 10的,这个时候就不循环了。下面就是结果。

    👸小媛:明白了。循环也可以进行嵌套吧?

    🐰小C:是的,不过我们暂时不用讲,由于是速成,所以我们在之后的游戏制作之中再做讲解。

    👸小媛:好的。

    06 列表

    🐰小C:接下来我们讲一个列表。我们在进行存储值的时候使用变量是存储一个值,那么我们使用列表就可以存储多个值了。

    a=[99,6,7,85,2,3]
    print(a)
    print(a[0])
    print(a[4])
    a[0]="你好"
    print("修改后的值是:",a)
    


    🐰小C:在这里这个 a 就是列表,然后使用一个等于号,将我们想要存储的值放到一个中括号内,并且值与值之间使用逗号进行分隔,这个时候就可以创建一个列表了。

    👸小媛:明白了,感觉挺简单的。然后 print(a) 就是显示这个列表的值了吧? 😢

    🐰小C:是的,然后 print(a[0]) 意思就是输出这个 a 列表内的第一个元素。在列表中 0 就表示第一个元素 99,然后 1 就表示第二个元素 6,然后以此类推,我们在输出的时候使用一个变量名,然后后面使用方括号,在方括号内写上你想显示第几个元素就可以取到这个元素然后将值进行显示输出了。

    👸小媛:懂了,然后 a[0]="你好" 的意思就是给这个位置重新赋值?

    🐰小C:是的,这个时候我们可以看到最后输出所有值的时候第一个元素的内容发生了改变。

    07 列表与 for 循环

    🐰小C:其实我们还可以使用一个循环使我们的列表一个个值进行显示,这个循环叫做 for 循环。

    👸小媛:循环还有内容没学完吗? 😰

    🐰小C:是的,还有一个 for 循环没进行学习,你看下面的代码示例。

    a=[99,6,7,85,2,3]
    for v in a:
        print(v)
    


    👸小媛:每一个值都一个个输出显示了。

    🐰小C:是的,代码 for v in a: 中的 for 表示开始使用 for 循环,接下来的 v in a 你可以理解成直接在这里创建一个变量 v,然后这个变量 v 进到 a 这个列表中一个个去取值,首先会取到最开始的值,然后每次循环就会跳到下一个值,这个时候我们就可以把这个值取出,使用 print() 就可以进行显示了。

    👸小媛:原来是这么回事,理解了。 😂

    08 自定义函数

    🐰小C:接下来我们开始编写自定义的工具了,其实 print() 我们可以称为函数,函数我们可以理解成一个工具或者说一个功能。我们需要用到这些功能的时候字节拿过来用就可以了,现在我们要编写一个菜单功能,每次用到菜单就不用自己去写那么多代码,直接使用就可以。

    👸小媛:那这样我不是可以节省很多时间了?

    🐰小C:是的,这个就叫做自定义函数,自己编写一个函数。你可以看下面的代码示例。

    def menu():
        print("这是一个菜单你可以进行查看")
        print("1.进入系统")
        print("2.退出系统")
        print("3.删除系统")
        print("4.退出帐号")
        print("5.关闭软件")
    
    menu()
    

    👸小媛:这个时候不会是上面的 print 直接显示的内容吗?

    🐰小C:不会,我先解释一下这个的意思吧。我们可以看到 def,def 表示你开始创建一个自定义函数,def 后就是一个函数名之后使用一个括号,这是定义函数的一种形式,之后的话我们使用冒号进行结束就可以了。

    👸小媛:例如我想创建一个函数叫做 abc,那么是不是可以这样写。

    def abc():
    

    🐰小C:是的,然后在冒号下一行开始编写这个函数的代码就可以了,一样的需要使用空格表示这个代码是属于这个函数内的内容。

    👸小媛:明白了。

    🐰小C:调用函数就是使用函数的意思,直接使用函数名加一对圆括号就可以使用,此时就等于运行了函数内的代码,这个时候就显示出了内容。

    👸小媛:意思说如果不使用就不会起作用?

    🐰小C:是的,是这个意思。

    👸小媛:明白了。

    🐰小C:其实函数还可以接受参数,就像你使用 print() 一样需要往里面传入数据才能显示。你自己创建一个函数也可以接受一下参数,参数其实就像你生活中用电饭锅做饭,需要有米才可以煮饭,这个米就是这个电饭锅功能的参数。

    👸小媛:懂了,那怎么做呢?

    🐰小C:很简单,在自定义函数的圆括号内创建变量,如果是多个就使用逗号进行间隔就可以了。

    👸小媛:你的意思是说这样? 😂

    def abc(a,b):
    

    🐰小C:是的,例如下面这个代码。

    def abc(a,b):
        print(a+b)
    
    abc(1,2)
    

    👸小媛:这个时候 1 就等于存到 a 里面,然后 2 就等于存到了 b 里面是吧?

    🐰小C:是的,如果你只想函数作为计算,不输出,我们可以使用一个叫做 return 的进行值的返回。例如以下代码。

    def abc(a,b):
        return a+b
    
    c=abc(1,2)
    print(c)
    

    👸小媛:你的意思是 return 会把 a+b 的结果给返回出去?

    🐰小C:是的,这个时候 c 就可以进行接收,abc(1,2) 计算后就等于了 3,最后输出 c 的内容就可以看到等于 3 了。

    👸小媛:明白了。

    09 类和对象

    🐰小C:我们接下来需要学习的是面向对象。

    👸小媛:面向对象是什么呀?我没有对象。 😨

    🐰小C:其实面向对象不是说你要有对象,其实就是我们可以创建一个类型,这个类型实例化后就是对象。

    👸小媛:不懂,好难。😭

    🐰小C:其实不难的,你看下面的示例。

    class human:
        name=""
        age=0
        def say(self):
            print("hello")
        def myInfo(self):
            print("myName:",self.name,"myAge:",self.age)
    

    👸小媛:完全看不懂啊,好难。

    🐰小C:我一个个解释给你听吧。在上面代码中的 class 就是表示现在要创建一个类别,human 就是这个类别的名称。

    👸小媛:你的意思就是 class 是关键字,后面就是这个类型的名称时候吧?

    🐰小C:是的,在这个 human 类型中,有两个属性;一个属性叫做 name,另外一个属性叫做 age。

    👸小媛:就跟正常变量一样,一个 name 存储的是空字符串,一个 age 存储的是年龄。

    🐰小C:是的,在这里 name 就用来存储名称,age 用来存储年龄,接下来就由两个方法,一个叫做 say 一个叫做 myInfo。

    👸小媛:这两个是自定义函数吧?那参数为什么是个 self 呢?

    🐰小C:这个 self 我们可以理解成当前这个类型之中的意思,家长自定义函数的参数之中我们可以当做表示这个自定义函数是属于这个类。

    👸小媛:你的意思就是加了 self 才表示是当前这个类型的方法?

    🐰小C:对的,规定是这样做的。你可以看这句代码 print("myName:",self.name,"myAge:",self.age),self就是表示当前这个类型,self.name 就表示是当前这个类型中的 name 这个变量,我们可以理解那个小数点为 “的” 的意思,self.name 就是当前类型中的 name 变量。

    👸小媛:明白了。😂

    🐰小C:我们接着看一下下面的使用方法。

    class human:
        name=""
        age=0
        def say(self):
            print("hello")
        def myInfo(self):
            print("myName:",self.name,"myAge:",self.age)
    
    xiaoM=human()
    xiaoM.say()
    xiaoM.myInfo()
    xiaoM.name="XiaoMing"
    xiaoM.age=18
    xiaoM.myInfo()
    

    🐰小C:xiaoM=human() 就是创建一个 human 对象。例如我们人是一个类型,那么具体到一个人就是一个对象,现在 human 这个类型创建到了一个具体对象存储在 xiaoM 这个变量之中。

    👸小媛:唔,明白了,有了类型才能创建到一个具体的对象。

    🐰小C:嗯,然后我们可以通过这个对象使用这个类型的方法,因为这个对象就属于这个类型。例如 xiaoM.say() 就表示使用这个类型中的 say() 方法,然后 xiaoM.myInfo() 也是;当然我们也可以使用 xiaoM.name="XiaoMing" 去赋予这个对象中这个 name 属性值,然后在使用 myinfo 进行输出,这个时候值就改变了。

    👸小媛:唔,全明白了,哈哈哈。 😎

    10 开始做游戏 pygame

    🐰小C:接下来我们开始编写一个小游戏吧。

    👸小媛:这么快?

    🐰小C:是的,已经可以去写了的。首先我们需要做的是准备工作,我们在命令窗口中使用 pip 命令安装 pygame 这个游戏库,你的电脑已经有 pygame 了,那我们就不需要这一步了。

    pip install pygame
    

    👸小媛:嗯。

    🐰小C:接下来我们的第一步是将 pygame 引入。

    import pygame
    

    🐰小C:import 就像你的一只手,然后 pygame 就是一个工具名,连起来就是将这个工具拿过来用。

    👸小媛:明白了。

    🐰小C:接下来我们就需要进行初始化。初始化就像你玩游戏需要创建一个角色一样,这就是初始化。

    import pygame
    
    pygame.init() 
    screen=pygame.display.set_mode((600,800))
    pygame.display.set_caption("这是一个飞机游戏")
    

    🐰小C:上面代码中的第二条 init 就是初始化的意思。

    👸小媛:那个小数点是不是就表示 pygame 中的 init 方法?直接使用就可以初始化? 😰

    🐰小C:是的,pygame.display.set_mode((600,800)) 这句代码我们可以理解成 pygame 这个工具中有一个工具叫做 display,display 有一个g功能就是创建窗口,名叫 set_mode,我们在 set_mode 中传入这个屏幕的宽高,并且使用括号括起来宽高就可以创建出一个屏幕了,其中 600 是宽 800 是高;之后创建了屏幕后将这个屏幕给予一个变量,之后就可以通过这个变量对这个屏幕进行操作。

    👸小媛:简单,理解起来容易。 😎

    🐰小C:接下来那一句代码 pygame.display.set_caption("这是一个飞机游戏") ,set_caption 是 display 的另外一个功能,可以设置标题,直接将字符串当作参数传入 set_caption 就可以了。

    👸小媛:懂了。

    11 游戏主循环

    🐰小C:接下来我们需要开始游戏主循环的内容,所有游戏都是通过一个循环去监听你在游戏中做了什么事,这个时候我们可以使用 while 循环给予一个 True 做条件,True 就表示永远条件正确。

    👸小媛:你的意思就是需要创建一个循环还一直看玩家按了什么键做了什么事?

    🐰小C:对的,你看下面代码。

    import pygame
    
    pygame.init() 
    screen=pygame.display.set_mode((600,800))
    pygame.display.set_caption("这是一个飞机游戏")
    
    while True:
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                exit()
    

    🐰小C:在 while 循环内有一个 for 循环用来取游戏中发生的所有事件。pygame.event.get() 将会获取到玩家做了所有的事情,通过 for 循环一个个去取,event 这个变量就分别每次取得这些内容,使用 if 判断 event 的类型 type 如果是 pygame 游戏中的退出 QUIT 那么就执行 exit() 退出整个程序。

    12 游戏素材添加

    👸小媛:唔,那也可以检测上下左右按键吧?这样就可以实现移动了?

    🐰小C:是的,不过现在我们需要往这个游戏里面添加背景和角色,这些都是图片,我们可以通过加载图片资源创建背景和主角对象,我们都可以称这些元素为精灵。

    👸小媛:精灵,好听的名字。 😢

    🐰小C:你看下面的代码。

    import pygame
    
    bg=pygame.image.load(r'E:\2dsrc\src\img\bg.png')
    hero=pygame.image.load(r'E:\2dsrc\src\img\hero1.png')
    enemy=pygame.image.load(r'E:\2dsrc\src\img\enemy1.png')
    enemy_boom=pygame.image.load(r'E:\2dsrc\src\img\enemy1_down1.png')
    bullet=pygame.image.load(r'E:\2dsrc\src\img\bullet1.png')
    
    heroX=250
    heroY=680
    
    pygame.init() 
    screen=pygame.display.set_mode((600,800))
    pygame.display.set_caption("这是一个飞机游戏")
    
    while True:
        screen.blit(bg,(0,0))
        screen.blit(hero,(heroX,heroY))
        
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                exit()
    

    🐰小C:上面的代码 pygame.image.load 就表示使用 pygame 中的 image 工具的 load 功能,load 就是加载图片的意思;在 load 方法中传入图片的路径就可以了,我在这里分别加载了 5 个图片,一个是背景图、一个是主角图、一个是敌人图、一个是敌人被击中后的爆炸图、一个是子弹图片。

    👸小媛:我电脑上你是放在同样的路径下吧?

    🐰小C:是的,如果没有图片可以私聊 bit 哥(博主 https://blog.csdn.net/A757291228),他会统一发的。

    👸小媛:明白。

    🐰小C:我们接着看 screen.blit(bg,(0,0)) 代码和 screen.blit(hero,(heroX,heroY)) 代码,这两句代码都是用 blit 方法,blit 方法 是 screen 的功能之一,也就是可以在屏幕中画出我们加载的图片;blit 的第一个参数是图片参数,第二个参数是整个屏幕的 x 和 y 坐标,也就是从哪里开始画;x 越大越靠右,y 越大越靠下。

    👸小媛:那为什么我运行了代码后是一片黑屏? 😭

    🐰小C:那是因为我们需要刷新,每次循环完我们都需要刷新整个界面,否则是不会呈现画完的效果的。你在 while 循环最后加一个代码,pygame.display.update(),就如下所示。

    import pygame
    
    bg=pygame.image.load(r'E:\2dsrc\src\img\bg.png')
    hero=pygame.image.load(r'E:\2dsrc\src\img\hero1.png')
    enemy=pygame.image.load(r'E:\2dsrc\src\img\enemy1.png')
    enemy_boom=pygame.image.load(r'E:\2dsrc\src\img\enemy1_down1.png')
    bullet=pygame.image.load(r'E:\2dsrc\src\img\bullet1.png')
    
    heroX=250
    heroY=680
    
    pygame.init() 
    screen=pygame.display.set_mode((600,800))
    pygame.display.set_caption("这是一个飞机游戏")
    
    while True:
        screen.blit(bg,(0,0))
        screen.blit(hero,(heroX,heroY))
    
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                exit()
        pygame.display.update()
    

    👸小媛:出来了耶。

    13 控制角色移动

    🐰小C:那么接下来我们来控制这个飞机左右移动吧。

    👸小媛:期待。

    🐰小C:我们创建一个函数,用来检测用户是否按下了上下左右。

    import pygame
    
    bg=pygame.image.load(r'E:\2dsrc\src\img\bg.png')
    hero=pygame.image.load(r'E:\2dsrc\src\img\hero1.png')
    enemy=pygame.image.load(r'E:\2dsrc\src\img\enemy1.png')
    enemy_boom=pygame.image.load(r'E:\2dsrc\src\img\enemy1_down1.png')
    bullet=pygame.image.load(r'E:\2dsrc\src\img\bullet1.png')
    
    heroX=250
    heroY=680
    stepX=0 #此部分新增
    stepY=0 #此部分新增
    
    pygame.init() 
    screen=pygame.display.set_mode((600,800))
    pygame.display.set_caption("这是一个飞机游戏")
    
    
    def keydown_envent(event,stepX,stepY):#此部分新增
        if event.key == pygame.K_RIGHT:
            stepX=5
        elif event.key == pygame.K_LEFT:
            stepX=-5
        elif event.key == pygame.K_UP:
            stepY=-5
        elif event.key == pygame.K_DOWN:
            stepY=5
        return stepX,stepY
    
    
    while True:
        heroX=heroX+stepX
        heroY=heroY+stepY
        
        screen.blit(bg,(0,0))
        screen.blit(hero,(heroX,heroY))
    
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                exit()
            if event.type==pygame.KEYDOWN:#此部分新增
                stepX,stepY=keydown_envent(event,stepX,stepY)
        pygame.display.update()
    

    🐰小C:以上代码我在新增部分添加了注释,主要添加了一个 keydown_envent 方法用来检测按下事件后的处理。我们可以看到在 for 循环事件遍历中,使用 if event.type==pygame.KEYDOWN: 检测用户是否按下键,随后我们通过这个事件传入到 keydown_envent 方法中做处理,判断用户按下的是否是右键 K_RIGHT、左键 K_LEFT、上键 K_UP、下键 K_DOWN。如果是右键那么就增加下次绘制图片的 x 坐标值,下键就增加 y 坐标值这样依次类推,所以在 while 循环中就有了下面这个代码。

    heroX=heroX+stepX
    heroY=heroY+stepY
    

    👸小媛:感觉有点像那个在书上画画,r案后翻动页码每次看到图都不一样,画上去的人物就可以动了。

    14 增加敌机

    🐰小C:是的,就是这个原理,我们接着添加敌人。

    import pygame,random
    
    bg=pygame.image.load(r'E:\2dsrc\src\img\bg.png')
    hero=pygame.image.load(r'E:\2dsrc\src\img\hero1.png')
    enemy=pygame.image.load(r'E:\2dsrc\src\img\enemy1.png')
    enemy_boom=pygame.image.load(r'E:\2dsrc\src\img\enemy1_down1.png')
    bullet=pygame.image.load(r'E:\2dsrc\src\img\bullet1.png')
    
    heroX=250
    heroY=680
    stepX=0 
    stepY=0 
    
    enemy_speed=2#此部分新增
    enemy_objs=[]#此部分新增
    
    pygame.init() 
    screen=pygame.display.set_mode((600,800))
    pygame.display.set_caption("这是一个飞机游戏")
    
    
    def keydown_envent(event,stepX,stepY):
        if event.key == pygame.K_RIGHT:
            stepX=5
        elif event.key == pygame.K_LEFT:
            stepX=-5
        elif event.key == pygame.K_UP:
            stepY=-5
        elif event.key == pygame.K_DOWN:
            stepY=5
        return stepX,stepY
    
    def enemy_show(enemy_objs,startY=-40):#此部分新增
        if len(enemy_objs)<5:
            while len(enemy_objs)<5:
                enemy_X=random.randint(0,500)
                enemy_pos=[enemy_X,startY]
                screen.blit(enemy,enemy_pos)
                enemy_objs.append(enemy_pos)
        else:
            i=0
            for pos in enemy_objs:
                screen.blit(enemy,pos)
                enemy_objs[i]=[pos[0],pos[1]+enemy_speed]
                i=i+1
        return enemy_objs
    
    while True:
        heroX=heroX+stepX
        heroY=heroY+stepY
        
        screen.blit(bg,(0,0))
        screen.blit(hero,(heroX,heroY))
        enemy_objs=enemy_show(enemy_objs)  #此部分新增
    
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                exit()
            if event.type==pygame.KEYDOWN:#此部分新增
                stepX,stepY=keydown_envent(event,stepX,stepY)
        pygame.display.update()
    

    🐰小C:以上代码中添加了一个 enemy_show 方法,enemy_show 方法传入了一个 enemy_objs 列表用来记录创建的敌人对象,enemy_show 方法接收两个参数,还有一个是默认的 Y 坐标。在 enemy_show 中,如果敌机数量小于 5 个,那么就直接使用 while 循环进行创建,并且把创建对象的 X 和 Y 值存储到 enemy_objs 列表中,之后我们只需要控制每个敌机的位置坐标就可以控制 敌机移动了。

    if len(enemy_objs)<5:
            while len(enemy_objs)<5:
                enemy_X=random.randint(0,500)
                enemy_pos=[enemy_X,startY]
                screen.blit(enemy,enemy_pos)
                enemy_objs.append(enemy_pos)
    

    👸小媛:你的意思是控制敌机移动只需要控制记录出现的坐标点进行绘制,那么就等于敌机在移动? 😭

    🐰小C:是的。如果已经创建了 5 个 敌机,n阿么只需要根据他们的位置坐标进行 y 轴坐标的增加就可以了,也就是 enemy_show 方法中 else 部分的内容。

    def enemy_show(enemy_objs,startY=-40):#此部分新增
        if len(enemy_objs)<5:
            while len(enemy_objs)<5:
                enemy_X=random.randint(0,500)
                enemy_pos=[enemy_X,startY]
                screen.blit(enemy,enemy_pos)
                enemy_objs.append(enemy_pos)
        else:
            i=0
            for pos in enemy_objs:
                screen.blit(enemy,pos)
                enemy_objs[i]=[pos[0],pos[1]+enemy_speed]
                i=i+1
        return enemy_objs
    

    👸小媛:唔,原来如此,那么 enemy_speed 加多少就表示速度了吧?我看你在前面定义这个值是 5。

    🐰小C:是的。你可以运行代码试一试。

    👸小媛:敌机下来了呢,真棒。 😎

    15 加子弹

    🐰小C:我们现在开始添加子弹吧,其实子弹添加也很简单,只需要知道我们这个主角的位置,然后使子弹在这个位置头部绘制,绘制后每次刷新后的距离都 -10 这样子弹就可以飞上去了呢。

    👸小媛:是的,我感觉会写了。 😎

    🐰小C:我们接着看代码吧,我们设置空格键就是子弹发射按键,这个时候我们在事件方法中添加空格事件的响应,然后绘制出一个子弹就可以了。

    import pygame,random
    
    bg=pygame.image.load(r'E:\2dsrc\src\img\bg.png')
    hero=pygame.image.load(r'E:\2dsrc\src\img\hero1.png')
    enemy=pygame.image.load(r'E:\2dsrc\src\img\enemy1.png')
    enemy_boom=pygame.image.load(r'E:\2dsrc\src\img\enemy1_down1.png')
    bullet=pygame.image.load(r'E:\2dsrc\src\img\bullet1.png')
    
    heroX=250
    heroY=680
    stepX=0 
    stepY=0 
    bullets_pos=[]#此部分新增
    enemy_speed=2
    enemy_objs=[]
    
    pygame.init() 
    screen=pygame.display.set_mode((600,800))
    pygame.display.set_caption("这是一个飞机游戏")
    
    
    def keydown_envent(event,stepX,stepY,hero_pos):
        bullet_pos=[]#此部分新增 
        if event.key == pygame.K_RIGHT:
            stepX=5
        elif event.key == pygame.K_LEFT:
            stepX=-5
        elif event.key == pygame.K_UP:
            stepY=-5
        elif event.key == pygame.K_DOWN:
            stepY=5
        elif event.key == pygame.K_SPACE:#此部分新增
            bullet_pos=[hero_pos[0],hero_pos[1]+10]
        return stepX,stepY,bullet_pos
    
    def enemy_show(enemy_objs,startY=-40):
        if len(enemy_objs)<5:
            while len(enemy_objs)<5:
                enemy_X=random.randint(0,500)
                enemy_pos=[enemy_X,startY]
                screen.blit(enemy,enemy_pos)
                enemy_objs.append(enemy_pos)
        else:
            i=0
            for pos in enemy_objs:
                screen.blit(enemy,pos)
                enemy_objs[i]=[pos[0],pos[1]+enemy_speed]
                i=i+1
        return enemy_objs
    
    while True:
        bullet_pos_=[]#此部分新增
        heroX=heroX+stepX
        heroY=heroY+stepY
        
        screen.blit(bg,(0,0))
        screen.blit(hero,(heroX,heroY))
        enemy_objs=enemy_show(enemy_objs)  
    
        i=0
        for v in bullets_pos:#此部分新增 
            bullets_pos[i]=[v[0],v[1]-10]
            screen.blit(bullet,(bullets_pos[i][0]+45,bullets_pos[i][1]))
            distance_b=[bullets_pos[i][0]+45,bullets_pos[i][1]]
            i=i+1
    
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                exit()
            if event.type==pygame.KEYDOWN:#此部分新增
                stepX,stepY,bullet_pos_=keydown_envent(event,stepX,stepY,[heroX,heroY])
                if len(bullet_pos_)>0:
                    bullets_pos.append(bullet_pos_)
        pygame.display.update()
    

    🐰小C:我们在响应按键的方法中添加了响应空格的处理,我们将记录当前主角所在的目标位置 bullet_pos=[hero_pos[0],hero_pos[1]+10],然后做为返回值返回,返回之后判断 bullet_pos_ 接收值后长度是否大于 1,大于则表示已经按下空格,则记录在 bullets_pos 列表中;之后使用循环遍历每个子弹的位置,然后在 Y 轴上减去 一个值即可发射子弹。

    i=0
    for v in bullets_pos:#此部分新增 
        bullets_pos[i]=[v[0],v[1]-10]
        screen.blit(bullet,(bullets_pos[i][0]+45,bullets_pos[i][1]))
        distance_b=[bullets_pos[i][0]+45,bullets_pos[i][1]]
        i=i+1
    

    👸小媛:那 +45 是啥意思呢?

    🐰小C:因为我们的飞机会占据一定宽度,+45 是为了保持子弹在飞机头位置中间进行发射。

    👸小媛:明白了,我的子弹出来了。 😎

    16 添加击中摧毁

    🐰小C:我们接下来开始添加击中摧毁吧。击中摧毁其实就是判断子弹与敌机的距离,我们使用欧氏距离就可以了,编写一个方法。

    def distance(bx,by,ex,ey):
        a=bx-ex
        b=by-ey
        return math.sqrt(a*a+b*b)
    

    👸小媛:不懂怎么办。

    🐰小C:哈哈哈,这个问题不是本篇的内容,不懂公式的大家搜索一下就可以了,或者直接使用这个方法。

    👸小媛:问题不大。

    🐰小C:接着我们在子弹移动时添加距离计算,如果子弹移动后与敌机小于一定距离,那么就在敌机位置显示出爆炸图片就可以了。

    i=0
    for v in bullets_pos:
        bullets_pos[i]=[v[0],v[1]-10]
        screen.blit(bullet,(bullets_pos[i][0]+45,bullets_pos[i][1]))
        distance_b=[bullets_pos[i][0]+45,bullets_pos[i][1]]
        ei=0
        for ep in enemy_objs:#此部分新增 
            if distance(distance_b[0],distance_b[1],ep[0],ep[1])<60:
                screen.blit(enemy_boom,(ep[0],ep[1]))
                enemy_objs[ei]=[random.randint(0,500),-50]
            ei=ei+1
        i=i+1
    

    🐰小C:其实就是移动后,我们去循环每一辆敌机的位置,如果距离达到了我们就在那个位置显示爆炸图片,并且更改这个位置到初始位置重新掉落。

    👸小媛:哈哈哈,可以了。 😎

    🐰小C:那我们这个就做完了,其他内容就不说了。

    👸小媛:行嘞,多谢小C。

    🐰小C:完整代码如下(改动了一下的)。

    import pygame,random,math
    
    bg=pygame.image.load(r'E:\2dsrc\src\img\bg.png')
    hero=pygame.image.load(r'E:\2dsrc\src\img\hero1.png')
    enemy=pygame.image.load(r'E:\2dsrc\src\img\enemy1.png')
    enemy_boom=pygame.image.load(r'E:\2dsrc\src\img\enemy1_down1.png')
    bullet=pygame.image.load(r'E:\2dsrc\src\img\bullet1.png')
    
    pygame.init() #初始化
    screen=pygame.display.set_mode((600,800))
    pygame.display.set_caption("这是一个飞机游戏")
    
    heroX=250
    heroY=680
    stepX=0
    stepY=0
    
    enemy_speed=2
    enemy_objs=[]
    enemy_objs1=[]
    enemy_objs2=[]
    enemy_objs3=[]
    bullets_pos=[]
    bullet_speed=[]
    
    def enemy_show(enemy_objs,startY=-40):
        if len(enemy_objs)<5:
            while len(enemy_objs)<5:
                enemy_X=random.randint(0,500)
                enemy_pos=[enemy_X,startY]
                screen.blit(enemy,enemy_pos)
                enemy_objs.append(enemy_pos)
        else:
            i=0
            for pos in enemy_objs:
                screen.blit(enemy,pos)
                enemy_objs[i]=[pos[0],pos[1]+enemy_speed]
                i=i+1
        return enemy_objs
        
    def screen_border(X,Y):
        #左右屏幕
        if X<0:
            X=0
        elif X>500:
            X=500
        #上下屏幕
        if Y<0:
            Y=0
        elif Y>700:
            Y=700
        return X,Y
    
    def distance(bx,by,ex,ey):
        a=bx-ex
        b=by-ey
        return math.sqrt(a*a+b*b)
        
    def keydown_envent(event,stepX,stepY,hero_pos):
        bullet_pos=[]
        if event.key == pygame.K_RIGHT:
            stepX=5
        elif event.key == pygame.K_LEFT:
            stepX=-5
        elif event.key == pygame.K_UP:
            stepY=-5
        elif event.key == pygame.K_DOWN:
            stepY=5
        elif event.key == pygame.K_SPACE:
            bullet_pos=[hero_pos[0],hero_pos[1]+10]
        print('space:',bullet_pos)
        return stepX,stepY,bullet_pos
        
    while True:
        bullet_pos_=[]
        heroX=heroX+stepX
        heroY=heroY+stepY
        heroX,heroY=screen_border(heroX,heroY)
        
        screen.blit(bg,(0,0))
        screen.blit(hero,(heroX,heroY))      
        enemy_objs=enemy_show(enemy_objs)   
        #enemy_objs1=enemy_show(enemy_objs1,-300)
        #enemy_objs2=enemy_show(enemy_objs2,-600)
        #enemy_objs3=enemy_show(enemy_objs3,-900)
        print(bullets_pos)
        i=0
        for v in bullets_pos:
            bullets_pos[i]=[v[0],v[1]-10]
            screen.blit(bullet,(bullets_pos[i][0]+45,bullets_pos[i][1]))
            distance_b=[bullets_pos[i][0]+45,bullets_pos[i][1]]
            ei=0
            for ep in enemy_objs:
                if distance(distance_b[0],distance_b[1],ep[0],ep[1])<60:
                    print('\n\n\n\n\n\n\n\n\n\n\n\n boom')
                    screen.blit(enemy_boom,(ep[0],ep[1]))
                    enemy_objs[ei]=[random.randint(0,500),-50]
                ei=ei+1
            i=i+1
        
        
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                exit()
            if event.type==pygame.KEYDOWN:
                stepX,stepY,bullet_pos_=keydown_envent(event,stepX,stepY,[heroX,heroY])
                if len(bullet_pos_)>0:
                    bullets_pos.append(bullet_pos_)
          
        pygame.display.update()
        
        
        
    
    展开全文
  • 刀讲小米产品实战

    千次阅读 2019-10-13 17:10:21
    是因为他们只知道小米七字诀“专注、极致、口碑、快”,却不知道怎么。我们进行深度挖掘小米内核,找出小米的制胜逻辑,告诉你为什么小米可以俘获粉丝的心?小米为什么能在短短几年从零做到行业第一?面对OPPO、...

    小米现象的背后,是互联网时代人类信息组织结构的深层巨变,为什么那么多人学习小米模式,却没有成功?是因为他们只知道小米七字诀“专注、极致、口碑、快”,却不知道怎么做。我们进行深度挖掘小米内核,找出小米的制胜逻辑,告诉你为什么小米可以俘获粉丝的心?小米为什么能在短短几年从零做到行业第一?面对OPPO、华为的大力猛攻,小米又是怎么逆袭的?小米做创业、做用户、做品牌、做产品的核心密码到底是什么?

    个人觉得小米的产品做的非常好,这个音频内容和梁宁产品思维30讲一样饱满~墙裂!!! 看评论拿资源。。。

    1.1 雷军做小米第一年的3个生死选择

    一、金句:互联网时代,要想成功,必须要做出爆品,引爆市场的产品和策略。温水你哪怕做到99°C,也没啥用。唯有沸腾之后,才有推动历史进步的力量。

    二、互联网创业必须跳出的三个大坑:

    1、[事]天道酬薪是个坑:找到风口,顺势而为。

    2、[人]存天理灭人欲是个坑:要用人性的方式做团队,不要洗脑。

    3、[产品]不是把事情做多,而是把事情做少:在产品上大刀阔斧做减法,打造爆品。

    三、行动指南:聚焦于一个产品,打造爆品,甚至把一个功能点打爆。

    四、思考题:什么是你觉得创业最大的坑?

    1.2 雷军不花钱做粉丝的一个秘密武器

    一、核心点一:参与感,让用户参与进来研发产品,做营销做传播的一种新式打法。

    二、核心点二:怎么样不花钱做粉丝?

    1、参与式研发:用户模式大于一切工程模式

    2、参与式营销:找到关键节点,让用户参与进来,放大营销

    3、靠优质内容激发参与感:不花钱做粉底,让用户参与是一个巨大的风口,背后有革命性的能量。

    三、思考题:你自己、你身边,是否有哪些公司有不花钱做粉丝的例子?

    1.3 100个铁杆粉丝战略

    一、核心点一:1000个铁杆粉丝理论:创作者只需要拥有1000个铁杆粉丝,就能够生存无忧。

    二、核心点二:怎么像小米一样,让100个铁杆发挥效用,产生战略级的能力?

    1、不是找100个粉丝,而是找100个超级用户:最重要的指标是参与度,要重度参与,有分享就精神。

    2、激励铁杆用户的不是靠钱,而是靠意义、靠特权:

    3、要有用户测试的理念:需要系统性的用户测试方法,灰度测试

    三、思考题:你们公司有没有100铁杆粉丝的运营或测试呢?

    1.4 如何找用户的生死痛点

    一、核心点一:什么是痛点?

    痛点就是用户最痛的需求点。什么叫生死痛点呢?就是这个需要,是用户愿意花钱买的,是用户不花钱买会死的需求点。痛点是我们做爆品的核心基础。

    Eg:小米曾经投过一个项目金额最大的一个公司,叫21克手机,这个手机是做老年人手机的。我们问大家一个问题,如果一个人创业了,而且很资深,团队很牛逼,技术很牛,随着中国手机的崛起,他发现了一个空白点老年人手机

    • 大家想想老年人手机有什么需求?他希望屏幕大一点,电池高一点,然后声音大一点。
    • 我的问题是老年手机是不是痛点?21克做了几年一直没有做起来,后来转型这也算是小米生态链投资里面金额最大的一个,算是个失败案例。
    • 为什么失败呢?老年手机这个品类是个伪通点。我觉得需不需要老家手机?有没有需要?有需要,但是没有人愿意花钱买。为什么呢?因为老年手机他不是一个真的痛点,他有需要但不是痛点,因为在中国老年手机其实约等于二手手机。年轻人在大城市打拼,他用坏的手机有的是回收,大部分人是把这手机让自己的爸妈用,所以说你们记住老年手机这个品类的核心就是我们的二手手机。所以各位听到这个案例,你是不是感觉这个现实很残酷。我想告诉大家,如果你找不到真痛点,你的创业会特别残酷。

    二、核心点二:怎么样找到真痛点呢?而且是找到用户的生死痛点呢?

    1. 要找到产业级的痛点是什么意思呢?就是你要找到很多中国人都需要的一个痛点,我们的学员的产品也会拿过让我看。很多产品,它不是产业级痛点,就是他挖空心思做了一个东西,不是产业级痛点,我见到的最多的都是什么呢?好多人做艺术品,这种比较有创意创新。

    • 找痛点第一要找什么呢?要找大痛点就是大的产业级的痛点,你不要找这种小众的,只有几个人买这个,你说是不是痛点是痛点,但是它不容易产生爆品,甚至来讲很难产生爆品。我们经常说一个全新的品类,要么产生伟大,要么产生死亡,或者说要一步天堂,一步坟墓,其实大部分来讲是走向坟墓,一定要引以为戒。
    • 怎么样找生死痛点呢?其实最重要的核心,你要深度了解用户,甚至要对用户进行画像。从产品的角度我们的用户是分层级的,我们就说我们的目标用户就愿意花钱买东西的用户都可以分好几个层级,比如说目标用户中,最核心的我们叫核心用户,在核心用户里面还有种子用户,他们真的是一个系统,甚至是我们说创始人他的一个信仰。用户到底是男是女,要么做好,要么做这个年轻,要么做男,要么做你就聚焦,特别是我们的种子用户一定要聚焦,甚至把它变成画像,因为如果你想搞定所有的用户,我想提醒所有的用户你都搞不定。

    Eg:小米耳机,现在应该干到全球第一。早期它的一个最重要的产品经理就是雷军,雷军为什么愿意参与耳机的研发呢?是因为雷军是耳机的深度用户,他说他有时候开电话会议,一般光打电话都要打四五个小时,这时候我们讲不可能用手机,贴着耳朵一定要用耳机,雷军有次跟我讲,他说你看耳机,耳机最大的痛点是什么呢?第一个最大的痛点,就是再漂亮的耳机你拿出来都是脏兮兮的团成一团。所以来讲小米做耳机第一个最重要的改革就是把线做升级,用了那种扁平线,因为扁平线不容易打结,而且它专门做了一个缠绕器,而且音质很重要,所以你看这两个痛点都是用户非常非常重要的生死痛点。小米也因为抓住了用户的这两个生死痛点,耳机很快打爆。

    三、思考题:你们公司的核心产品,是不是直击用户的生死痛点呢?

    1.5 千万警惕伪痛点

    一、核心点一:伪痛点,是看起来很痛,但是并没有直击用户内内心,不会产生购买。

    二、核心点二:如何像小米一样找到真痛点,警惕伪痛点

    1、不要进入装逼模式:不要闭门造车,要让用户先试

    2、不要进入专家模式:拒绝行业内思维,从用户出发

    3、丈母娘理论:让你身边的人先试用,测试他们会不会购买

    三、思考题:你们公司有没有伪痛点的产品呢?

    1.6 如何让粉丝变成铁粉

    一、核心点一:提高粉丝的黏性,让粉丝持续有忠诚度,这样公司才会持久

    二、核心点二:有什么方法让粉丝变成铁粉?

    1、产品是1,粉丝是0:要想吸纳铁杆粉丝,产品是王道,要把核心产品做好

    2、要让用户当明星:激发粉丝行为的活动,让用户、粉丝成为明星

    3、克制贪婪:少赚一点,制造用户的强信任,产生价值观认同

    三、思考题:你们公司的产品有没有铁粉?什么是你们把粉丝变成铁粉最大的障碍呢?

    1.7 如何精准用户画像

    一、核心点一:什么是用户画像?即用一句话描述核心用户,用户画像是真实用户的虚拟代表。

    二、核心点二:怎么做好用户画像?

    1、找到种子用户:目标用户-核心用户-种子用户,得种子用户,得天下

    2、找变态用户:产品的变态使用者,很专业,还经常吐槽

    3、要有关键的用户数据,要有大数据

    三、思考题:你们公司有没有变态用户?

    1.8 如何不花钱搞定100万粉丝?

    一、核心点一:先找到100个铁杆粉丝,给小米带来了极大的能量

    二、核心点二:雷军是怎么不花钱搞定100万粉丝的?

    1、找到重度意见领袖用户:种子用户

    2、千万不要把用户当上帝,要把用户当朋友

    3、做好粉丝裂变:核心粉丝引爆铁杆粉丝,再引爆大众粉丝

    三、思考题:你身边有没有不花钱做到100万粉丝的案例?

    1.9 雷军的提醒:没有用户思维必死

    一、核心点一:什么是用户思维?

    从用户出发,一切将纷至沓来。用户可以参与产品所有不好的体现,改进产品。

    回到本质,用户思维就是你用什么样的观念看到用户,什么样的观念看待产品,什么样的观念看到员工跟股东,是一个全新的思考。

    二、核心点二:用户思维到底怎么干?

    1、不要像专家一样思考,要像脑残一样思考

    2、用户思维先要从公司老大干起

    3、要把用户思维变成公司上上下下的信仰

    三、思考题:你知道的最具用户思维的产品是什么?

    1.10 答疑

    用户1,做中小学生眼镜:我的用户痛点是摘掉眼镜,不近视。在满足不了的情况下,怎么找用户痛点?

    解答:不要打品类痛点,要找用户痛点。让用户不近视,摘掉眼镜,这个是品类痛点,整个行业可能都解决不了。要从用户角度找他们的差异化痛点,解决某个单点的痛点,比如预防做的好、检测做的好、服务做的好,等等。

    另外,可以尝试从用户出发,找到其他解决方案,不一定是你现在做的产品,可能是搭配的产品,或者是另一种产品。

     

    用户2,做纯棉T恤衫:如何找用户痛点?

    解答:找用户痛点之前,必须先做聚焦用户,聚焦男生还是女生?线上卖还是线下卖?先找到自己的聚焦用户,再来找痛点。

     

    用户3,做家居产品:我的产品很好,但是没有小米的加持,怎么做爆品?

    解答:小米会给小米生态链提供1-10万的加持,但是从10万-1000万,就要靠自己的产品。爆品还是要回归到产品,不要寄托于抱大腿。产品好不好要让用户自己去判断,不是自己说了算的。测试自己的产品会不会成为爆品,先去测试产品的口碑指数。

     

    用户4,给商超供应凤梨:我接触不到用户,怎么寻找种子用户?

    解答:商超是你的客户,消费者是你的用户,不仅要重视客户,更要重视用户。接触不到用户怎么办呢?先去找100个用户,利用这100个用户产生巨大的力量。

     

    用户5,代理记账业务:代理记账是低频的产品,怎么增加黏性?

    解答:黏性弱,两个问题:1、接触不够高频,可以做更高频的产品,比如合同;2、增加黏性,了解用户,围绕用户做产品开发。3、找100个种子用户。

     

    用户6,做酵素:如何做用户调查,做用户画像呢,我的用户很模糊?

    解答:不是针对所有用户做调查,要找变态用户做调查,也就是搞定最难搞定的用户群。

     

    用户7,LED屏幕的toB企业:我们是toB企业,能够用爆品战略吗?

    解答:爆品的核心没有toB和toC的区别,toB更需要用爆品的打法,爆品就是单品打爆用户,并且产生口碑。

    2.1 雷军的一堂产品经理必修课

    一、单点切入:我们做产品的时候一定要找单点切进去,不要做又大又全,要聚焦做减法,要在单点上做到极致。

    二、怎么才能做到单点切入?

    1、做产品,特别是互联网产品,最害怕的一个词就是“布局”,要单点切入,逐点放大。

    2、要围绕这个单点做快速迭代。

    3、要把这个单点打穿打透,甚至做到世界顶尖级的水平。单点要切的够深,切的够疼才行。

    三、思考题:你身边有哪个产品单点切入特别强?

    2.2 雷军的提醒:打造爆品要避免三个坑

    一、什么是雷军眼中打造爆品的三个坑?

    1、坑一:做小众市场。不要做小众市场,要选风口市场,要选产品足够大的市场,不要做全新品类

    2、坑二:做多做大。不要想着做多做大,要做单品,不要做品类

    3、坑三:态度恶劣。做爆品的态度要足够好,要站制高点。有高品质的态度,才能做出爆品

    二、思考题:以上三个坑,你认为哪个最致命?

    2.3把对手逼死,把自己逼疯

    一、什么是变态的极致?就是性能大幅度提升,但是价格很低。

    二、如何做到变态的极致?

    1、打动用户的内心

    2、变态的性能和品质

    3、超预期

    三、思考题:你身边有什么把自己逼疯、把对手逼死的公司?

    2.4 雷军做爆品有什么独门秘籍

    一、雷军做爆品的独门秘籍是什么?答案就是小米之道。

    1、真善美:要跟用户交朋友,难度系数3星

    2、只做感动人心,价格厚道的产品,难度系数3星半

    3、要么不干,要干就干到极致,要用变态的方式干到极致,难度系数4星

    4、克制贪婪,大幅砍加价率,控制毛利率,用户才能产生强信任,难度系数5星

    二、思考题: 小米之道的四个关键点,你觉得哪个最难?

    2.5 小米为何先做忠诚度再做美誉度

    一、雷军为什么先做忠诚度再做美誉度? 忠诚度背后是用户的强信任,强信任带来的结果就是闭着眼睛买。

    二、如何激发用户的强信任?

    1、产品基本面要好,要极致

    2、不要用商人思维,要用朋友思维对待用户, 不是为了投资回报率,而是为了长期的关系。

    3、用高性价比的流量产品征服客户,一定要让用户体验你的产品

    三、思考题:你身边有没有让你闭着眼睛买的公司或产品?

    2.6 在小米,什么才是好设计

    一、在小米什么才是好设计呢?一剑封喉,抓住设计的本质,围绕用户最最关心的点,释放出来。这个本质点一定要够狠。

    二、小米一剑封喉的内部秘笈:

    1、颜值即正义:中产一代,关心实用,关心性能;中产二代,关注关注颜值,关注设计。

    2、要有撕逼对象:你的产品要有PK对象,因为用户要货比三家,所以一定要有撕逼对象,才能有产品力,颜值力。

    3、设计、颜值,一定要可感知:设计好,一定要让用户感知到。

    三、思考题:你身边有没有一剑封喉的例子

    2.7 小米大幅下跌后再绝地反击的一个内幕

    一、闭着眼睛买,是新零售的本质,是商业竞争最高维度。

    二、怎么做到闭着眼睛买?

    1、狠抓品质:用显微镜看品质

    2、找到品类关键:用望远镜看创新

    3、厚道:坎加价率,克制贪婪

    三、思考题:你身边哪个公司的产品是让你闭着眼睛买的?

    2.8 小米的性价比武器有一个狠招

    一、小米性价比武器的大招:明确的PK对象

    二、如何像小米一样找到强悍的性价比武器:厚道将变成新世界重要的商业价值观。

    1、撕逼对象要选对:在用户已经买单的产品中,找到卖得好的产品撕一下

    2、在核心性能上跟世界顶级产品撕一下:做到变态级,和全球顶级同行PK

    3、找到领先精品的痛点:找到清晰的PK对象,撕撕更健康

    三、思考题:你公司是否有清晰的PK对象?

    2.9 小米如何打造产品逼格

    一、什么是逼格:产品可以被炫耀的存在

    二、如何提升产品逼格?

    1、工艺材质

    2、明星设计师

    3、仪式感:把独特亮点变成仪式感

    三、反思:你的产品有逼格吗?逼格够高吗?

    四、思考题:你觉得什么是提升逼格最大的难题?

    2.10 答疑

    问题1:我是做办公桌椅的,怎么找到像小米一样清晰的产品线定义?

    解答:关键是性价比,解决用户的核心性能需求:无甲醛、定制速度快、好看。

     

    问题2:服装产品的坑有哪些?

    解答:最大的坑:严重缺乏爆品。

    1、不要做小众市场,要做风口市场

    2、做多做大是个坑

    3、要有好的产品态度

     

    问题3:传统行业都适用价格战吗?

    解答:不做价格战,做性价比,性价比是绝杀。用户要的是好产品,不是低价格。雷军做小米的独门秘籍:克制贪婪。

     

    问题4:如果行业内标准已经极其清晰,如何逼死对手呢?

    解答:把对手逼死,把自己逼疯。要有极致的产品点,在一个单点上做到强悍。

     

    问题5:什么样的设计才是好设计?内部人员和外部粉丝,都无法定夺。

    解答:好的设计,感动人心,用户直接可感知。

     

    问题6:食品行业大幅下跌之后,是提升菜色品质还是种类,绝地反击?

    解答:最重要的是搞定用户。提升菜色品质还是种类,都不是原点,让用户爽。用户关心的是好吃,要围绕好吃战略做爆品。

    3.1从金山到小米:雷军的最大的一个转变

    一、雷军的转变:格式化,清零,归零,从海陆空全面轰炸到单点突破

    二、雷军最大的转变,也是现在做公司需要的最大转变:用户参与式营销

    1、过去是明星为王,现在是粉丝为王

    2、过去是广告为王,现在是口碑为王

    3、员工是粉丝营销的发动机

    三、思考题:你身边哪个品牌的粉丝营销做得最好,好在哪?

    3.2 雷军在营销上最重视、最死磕的一个数据

    一、粉丝参与感,粉丝的信任感,粉丝能不能闭着眼睛买,就看复购率,即用户的重复购买力。

    二、怎么样打造粉丝参与感

    1、开放参与节点:生产、制作、售后、研发,都要开放节点,让用户参与,和米粉交朋友

    2、要有用户流量池:发一个活动,快速到达用户。如网上论坛、线下同城活动、微博、微信公众号、今日头条、抖音、QQ空间

    3、要有内容营销高手:做年轻人喜欢的内容,变成情感联系。情绪是第一生产力

    三、思考题:你做粉丝参与感最大的难题是什么?

    3.3 小米经常上头条背后的一个狠招

    一、小米天天上头条,背后的狠招:抢首发,做第一

    二、怎么干?

    1、抢首发:和一个大平台合作第一次发布

    2、做第一:要做行业第一,做销量第一,第一

    3、借势能:凭自己的能力很难做第一,需要学会借势

    三、思考题:什么是我们公司上头条最大的困难?

    3.4 最强武器:如何开好一个发布会

    一、雷军在金山时期开的秘诀:1、管理好嘉宾,嘉宾准时到;2、人满为患,现场如果100,就放80个椅子。

    二、小米做发布会:把一个PPT做成变态级

    三、发布会很重要,是战略,是爆品的第一营销出口。

    1、发布会的核心是产品,表现形式是PPT

    2、要制造话题

    3、一个成功的发布会,一定要带来成交

    四、思考题:我们开发布会最大的问题是什么?

    3.5 如何让口碑在社会化媒体上快速引爆

    一、 小米的渠道很强,打小米的牌子是不是容易爆啊?从0到10万台,可以靠小米,但是从10万台到100万台,就要靠口碑引爆。

    二、小米内部口碑铁三角:产品是发动机,社交化媒体是加速器,用户关系是关系链

    三、怎么做口碑引爆?

    1、搞定发烧友和意见领袖

    2、擅长上社交头条

    3、制作事件,甚至制造流行

    四、思考题:你身边有哪些口碑裂变的案例呢?

    3.6 小米的危机公关必修课

    一、情绪管理:

    (1)管理自己的情绪;(2)管理用户的情绪

    二、应对危机:

    1、练不生气功,生气容易走形,我们要允许不同的声音

    2、该亮剑的时候要亮剑,用产品传达公司价值观

    3、要有娱乐精神

    三、思考题:如果你遇到个人的危机公关,你能做到不生气吗?

    3.7小米社会化营销的3个内部关键词

    一、怎么样抓住社会化营销的本质:社交货币

    二、社交货币:用社交货币获得家人、朋友和同事等更多好评、更积极的印象,即用社交货币买到情感的东西。能量传播是社交货币的本质。

    三、怎么样传播社交货币

    1、不是做广告,而是做自媒体:让自己成为媒体

    2、说人话

    3、想办法让用户疯传 

    四、思考题:怎么用社交货币提升自己呢?

    3.8 小米在《参与感》里不会告诉你的3个关键

    一、为什么雷军的发布会能刷爆朋友圈,还能让让买买买:雷军的人设清晰,并坚定强化自己的人设。

    二、小米的人设到底是怎么做的?

    1、挖地三尺,比别人多努力5%

    2、有点二,人设不要太高大上

    3、真诚热爱,是引爆粉丝的核心

    三、思考题:我自己的人设是什么,我自己的人设清晰吗?

    3.9 小米新营销部门内部四字真经

    一、四字真经:一剑封喉,在最快最短的时间内击中对方的要害,不给对方反抗的机会。

    二、找到本质,找到关键原点

    1、坚持:找到最能坚持的原点,能够坚持的战略是好战略

    2、死磕到底

    3、团队的创造力:解放团队,激发创造力

    三、思考题:我自己做事情是一剑封喉、三剑封喉,还是十剑封喉呢?

    3.10 答疑

    问题1:在营销活动中,初始用户是至关重要的吗?

    解答:非常重要!!小米单点切入做粉丝,种子用户至关重要。

     

    问题2:社群运营将是近几年的主要趋势吗?

    解答:社群运营是一个重要的工具,社交营销、社交电商是主要趋势,用社交货币放大核心营销。

     

    问题3:如何做用户留存?

    解答:做用户留存,要抓住这个行业用户最最重要的痛点。留存跟复购率有关,复购率跟口碑有关。

     

    问题4:怎么提高用户的复购率?

    解答:产品是1,营销是0,提高复购率需要提高旗舰产品的尖叫点。

     

    问题5:产品品类单一的公司,怎么做流量产品?流量产品的品质和成本如何平衡?

    解答:产品单一的公司更需要流量产品导流,对自己的上下游动刀。流量产品靠的是性价比,用低成本做出高品质。

     

    问题6:市场变化好快,如何快速准确抓住用户关系的那个点呢?

    解答:找到用户的一级痛点,用户不买会死的点。

    4.1 雷军如何降薪挖团队大牛

     

    4.2 雷军的提醒:团队第一,产品第二

     

    4.3雷军跟自己投资公司才讲的挖人一招

     

    4.4小米的“爆扁爽”组织架构到底爽了哪些人

     

    4.5怎么理解小米的合伙人分权制度

     

    4.6小米不靠KPI如何提升执行力

     

    4.7如何让用户来激励团队

     

    4.8核心团队没有温度感必死

     

    5.1雷军经历过的三个大坑

     

    5.2商业模式第一关:风口的猪

     

    5.3小米是如何通过新模式打爆电商的

     

    5.4雷军的痛苦,小米模式的本质,就在一张表里

     

    5.5小米是如何打爆线下门店的

     

    5.6小米的新零售有1个超级武器

     

    5.7什么是小米跟苹果正面撕的真正底气

     

    5.8移动时代商业模式的最大敌人

     

    总结

     

    展开全文
  • 是谁了?

    千次阅读 2010-05-27 20:38:00
    可是当我们遇到批驳的时候怎么办,当你说出你的观点的时候,有些人表示不同意,可是他不是用事实证明你的观点是的,而是直接否定你,没有任何缘由的否定你,你怎么办?我总是遇到这种情况,所以我几乎不与一些我不...
  • 混日子不是你的,根源在这里

    万次阅读 多人点赞 2016-06-22 07:08:06
    程序员经常会干着干着就没劲了,有时一两天觉得没意思,有时十天八天甚至几个月都觉得提不起精神,上班开了电脑不知道干什么,浏览浏览新闻,翻翻朋友圈,看看群里的小伙伴都在瞎逼逼什么,然后就下班了。...
  • Java中实例是什么意思

    千次阅读 多人点赞 2018-01-04 21:46:18
    Java中实例是什么意思?补充:new 一个对象是实例吗? 能举个小例子吗?  new 一个对象是实例吗?对,是实例,你说的没。可以把这个new出来的对象叫做实例,说白了就是这个new出来的“东西”,叫它对象也可以,...
  • SQL注入之显注入

    千次阅读 2019-08-30 16:03:28
    整形显注入建议使用-1来观察页面变化,某些情况下直接输入order by 会报错,这是因为原有语句中已经存在了order by,只需要加上注释符号即可 5、base64变形注入 通过谷歌语法,inurl:.php?id=MTM intext:...
  • [干货分享] 反省我十年开发犯过的

    万次阅读 多人点赞 2016-11-11 01:39:22
    原文链接:... ...反省我十年开发犯过的反省我十年开发犯过的 专注于一个方向平台 框架语言 别为了薪水去管理 不需要那么忙 敲敲敲不要停 主动加入社群 别从网上投简
  • 平时我们在工作在把网站做好后,往往喜欢把404页面忘记在服务器里面进行设置,导致我们在有时候页面进行超链接的时候把链接写了,有时候无意的时候去点击的时候,就出现404错误这样一个页面,搞的我们很无语,一头...
  • 外行人都能看懂的SpringCloud,错过了血亏!

    万次阅读 多人点赞 2018-08-27 09:31:50
    一、前言 只有光头才能变强 认识我的朋友可能都知道我这阵子去实习啦,去的公司说是用Spring...)当然了,我的水平是有限的,可能会有一些理解的的概念/知识点,还请大家不吝在评论区指正啊~~ SpringClou...
  • Java IO流中偏移量是什么意思

    千次阅读 多人点赞 2019-07-18 22:20:11
    文章目录背景示例前置条件使用 FileInputStream 流读取内容参数详解网上的错误解释正确的解释总结 背景 在使用Java的 IO过程中,肯定遇到过偏移量这个概念。...下面就详细解释一下偏移量到底什么意思...
  • tensorflow别字检测

    千次阅读 2018-08-13 17:09:29
    意思就是说一个词出现的概率只与它前面 n−1n−1 个词有关,而不是与它前面所有的词有关,这样极大的减少了统计的可能性,提高了计算效率,这种处理方法称之为 n-gram 模型,通常 nn 取2~3就能得到不错的效果...
  • 记得原来在考试的时候看到一个词组,叫confidence man,想都没想,就选择了自信的男人那个选项,下来后发现是的,一查,是骗子的意思,百思不得其解,这明明是自信的意思啊。也许,这就像中文里心宽体胖中的“胖”...
  • 了?那就越""越勇

    千次阅读 多人点赞 2018-12-02 22:57:09
    选择塑造着你生活的剧本,选择决定了你什么样的事,成为什么样的人。 但,其实大部分的选择都是错误的。因为幼稚、无知、愤怒、焦虑、兴奋等等因素都在扰乱着我们做出正确的判断,要做出正确的判断很难,所以别为难...
  • SPU和SKU都是什么意思

    万次阅读 多人点赞 2019-01-16 07:11:57
    电商的需要厘清两个概念SPU和SKU SPU = Standard Product Unit (标准产品单位)SPU是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。 在商品信息电子化过程中...
  • SEO是什么意思?seo入门者必读

    千次阅读 2017-05-05 10:04:06
    看到许多人在百度知道、百度贴吧甚至等等地方提问:SEO是什么意思?这个时候许多朋友认为这是一个非常奇葩的问题。记得我前两天去深圳一个医院应聘SEO技术支持的时候,我和医院前台说我应聘的职业是SEO,前台两个女...
  • Java里的this到底是什么意思

    千次阅读 2013-11-11 15:41:31
    this代表当前对象的意思。 这个this肯定是用在某个类的方法里吧。呵呵,我们继续往下说。 举个例子: public class persion{ private String name=null; private int age; public void setName(String name){ ...
  • socket是什么意思(1)

    万次阅读 多人点赞 2016-04-12 09:23:54
    也就是说,数据了就了,无法重传。因为 SOCK_DGRAM 所的校验工作少,所以效率比 SOCK_STREAM 高。 QQ 视频聊天和语音聊天就使用 SOCK_DGRAM 传输数据,因为首先要保证通信的效率,尽量减小延迟,而...
  • 小媛:bit 哥,最近有人找我一个网页,但是我不会,300块钱呢。 ????1_bit:啥网页?给你300? ????小媛:吃鸡的网页,赚了300我就可以吃半个月了,下面就是一个示例。 ????1_bit:哈哈哈,我觉得一周你就用完了...
  • @transient 注解注解,什么意思

    万次阅读 2016-11-25 09:52:21
    在网上找的方法是要将这个注解添加到自定义字段的get方法上,这样了之后程序报错,最后试了将该注解添加到定义该字段的头部即可,例如: 即放在实体类的成员变量上部。 [java] view plain copy
  • localdiskto disk to imade from imagepartitionto partition to image from imagecheckimage file disk这些是什么意思? disk 是对硬盘操作项;to disk 硬盘对硬盘克隆 to image 把硬盘内容作成镜像文件 from ...
  • 刷机必看recovery和fastboot是什么意思

    万次阅读 2012-06-13 03:01:55
    在刷机这件湿中你经常会看到recovery的身影,从字面上来看就是【恢复】的意思,大家可以直接把recovery当作一个【刷机界面】。一般某些手机的刷机和提ROOT也需要recovery的刷新。 再说一下recovery 几个主要的功能...
  • c#里namespace是什么意思

    千次阅读 2013-01-22 22:50:59
    (呵呵,以前选择题养成的习惯,凡是这样问的答案就是!不 过原因是说不出来的了!) 真的上面这个程序,先开始看我也以为是正确的,后来才知道。。。,唉,看来还是要多看 书的...
  • 如果不到,并不是内卷受害者的,而应该想想是谁提供了这个内卷斗兽场。 举个反内卷的例子吧。那是我大一的时候,距现在四五年了,那时候我甚至还没有听过“内卷”这个词,却无意间完成了一件反内卷的标准案例。...
  • 为了完成月入 3W 的目标,我都了哪些准备?

    万次阅读 多人点赞 2018-10-31 08:11:50
    好吧,考验一下你,你知道女孩的意思是?如果你知道,那么恭喜你——读书的重要性就在于此。如果你不知道,赶快加我微信号:qing_gee,让这个读书人来告诉你。 综上,完成月入三万的目标可以实现吧?
  • 简单说 用CSS一个魔方旋转的效果

    万次阅读 多人点赞 2017-07-15 04:47:41
    解释我们要这样的效果,重点在于怎么把6张图片,摆放成魔方的样子,而把它们摆放成魔方的样子,重点在于用好CSS的transform,这是非常重要的,好的,我们先拼出一个魔方的样子。 效果图 代码(代码比较长,朋友...
  • 这是一个历史问题,因为C#的数据和C++的数据布局方式有很大的不同,然而如果在P/Invoke和COM Interop当中,又必须要...MarshalAs这个属性很难用,很容易用,用好需要对C#、C++和COM数据的布局方式有一定的了解才能
  • 关于git push分支的问题

    千次阅读 2016-11-10 16:02:53
    但今天碰到一个问题,就是我在B分支下了一个动作,git push origin A,很蛋疼吧,本来应该是git push origin B的。与是我第一反应就是,会不 会把当前分支,也就是B分支推到远程A分支上了,这样那就麻烦了。  ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 233,379
精华内容 93,351
关键字:

做错的意思