注意!!本文字数较多!都是干货!

很多初学者都会遇到各种各样的问题,比如下面这些类型的:

1、只会像高中一样跟着课程学习

2、怎么可以脱离课本和教学视频自己编写一个小项目?

3、停于理论,不知道如何实战

4、就算跟着教程安装软件,搭配环境几乎每一步都会有这样那 样的错误

5、知识遗忘得快,理论没有形成体系,自己计算机的学习只局 限在刷了一些慕课上的题,做了学校要求的实验

6、学完一门课程不知道能干什么

7、畏难情绪严重

8、焦虑、担心找不到工作

首先,看似抽出了很多条的问题,但是我把所有问题都归为一个,那就是 「如何提高编程能力」。

只要编程能力、实战能力提高,上面一长串的问题自然也就不成问题了,更不用担心找工作的问题。

所以今天就来聊聊如何提高编程能力这个话题。

要说提高,总得先明确下什么是 「编程能力」 吧~

一、什么是编程能力

在我看来啊,所谓的编程能力其实说到底就是用代码解决问题的能力,无论是 Leetcode 上的还是现实世界的问题。

能够从问题本身或是业务逻辑提炼出解决方案,并且用代码去实现,编程就是在干这样一件事:

现实世界的问题 -> 抽象出解决方案/建模 -> 计算机语言表达

可以看到,写代码只是最后一步,而我们常常说自己不会写,真的是不会写代码吗?

不会写代码,也许是你连解决问题的思路都没想明白,就是说你的脑海里没有形成「第一步该做什么,第二步该做什么」这样的流程。

这其实是最重要的,编码实现反而是相对简单的事情。

很多大厂,一般都是高级工程师或者架构师进行领域设计、架构设计,初级工程师进行编码实现各种接口。

其实编程的核心就是,你需要在心中对整个实现流程有一个大致的思路,然后用代码去一步步的实现。

在实现过程中,你会遇到很多细节问题,比如数据结构的选择,用 set 还是 list,存储结构的选型,以及如何 bug free的实现。

更进一步,怎样写出高性能、易读、易维护、易扩展高质量的代码,当然这都属于编码能力了。

二、编程究竟难在哪

“编程一点都不难,它只是和你十几年来在学校受的教育格格不入而已。”

第一次看到这句话,是在知乎问题“编程究竟难在哪里?”里一位名叫@ invalid s的高赞回答。

与也是这两年才开始半路学编程的我,所感所悟不谋而合。

从小到大,我们受到的教育终极目的是有一个:考取理想的学校。每一张张考卷都是一个个堆砌起来的知识点:三角函数,解析几何,数列,函数…...

这么多知识点,你需要做的是背下它们,或者说的更高级一点,理解它们。

即便是强调思辨和分析的“文科类”,也可以靠死记硬背答题模板拿分,就连作文都要有统一的标准。

(图片源自网络)

绝大部分人,难以形成系统的学习方法论的意识,以至于很多人一旦脱离试卷,在社会中面对实际问题的时候,完全没有一套行之有效的方法论支撑其解决问题。

而编程的核心,不是编程,不是语法,甚至不是算法或数据结构本身,恰恰是如何分解问题——发现规律建立解决问题模型,映射到合适的数据结构和算法上,最后才根据算法写程序实现。

基于此,卡耐基梅隆大学计算机的一名华裔教授提出「编程思维」这个概念。

(图片源自网络,编程思维的四个组成模块)

他定义编程思维——能够把现实生活中的复杂问题,逐步拆分成可理解的小问题。

1、Decomposition,即拆分。根据已有的知识和经验,把问题拆分。

比如我想喝咖啡,那我可以请求你:“可以帮我倒杯咖啡吗?”但这句话如果想让电脑听懂,我得先告诉它哪个是“杯子”、哪个是“咖啡”、什么是“倒”,然后再告诉它怎么去倒,比如先直走5米,左转75度,左臂下放50度……

现实生活,每一个复杂问题,都是基于解决一个个被拆分的小问题而被解决的。

(图片源自网络)

比如说,超级计算机感觉很复杂最后无非是解决一个带宽问题、一个存储问题;

比如说,解决碳排无从下手,实际上是解决人口、服务、能源、单位能源的碳排放这几个问题。

2、Pattern Recognition,即模式识别。根据新问题和以前解决过的问题的相似性,举一反三琢磨出规律。

假如你需要画100只猫,你会怎么办?找100只猫来挨个临摹?

对于计算机来说,你需要找出猫的“模式”。

