竹笋

首页 » 问答 » 常识 » 写给设计师的趣味编程指南6Proces
TUhjnbcbe - 2021/8/16 0:05:00

上节提到,循环语句可以让某段代码反复执行,如果我们用一根线条来去类比程序的执行流程,它就像其中打圈的部分。而后面介绍的条件语句,则会使程序创建多个分支,呈现树根一样的形态。

这节主要展示条件语句if的特性,同时辅以多个知识。你会了解到如何使用逻辑运算符,关系运算符,以及keyPressed事件。

下面先铺垫有关数据类型以及关系,逻辑运算符的基础知识。

数据类型boolean,char,String数据类型含义作用int整形储存整数数据float浮点形储存小数数据char字符类型储存字符string字符串类型储存字符串bool布尔类型保存true值或false值

前面提到的int,float可以保存数值数据。但显然是不够用的。例如我们想储存一些中文或是英文字符,就需要用到char和String。

代码示例(6-1):

voidsetup(){chara=x;Stringb=words;println(a);println(b);}

控制台输出结果:

对照上面的示例。char是一种用于存储单个字符的数据类型。赋值时,字符必须带上单引号,以此与变量名区分开来。而对String类型进行赋值,字符则需要使用双引号。它可以比char存储更多的字符信息。假如我们希望在程序中储存地址,对话,人名等信息,就可以考虑用String。

既然String存储的信息比char更多,那能否直接将char类型赋值给String类型呢?是可以的,前提是需要写上一个类型转换函数,否则程序会报错。

代码示例(6-2):

voidsetup(){chara=x;Stringb=str(a);println(a);println(b);}

控制台输出结果:

这里的str(),就是类型转换函数。它能够将char类型转换成String类型。

连接字符串

String类型有一个特殊的用法,使用“+”号可以将两个字符串连接起来。

代码示例(6-3):

voidsetup(){Stringa=words1;Stringb=words2;Stringc=a+b;println(c);}

控制台输出结果:

当我们希望将多个文本信息组装在一起,就可以考虑+号。

boolean类型

下面介绍另一种数据类型-boolean。它能存储的东西非常少,只有两个值,true(真)与false(假)。就像抛一个没有厚度的硬币,要么正面,要么反面。非黑即白,没有中间状态。布尔类型会与后面提到的if语句结合得非常紧密,根据true值或false值,可以决定某些语句是否执行。

先看一个有关boolean的例子

代码示例(6-4):

voidsetup(){booleana=true;booleanb=false;println(a);println(b);}

在Processing的控制台中,会输出变量a,b对应的布尔值。当然,除了用true,false来代表真假值之外,程序中还可以用数字来进行赋值。

代码示例(6-5):

voidsetup(){booleana=boolean(1);booleanb=boolean(0);booleanc=boolean(3);println(a);println(b);println(c);}

控制台输出结果:

boolean()是一个类型转换函数。所有“非0”的整形数据,都会转换成true值。而当数字为0,则会转化成false值。boolean()转换函数中不能写小数。假如写成boolean(3.2)会出现报错的情况。

关系运算符与逻辑运算符号

在程序中不仅能做加减乘除的运算,还有一些我们意想不到的运算方式。

关系运算符

像加减乘除这类运算符,最终返回的结果都是数值。而关系运算符,返回的则是布尔值。

关系运算符含义调用方法==等于a==b!=不等于a!=b大于ab=大于等于a=b小于ab=小于等于a=b

代码示例(6-6):

voidsetup(){inta=1;intb=2;println(a==b);println(a!=b);println(ab);}

控制台输出结果:

顾名思义,关系运算符就是用作比较左右两边的关系,非常浅显易懂。当条件成立的时候,就返回ture值,不成立则返回false值。其中唯一要注意的是“==”的写法,必须写两个等于号才是关系运算符。只写一个就成了赋值“=”符号。

逻辑运算符

接下来轮到介绍逻辑运算符,它返回的一样是布尔值。并且有三种类型:与,或,非。

逻辑运算符含义调用方法与ab

或a

b!非!a

使用运算符时,只有当表达式两边都为真时,返回的才会是true值。当其中一边为假,又或是两边都为假,返回的会是false值。

运算符的满足的条件则宽松一些,只要其中有一边为真,返回的就是true值。两边为假,返回的就是false值。

!运算符的作用是取反。它需要直接写在表达式前面,而不存在需要比较左右两边的情况。若原有的表达式为真,使用后返回的结果则为false。若原来为假,返回的结果则为true。

代码示例(6-7):

voidsetup(){println(truetrue);println(truefalse);println(falsefalse);println(true

true);println(true

false);println(false

false);println(!true);println(!false);}

控制台输出结果:

条件判断语句if

前面提及的概念都比较抽象。似乎也很难想通,关系运算符与逻辑运算符具体能有何作用。其实只要放在图形创作的语境下去理解,一切都会非常直观。这节的主角终于来了,那就是if语句。