(图片源自网络)

你要知道猫是专属的毛,眼睛,尾巴,四条腿等,按照这个“模式”,你才可以“批量”画猫——你不用每次画一个新动物,只需要变换局部特征:黄白条的猫还是黑猫,长尾巴的猫还是短尾猫。

3、Abstraction,即抽象,将问题里涉及的数据,抽象到数据结构(变量,数组,链表等),把数据处理过程可重复执行部分抽象成函数模块。

听起来很复杂吧?这是一个过滤的过程,整个过程你要聚焦重要的关键信息,忽视无用细节,这样才能通过认知问题的核心本质,帮助我们形成解决问题的构想。

比如,当我们看到这一房子,我们看到的是:

(图片源自网络)

但在建筑师的眼中,它可能是这样的:

(图片源自网络)

建筑师通过自己的经验,抽象出房子里面具体的构造。

这一步,我们虽然几乎难以在应试教育的学习方法中获得,但我们能从不断地编程训练中去培养抽象思维。会编程的人,往往能透过一个应用表象,看到背后实现的步骤。

4、Algorithms,即算法。通过循环执行,根据前三步的分析成果,设计步骤,写出算法,从而解决问题。

这一整个过程,我们看到所谓的编程语言和语法,在最后才发挥出作用。

所以当我们觉得学编程难,是因为我们还未从过去根深蒂固的学习习惯中抽离出来,凡是需要打破习惯的事,必是不易的。

就像很多刚刚出国读书的孩子,常常在面对外国老师问出「why」的问题时,马上一种惊慌失措的表情,满脑子想着自己是不是又说错答案了,不知道老师这样问仅仅是为了引导他们拓展思维。

我们真实的社会和生活也是不易的,它们没有标准答案,许多人终其一生没有追寻问题的能力,无法理解世界的复杂。

而编程,是你找出解决方法的能力,把现实问题转换为代码逻辑的能力。只有认清这一点,你才能更好地攻克它。

三、如何提高编程能力

提高编程能力,我自己总结了以下几点:

  • 多实战,做项目,用需求倒逼输入
  • 善用工具,尤其是搜索引擎
  • 看优质资料,特别是经典的计算机书籍
  • 养成自学习惯,提高自学能力
  • 看一些小而美的源码

一、实践

learning by doing

是的,我们都知道编程是一门实践的学科,不动手永远学不会,看懂了和学会了之间差了上万行代码。

或者说:看懂了 + 上万行代码 = 学会(此公式未经证明,纯碎自己拍脑袋想的

刚学完一门语言,想必大家都想做点有用的东西,而不是天天写练习题,但是呢,又不知道从何下手,尤其是 C 语言。

我大一上完 C 语言课,就处于这种状态,但是我隔壁一个室友就不一样的。

他在学习 C 语言的过程中,刚学到动态内存分配(malloc),就去摸索着写贪吃蛇、坦克大战,而且完成度都挺高的,那时候是我们眼里妥妥的大神。

但是大神和我上的课,学的东西都完全一样呀,况且都是上了大学才开始接触编程,为什么差别这么大呢?

以至于那时候,我和学妹一样,常常怀疑自己没有编程天赋,觉得别人天生就是这么强。

这种状态一直持续到大一下,那时候刚学完 Java,而 Java 也比 C 友好了不少,所以总想写点什么。

于是自己就选择写一个类似 QQ 的聊天工具,其实功能就很简陋,就是一个简单的 GUI + Socket 编程,然后在加上用户信息管理就完了。

但是,当我用这个简陋的软件,分别在室友和我的电脑上跑起来并且成功发送消息的那瞬间,我觉得我的编程世界被点亮了。

原来编程这么好玩,原来我也能做一些有趣的东西!似乎找到了一丝编程的感觉,但还说不上到底是什么感觉,毕竟这个程序总共也就几百行。

紧接着,趁热打铁,我又写了一个联机五子棋,实现上依然是 GUI + Socket 传输数据。

但是写这个又遇到了不同的问题,比如棋盘在我的实现里是一个 N*N 的数组,棋子是用对象表示,对象里有坐标、颜色这些属性。

当时我就疑惑了,当一方落子后,该怎么把棋子对象通过网络传输给对方呢,再从网络接收的数据恢复到对象?

起初自己的想法是手动的把对象转换成字符串,然后像聊天工具一样发送给对方,比如:

{x: 12, y: 13, color: black .......}。

这种做法没问题,但是总感觉不够优雅完美,于是上网一番搜索之后发现,原来我想的这个就叫「序列化」和「反序列化」。

并且在 Java 里直接实现 Serializable接口就好了,甚至可以直接使用ObjectOutputStream类就能完成序列化和反序列化对象。

这些问题在现在看来,根本就不是问题,更像是“常识”。甚至序列化这块,还会选择一些兼容性更好、性能更高的协议,比如 Protobuf、Thrift、Avro 等等。

但是对大一时的我来说,在这个过程中不断的遇到问题并且去解决,就是实打实的编程能力上的提高啊。

在我解决掉一系列问题之后,顺利的和隔壁室友用自己写的联机五子棋对战了几局,这个五子棋还支持不少诸如悔棋、暂停、自动判断输赢等功能。

界面风格和下面这个很相似(这是网上搜的)

Java版五子棋

但是由于当时没有存 Github 的习惯,代码在换电脑之后没能留下来。

通过写这些项目,我像打通了任督二脉一样,不是学了什么厉害的算法、也不是高深的设计模式、更没有分布式这样高级的东西。

那是什么呢?

我感觉到编程就好像搭积木一样,基本的函数、库、组件就是一个个的积木块,写的代码就是胶水。

只要我们心中有设计图纸,那就能通过胶水把这些积木搭建成想象的模样,缺少什么积木块,用到的时候再去搜索就行了。

在程序的世界,只要你想,你就能。

这段时间大概是我编程能力提升最快的一个阶段之一。

关于这个五子棋,还有个小插曲:

我写的不是联机五子棋嘛,然后启动的时候输入对方的 IP 和 Port 就能连上对战。

后来,我找了一个在其它城市上大学的高中同学,让他和我一起玩五子棋,但是呢,我傻乎乎的让他用 ifconfig 查看自己 IP 后告诉我,然后我在这边连接。

那个 ip 呢,大概长得像 http://192.168.1.xxx,熟悉的同学都知道,这个就是局域网内使用的 IP 了,并非公网上的 IP。

局域网内的 IP 只能在内网才能使用,所以我用这个 IP 是永远连不上的他的电脑的。

但是那时候我才大一,没学过计网,根本不懂这里面的原理。

为啥我和室友能连上呢(因为在一个局域网)?为啥和其它学校的同学就不行?

别看现在这个东西在我看来是常识,但我那时候是一点计网知识都没,就是硬着头皮学的 Socket 编程,去理解 IP 和 Port。

那是怎么解决的呢?

当然是找谷歌呀!

在网上一番查询后,大概明白了,如果想让不同局域网内的主机进行 P2P 通信,需要一个公网中转服务器辅助进行 NAT 打洞。。。后来,我就又去尝试 NAT 打洞了,其中细节就不再描述了。

其实把我个人编程经历上写这么多,就是想展现我是如何一步步去实践的,遇到了什么问题,又是怎么解决的,把这个过程展现出来。

你看我没学任何计网知识,还不是通过边学边用,完成了网络相关的项目。

所以你离项目只差一个开始。

说到这里,不少同学又会说,我知道要多实践、多动手,道理我都懂。

可我还是不知道如何开始去写一个五子棋、贪吃蛇之类的东西。

那我们以贪吃蛇为例拆解一下,看看是如何从问题到代码的。

首先,贪吃蛇是一个个的节点组成的,节点肯定有横纵坐标吧?一个个的节点组成了一条蛇,那自然应该想到链表吧?

蛇还有什么属性?当前移动的方向

还要食物位置吧?那这些属性在 C 语言中用结构体表达出来就是这样:

typedef struct node{int x;int y;struct node* next;// 单向链表
} SnakeNode;typedef struct snake {SnakeNode *pHead; // 蛇头SnakeNode *pFood; // 食物int direction;  // 方向  0-3 依次表示:上、下左、右...
}

接下要考虑的就是如何去绘制蛇,这个简单呀,就把整个链表从头开始把每个节点打印出来。

每个节点可以是一个圆点,也可以是方形。

那如何让蛇动起来?所谓的动,其实就是不断的将蛇打印出来,然后又清除。

并且不断的根据移动方向更新蛇的位置,只要这个过程够快,快过人眼能够分辨的帧率,那看起来蛇就像是在连续的动一样。

然后这个过程你还要去考虑如何检测碰撞,如何判断吃到了食物,还要随机产生食物。。。这些东西首先你得想清楚逻辑,代码实现其实if、else 、for 就足够了。

做项目的过程总会遇到不会的东西,也会遇到问题。

但是要相信,所有的问题在你之前基本上都已经有人遇到过了,只需要把问题准确的描述出来,然后去搜索引擎上搜就肯定能找到解决的线索。

如果你要等学会所有东西,才去开始做项目,那估计等到本科毕业也没机会。

本科上的就那几门课,Java/C/C++、操作系统、计网、编译原理、离散、数据结构......

可能没有学校会单独开一门课教你 Java Web、Python 写爬虫等等。

学完这些理论课,等到毕业,你会发现,依然好像什么都做不了,所以说,要动手,趁早。

并且理论上,学完一门语言,掌握了数组、链表、 if、for、函数这些编程最基本的概念,就有能力去实现一些诸如贪吃蛇、五子棋、扫雷这样的小玩意了。

这种通过项目去学习,以解决问题为导向的学习才是更加精准和高效的。

课堂上的学习大多数是老师灌输知识、学生记住,然后考试就能拿高分。

实际上有多少知识能转化为解决问题的能力呢?

不好说。

还是那句话,编程就像搭积木,学完基础的,积木块都给你了。

你能搭出房子、车子、还是火箭这全靠自己。

二、善用工具、学会搜索

学会用工具,更要用好的工具。什么是好的工具?

诸如 VSCode,Github、Stackoverflow、Google、知乎、Jetbrains 全家桶都是不错的编程工具,有的提高生产力,有的能解决问题。

都 2020 年了,就不要在机房装着 VC6 写练习题了。

不要等到大一结束了,还没上过 Github,更不知 issue、pull request 为何物。

计算机专业的学生,如果还在用百度搜索技术问题,送给你一段陈皓(左耳朵耗子)前辈的话:

coolshell截图

当然,在没法使用谷歌的情况下,百度还是可以用的,但是这对计算机专业的同学,不应该是一个问题。

很多时候,你把遇到的问题准确的复制到 Google/Stackoverflow 搜索框,大概就能找到答案。

而百度会将你带向培训班的课堂,嘿嘿,刺激不。

3. 看优质资料

现在处于信息大爆炸的时代,互联网上充斥着各种博客、学习资源,这是对学习者最好的时代。但是资源太多,就存在一个选择的问题,在这里我给你几个建议:

1.把网盘里屯的那 500G 视频/资源 删掉,你永远不会去下载来看的

正所谓,收藏从未停止,学习从未开始,当你不再习惯的收藏资源了,你就成长了。最好掌握获取/搜索资源的方式,自己需要什么资源再去搜就完了。而不是让资源白白的占据你的网盘。

2.当需要学习某个东西的时候先去知乎/Google 搜索 「xx学习路线」

然后根据高赞/优质回答,选取大 V 们都提到的资源,这大概是这个领域比较经典的,然后去搜集资料,开始学习。

B站、mooc、网易公开课、Coursera等视频网站上有很多优质免费的课程

答应我,不要再被那些关注送 500 G 学习资源的骗了好吗?资源都在网上公开着,直接打开 B 站就能看,不香么?

学应用框架,官方文档是最适合入门的,并且很多都提供了「快速入门」的指引

比如 Vue、Hadoop、Requests 这些官网的指引都非常的清晰易懂,真的不要再去看七零八碎的博客,博客的定位应该是补充。

少看博客,多看书

很多博客其实就是博主自己读完书,然后复述一遍的笔记,你再去看他的博客那就是等于学二手知识,他的高度就决定了你的高度。

当然有些优秀的博主能够概况性的总结,或者把某些原理讲得特别清楚,这是值得看的。

总的来说,系统性的看书是你成长最快的方式。

4. 最后最后

我精心挑选了Java小白必备的电子书和详细的学习线路图,以及小白到大牛的文档说明。

微信搜索公众号“微编社”,菜单栏即可领取。

每天“游戏式”地学习30分钟能带你轻松掌握“难搞的”Java

编写五子棋程序时如何添加下棋时的音效_干货:如何提高编程能力相关推荐

  1. 【Python3.7】就餐人数:在为完成练习 9-1 而编写的程序中,添加一个名为 number_served 的属性,并将其默认值设置为 0。根据这个类创建一个名为 restaurant 的实例

    # [Python3.7]就餐人数:在为完成练习 9-1 而编写的程序中,添加一个名为 number_served的属性,并将其默认值设置为 0.根据这个类创建一个名为 restaurant 的实例: ...

  2. 程序员提高编程能力万无一失的办法

    那就是去读别人写的代码.读那些你常用的库.编程框架的源代码,读那些你景仰的大牛的源代码,读代码里的测试(测试本身就是一种有效的文档):读代码.改代码.运行代码. 其实,所谓写程序,大部分的时间都是花在 ...

  3. 实现两个数交换python_编写一个程序,用于实现两个数的交换。_学小易找答案

    [判断题]定喘穴定位在胸部 (10.0分) [其它]实现实心等腰三角形图案打印输出. [其它]编写一个程序,用于实现两个数的交换. [其它]实现空心等腰三角形图案打印输出. [判断题]表寒肺热证的代表 ...

  4. 提高计算机编程水平,写程序10大习惯和如何提高编程能力

    如何提高自己的编程能力 1. 扎实的基础.数据结构.离散数学.编译原理,这些是所有计算机科学的基础,如果不掌握他们,很难写出高水平的程序.据我的观察,学计算机专业的人比学其他专业的人更能写出高质量的软 ...

  5. 用c语言写程序求序数的后缀,用C编写mex程序

    用C编写mex程序 大家都知道,matlab是一种解释型的编程环境,也就是说,跟以前的basic一样,是读 一句执行一句的.这样做可以很方便的实现编程过程中的交互,也免去了麻烦又耗时的 编译过程.但凡 ...

  6. 编写python程序、计算账户余额_《易学Python》——第1章 为何学习Python 1.1 学习编程...

    本节书摘来自异步社区<易学Python>一书中的第1章,第1.1节,作者[澳]Anthony Briggs,王威,袁国忠 译,更多章节内容可以访问云栖社区"异步社区"公 ...

  7. ubuntu系统中用c语言编写简单程序

    目录 (一):修改参数提高下载速度 (二):c语言入门编写helloworld (三):在ubuntu系统下编写简单程序 (四):在windows系统下编写简单程序 (五):在ubuntu系统下使用m ...

  8. 编写Java程序,在屏幕上显示带标题的窗口,并添加一个按钮。当用户单击按钮时,结束程序。

    编写Java程序,在屏幕上显示带标题的窗口,并添加一个按钮.当用户单击按钮时,结束程序. package p3;import java.awt.event.ActionEvent; import ja ...

  9. 编写一程序,有2个文本框,在第一个文本框中输入一个整数,当焦点从第一个文本框离开时,第二个文本框将显示这个数的绝对值(使用FocusListener)。

    编写一程序,有2个文本框,在第一个文本框中输入一个整数,当焦点从第一个文本框离开时,第二个文本框将显示这个数的绝对值(使用FocusListener). import javax.swing.*; i ...

最新文章

  1. 关于visualizer的setEnabled()方法何时进行设置成false?
  2. oracle合并查询
  3. iOS开发UI篇—UITableview控件使用小结
  4. yarn add yarn global add
  5. linux未知设备驱动程序,未知Android设备 - linux mint
  6. PowerEdge服务器生命周期控制器:Lifecycle Controller
  7. 用于快速排查Java的CPU性能问题(top us值过高)
  8. Notepad软件的下载安装和使用
  9. 占坑:fullpage.js 在edge浏览器上上下移动鼠标(不滚动滚轮)会翻页的问题
  10. Android数据库更新并保留原来数据的实现
  11. 短视频SDK简单易用——来自RDSDK.COM
  12. changelog 生成  npm install -g conventional-changelog-cli
  13. SAP中公司间过账问题处理实例
  14. Proxmox VE
  15. 自建个人用服务器要多少钱,我想建立一个人网站,像19楼那样的论坛,是自建服务器便宜还是租用服务器便宜...
  16. rmm 一个替换rm 的工具
  17. Angular:解决innerHTML绑定页面内容,sanitizing HTML stripped some content警告处理和富文本背景色样式无法正常显示的问题
  18. 【控制工程基础】二、方框图化简与梅森公式
  19. 【科研技巧】PPT如何导出1000dpi的图片
  20. Linux 学习笔记——二、主机规划与磁盘分区

热门文章

  1. 高效的判断素数---筛选法
  2. Spring boot定制错误数据携带出去
  3. Thymeleaf抽取公共页面片段
  4. 实战上亿数据,如何实现秒查!
  5. 22道Java面试题,看看你会了多少?
  6. struts2教程(5)--请求参数校验
  7. 蓝桥杯-表达式计算(java)
  8. java IO流面试总结
  9. SpringMVC上传文件配置
  10. LeetCode 21合并两个有序链表22括号生成