下面是if语句的一般调用方式:

if(表达式){}

在没有学习if语句之前,写在程序中的语句,都是必须执行的,没有选择的机会。而使用了if语句后,在执行前需要先判断表达式的值。当表达式的布尔值为true的时候,大括号内的代码则会执行,否则会跳过。

代码示例(6-8):

voidsetup(){if(true){println(1);}if(32){println(2);}if(false){println(3);}if(32){println(4);}}

控制台输出结果:

你可以通过以上的输出值,看到哪些语句被真正执行,它们都与表达式的布尔值密切相关。

if语句控制图形的显示与隐藏

现在我们可以不看黑乎乎的控制台了,尝试用if实现些简单的图形效果。

代码示例(6-9):

voidsetup(){size(,);}voiddraw(){background(32,48,65);if(mouseXwidth/2){fill(3,,);noStroke();ellipse(width/2,height/2,,);}}

将鼠标的位置的判断写在if中,就能影响后续的语句是否执行,从而达到控制图形显示或是消失的效果。

if语句的扩展-else与elseif。

if语句只有在满足条件时,才会执行大括号中的代码。上例表达式的条件是mouseXwidth/2,所以鼠标一旦移到屏幕右方,就会显示圆形。假如我们希望鼠标移到屏幕左方出现的是另一个图形。应该怎么办?需要多写一个if语句?

大可不必,如果两个条件之间是非此则彼的关系,那直接用else会更方便。

调用形式:

if(条件){语句1;}else{语句2;}

满足条件时,执行语句1。不满足则执行语句2.

代码示例(6-10):

voidsetup(){size(,);}voiddraw(){background(32,48,65);noStroke();if(mouseXwidth/2){fill(3,,);ellipse(width/2,height/2,,);}else{rectMode(CENTER);fill(,3,);rect(width/2,height/2,,);}}

这样写就简便多了。除此之外,关于if还有另一种用法,那就是elseif。当我们有更多的条件需要判断时,就可以考虑它。

调用形式:

if(条件1){语句1;}elseif(条件2){语句2;}...elseif(条件n){语句n;}else{语句n+1;}

elseif语句是可以不断叠加。它的执行顺序依然是自上而下,先从条件1开始进行判断。若条件1满足则执行语句1,同时后面的语句都跳过,不执行。当条件1不满足,才会检测elseif中的条件2。若条件2满足,则执行语句2。否则就往复循环,直到执行为止。最后,如果所有条件都不满足,则执行else中的语句。

当然,最后的else也不是必须添加的。如果你不写else,并且所有条件过一遍后,仍不满足,那if中的所有语句都不会执行。

代码示例(6-11):

voidsetup(){size(,);}voiddraw(){background(32,48,65);noStroke();if(mouseXwidth/3){fill(3,,);ellipse(width/2,height/2,,);}elseif(mouseXwidth/3*2){rectMode(CENTER);fill(,3,);rect(width/2,height/2,,);}else{fill(3,,);triangle(,,,,,);}}

这个例子就相当于把屏幕划分成了3块。左,中,右。鼠标横坐标不同,显示的图形也不同。

if的嵌套

if语句是可以嵌套使用的。可以由此组合出更复杂的情况。

代码示例(6-12):

voidsetup(){size(,);noStroke();}voiddraw(){if(mouseXwidth/2){background(,16,0);if(mouseYheight/2){fill(32,48,65);rectMode(CENTER);rect(width/2,height/2,,);}else{fill();rectMode(CENTER);rect(width/2,height/2,,);}}else{background(48,,89);if(mouseYheight/2){fill(32,48,65);ellipse(width/2,height/2,,);}else{fill();ellipse(width/2,height/2,,);}}}

由于在第一层ifelse的两个分支里,写入了不同的背景颜色。所以鼠标左右位置变化,就会直接影响背景色。后面在两个分支内,又分别写入了一个ifelse。通过多重状态的组合,就相当于将程序划分成了4个区域,4种状态。

if语句与取模运算

这里介绍一个比较巧妙的用法。它在for循环中使用频率非常高。过去我们一直通过for循环的“i”值,来影响绘图元素的部分参数。例如画一排圆,就需要用到“i”值来确定位置坐标。除此之外,我们其实可以对这个“i”作一些判断。比如进行取模运算(相当于求余数)。根据余数数值的不同,结合if语句就可以对大量元素进行分组处理。下面的例子中,当“i”为偶时,元素的填充色便设置为白色。否则(奇数时),填充色则为黑色。

代码示例(6-13):

voidsetup(){size(,);noStroke();}voiddraw(){background(,,);intnum=10;floatw=mouseX/10;for(inti=0;inum;i++){if(i%2==0){fill();}else{fill(0);}rectMode(CENTER);rect(width/(float)num*(i+0.5),height/2,w,);}}KeyPressed事件

现在相信你已经理解if的特性了。但要让它更好玩,你还需要用到后面介绍的一些编程概念。接着要介绍的,就是keyPressed事件。

前面与程序发生交互,基本上都是靠鼠标坐标mouseX,mouseY来实现的。虽然灵活,但局限性也很明显。当我们想通过鼠标位置来做选择的时候,就得写许多许多的if。在还没掌握如何写一个按钮控件的情况下。用键盘来做交互才是最明智的方式。

keyPressed是与键盘相关的事件。它和setup,draw一样。在程序中已经事先定义好。你只需要把它的结构写进去,就能直接调用。

调用格式:

voidkeyPressed(){}

keyPressed可以暂且理解为与setup,draw是“同级”的。它独立于setup,draw之外。当你按下键盘上的按键,keyPressed中填写的语句才会被执行。

下面先通过一个示例,理解keyPressed对程序流程的影响。

keyPressed的运行流程

代码示例(6-14):

voidsetup(){println(frameCount+:setup);}voiddraw(){println(frameCount+:draw);}voidkeyPressed(){println(frameCount+:keyPressed);}

代码说明:

运行程序后,记得在键盘上任意按下一些键,然后关闭程序,查看控制台的输出

这里主要观察各个结构的执行顺序,其中的frameCount可获取程序当前已运行的帧数。

在控制台往下翻,寻找带有“keyPressed”的字符串。它的输出位置,取决于你的按键时间。在这个例子中就表示,程序运行到90帧,就触发了按键事件。

通过观察frameCount,不难发现keyPressed事件是在draw后才执行的。

这里的“+”代表链接前后两个字符串。前面的frameCount尽管是整形数据,但在P5中会默认先将它转化成字符串类型,再作链接。最终输出到控制台上。

keyPressed获取按键键值

keyPressed不仅能判断你何时按下按键,通过获取key的值,还能知道具体按了哪个键。

代码示例(6-15):

voidkeyPressed(){if(key==1){println(1);}if(key==2){println(2);}if(key==3){println(3);}if(key==a){println(a);}if(key==s){println(s);}if(key==d){println(d);}}

上面例子对数字键1,2,3,以及字母a,s,d添加了按键检测。当你按下这几个键。就会在控制台输出对应的字符。key是系统定义好的,它会自动获取你按下的键值。所以若想了解key是否为某个值时,判断条件就需要写成if(key==某值)。当你想检测的是数字键或是字母键,只要在数字或是字母的基础上加单引号即可。

keyPressed控制图形

前面通过鼠标的位置,来控制图形的显示或是隐藏。现在可以改用keyPressed试试。

代码示例(6-16):

booleanshow;voidsetup(){size(,);}voiddraw(){background(32,48,65);if(show){fill(3,,);noStroke();ellipse(width/2,height/2,,);}}voidkeyPressed(){if(key==1){show=true;}if(key==2){show=false;}}

绘图函数不能写在keyPressed中,只能通过创建一个布尔变量来作为中介。keyPressed先影响布尔变量的值。从而draw函数中的if语句再根据此值来决定显示与否。

有关keyPressed的用法先介绍到这里。后面会有更多的篇幅去深入理解各种事件。

条件控制语句switch

条件控制语句不只有if。if语句还有一个兄弟,那就是switch。

写法格式:

switch(表达式){case常量表达式1:语句1;break;case常量表达式2:语句2;break;....case常量表达式值n:语句n;break;}

switch后需要写一个表达式,后面的case语句写的是这个表达式值可能出现的条件。当此值满足条件,对应的语句就会执行。

case可以叠加多个,并且后面必须填写常量。

需要在每个case的末尾都加上break,这是一个固定写法。代表跳出语句。

若是不加break,则break后的下一个case语句,会直接执行。

switch和if非常的相似,那何时用switch,何时用if?可以对照前面的例子(6-15),并且熟悉一下switch的用法

代码示例(6-16):

voidkeyPressed(){switch(key){case1:println(1);break;case2:println(2);break;case3:println(3);break;casea:println(a);break;cases:println(s);break;cased:println(d);break;}}

用switch语句来判断键值,比起用if更简洁直观。

当程序需要处理多个分支,并且需要判断的都为常量值时,可以考虑使用switch。

switch语句中的case要求的是常量,一般不能进行逻辑判断。如果内层的判断条件是诸如“x5”之类的,就不能使用switch,而是需要考虑if语句。

switch的扩展

switch和if类似。if当中的else,只有在前面的条件都不满足时,才会执行其中的语句。在switch中与之相对应的就是default。它总是放在最后。

写法格式:

switch(表达式){case常量表达式1:语句1;break;case常量表达式2:语句2;break;....case常量表达式值n:语句n;break;default:语句n+1;}

default后无需加上break语句。

End

关于条件控制语句就介绍到这里。下节将会介绍加载文字图片的方法。这些知识点将与if糅合到一起,你可以从零开始制作一个文字冒险游戏!

Wenzy

1
查看完整版本: 写给设计师的趣味编程指南6Proces