Project1
标题: 【脚本教程】有关rmxp基础脚本的解释与分析 [打印本页]
作者: wolves 时间: 2014-12-29 00:31
标题: 【脚本教程】有关rmxp基础脚本的解释与分析
本帖最后由 wolves 于 2014-12-29 01:17 编辑
第一次讲ruby,感觉有些紧张。
本篇讲述的主要是ruby基础语法部分,游戏中的内部类和一些方法,都没有涉及到。
由于是我社团ruby讲解的草稿,时间仓促,并且我本人也是大一新生,ruby也大部分是自己看教程学的,可能会有些地方没有讲到。
又考虑到听讲解的人都是软件学院大一的同学,所以说太难的东西(比如正则表达式、API等等)都没有渗透,日后会陆续补齐。
计划在2015新年之前把我编写游戏中的一些经验在此处发布一下,也望大家帮忙指正我编程过程中的一些小毛病。( ^_^ )
作者: wolves 时间: 2014-12-29 00:32
本帖最后由 wolves 于 2014-12-30 00:26 编辑
第一部分 基础篇
第一节 变量与数字的计算
ruby的标识符与语法格式:
ruby的语句换行可以用分号代替。例如:
在写ruby代码的时候注意要把运算符(加减乘除什么的)与标识符(与c语言中标识符条件一样)用空格分开,不光是为了美观,因为有些时候可能会出现错误,比如:
相对于c语言,ruby可以将汉字作为标识符,当然,个人不建议用汉字做标识符,标识符为汉字会影响代码整体美观性。是合法的
注释:
井号(#)是注释的意思
后面的代码不进行运行
ruby中可以进行多行注释
=begin
我是注释
我还是注释
我也是注释
=end
注意,=begin前面和=end前面不能有空格,否则会引发错误。
数字运算:
ruby中常数加减乘除与c语言中一模一样,整数与浮点数运算得到的是浮点数
例如10 / 3 #=>3
10 / 3.0 #=>3.33
10 % 3 #=>1
a = 10
a %= 3 #=>1
10 / 3 #=>3
10 / 3.0 #=>3.33
10 % 3 #=>1
a = 10
a %= 3 #=>1
变量:
上例引入的字母a即为一个变量,进行了自运算,如上自运算写成完整表达式为a = a % 3 ;注意,C语言中的++运算在ruby里是不允许使用的,会出现SyntaxError。
值得注意的是,与c语言不同,多重自运算表达式嵌套时,变量的值只有在第一个表达式发生了改变。举个例子:
上述脚本a的最终的值为8,而c语言中计算结果为0。
c语言把这个式子展开来看就是:
而ruby展开来则是:
这也算是c语言和ruby的一大区别。
ruby中的变量可分为以下5种:
1.局部变量:局部变量只在一个语句中有效,直接用标识符的变量是局部变量,当局部变量没有初始化时,我们能确定该标识符是函数而并非变量(后期会讲什么是函数)。
2.实变量:以@开头的,标识符为名称的变量为实变量,实变量赋值与普通变量相同。实变量的作用范围后期再讲。
3.全局变量:以$开头的,标识符为名称的变量被称作全局变量,全局变量整个工程都可以用。
4.类变量:以@@开头的,标识符为名称的变量称为类变量,类变量使用前必须赋值,讲到class时再讲。
5.常量:在ruby中,我们约定在类(模块)内,方法(函数)外定义的首字母大写(约定所有字母大写)的标识符为该类(模块)的常量,讲到类时会具体讲解。
变量用 变量 = 值 的方法来赋值:$a和a是两个不同的变量,一个是全局变量,一个是局部变量,两个变量是独立存在的,不要把全局变量想象为局部变量的外部定义。
查看变量的值可以用或者例如都是合法的
使用代码后可以将变量的值显示在程序弹出的对话框中。
当然,如果局部变量没有被赋值就用p显示其值的话就会出现错误,因为我们不能确定这个标识符是否是变量。
实变量和全局变量显示时如果没有被赋值,用p显示不会发生错误
会弹窗显示 nil
nil就是未被定义的变量空间
具体是什么后期再讲
习题:
下列对于ruby代码的说法正确的是( )
A.ruby未定义,代码 p ruby 会弹出对话框显示 nil。
B.代码 a=1;$a=2;p a 的输出结果为2
C.$a没有被赋值,代码 c=$a;p c 的运行结果为nil。
D.代码 a=8;a+=a-=a+=2;p a 的运行结果为0
A.ruby这一标识符未定义,因此可以确定ruby是一个函数,然而编译器找不到这个函数,因此用p显示会出现错误。
B.局部变量和全局变量是两个变量,标识符相同的全局变量和局部变量没有相互关系。
C.$a本身是变量,默认值为nil,当用赋值表达式将c赋值为$a的值nil时,c为变量,值为nil,因此p显示出nil。
D.的运行结果为6,翻译过来就是a=(8+(8-(8+2)))。
因此答案选择第三个。
第二节 数组
初始化与赋值:
数组的初始化很简单
或者
当然想要赋值也和c语言一样
也可以这样用迭代的方法赋值:Array.new(10) { |e| e = e }
Array.new(10) { |e| e = e }
注意:数组的第一个值为a[0],从左向右编号。当用p 显示数组的值时会将最后一个值及其前面所有的值组成的数组加上中括号都显示出来
例如刚刚赋值的a显示的是[nil,3]
因为a[0]没有被赋值
所以a[0]的值为nil
数组中所有单元在未赋值时都是nil,数组中的每个单元可以是任意类型的值。例如:数组的一个值是数组时,这个数组是二维的
一维数组调用修改方法是a[0],a[0]=
二维数组其实就是找到一维数组的某个值,把它看做标识符。例如刚刚的数组,我想调用第三个单元的第二个数
数组可以不带中括号,直接用逗号分开将变量赋值。例如:
数组的加减方法:
与c语言不同的是,ruby中的数组可以进行加减运算。
看下面的程序a = [2,3,4]
b = [3,4,5]
p a+b
#=> [2,3,4,3,4,5]
a = [2,3,4]
b = [3,4,5]
p a+b
#=> [2,3,4,3,4,5]
减法是算交集,把与后面数组相交的元素删掉,形成新数组。例如:a=[1,2,3]
b=[2,3,4]
p a-b #=>[1]
a=[1,2,3]
b=[2,3,4]
p a-b #=>[1]
这些是数组的方法,更新之后再具体讲数组的其它用法。
随机数函数 rand(max)
rand(max)函数是rgss内部定义的一个取随机数的函数,其作用是在0到max-1的范围内随机取一个数,默认max与其返回值都是整数
若将 max 设为 nil 或 0 的话,函数将返回一个[0,1)范围内的实数型 Float 随机数。
数组的迭代:
该语句的作用是将数组的每个值逐个代入变量中并执行语句。
第三节 循环语句
在说语句前,我们先来说一下and与or (&& 与 ||)与c语言相似,&&与||都是表达式中的运算符,只不过运算结果不再是1和0,而是true和false。而在如ruby这类解释性语言中,绝大多数真和假都用true和false表示、且和或大多用and和or表示。vb就是个典型的例子。
ruby中的&&与||运算符优先度高于and与or。
用法:
true and true #=> true
false and false #=> false
true and false #=> false
true or true #=> trule
false or false #=> false
false or true #=> true
true and true #=> true
false and false #=> false
true and false #=> false
true or true #=> trule
false or false #=> false
false or true #=> true
注意,true和false跟self类似,在ruby中是伪变量,是不能改变其值的。
深入解读:
Ruby的 && 与 || 与其它语言有些不同。
&&运算法则为:左边为 false 或 nil 时,直接分别返回 false 或 nil ,右边将不会运算。
左边不为false或nil时,返回右边的对象。
||运算法则为:左边为 false 或 nil 时,返回右边的对象。
左边不为 false 或 nil 时,直接返回左边的对象,右边的不会运算。
例如:
puts false && "abc" # => false
puts nil && "abc" # => nil
puts true && "abc" # => "abc"
puts "123" && "abc" # => "abc"
puts false || "abc" # => "abc"
puts nil || "abc" # => "abc"
puts true || "abc" # => true
puts "123" || "abc" # => "123"
#其中
x ||= y
#相当于
x || x=y
x &&= y
#相当于
x && x=y
也可以这样理解:
if defined?(a) && a #defined?(变量)的作用是判断这个变量是否被定义,若被定义则返回被定义的实例对应的类,否则返回nil。
a
else
a = obj
end
puts false && "abc" # => false
puts nil && "abc" # => nil
puts true && "abc" # => "abc"
puts "123" && "abc" # => "abc"
puts false || "abc" # => "abc"
puts nil || "abc" # => "abc"
puts true || "abc" # => true
puts "123" || "abc" # => "123"
#其中
x ||= y
#相当于
x || x=y
x &&= y
#相当于
x && x=y
也可以这样理解:
if defined?(a) && a #defined?(变量)的作用是判断这个变量是否被定义,若被定义则返回被定义的实例对应的类,否则返回nil。
a
else
a = obj
end
for语句:
c语言中循环语句比较常用的是for语句,ruby中也有for循环的方法,不过在ruby中for语句的常规写法为:变化范围可以是一个数组
也可以是一个最小值到最大值的一堆数
例如从1到20依次显示数按顺序显示数组的所有元素
for语句退出循环的方法是break语句
进入下一次,跳过本次循环用的方法是next语句
类似于c语言中的continue
while语句:
while循环语句在ruby中的常规写法为:while 条件语句 do#do可以省略
循环体
end
while 条件语句 do#do可以省略
循环体
end
条件语句满足(值为true)时,执行循环体,否则跳出循环
while语句也可以写成表达式 while 表达式#当while右边的表达式为真时,执行左面的表达式。
表达式 while 表达式#当while右边的表达式为真时,执行左面的表达式。
ruby中的条件语句和c语言中的条件语句一样
但是ruby中条件语句的值为true 或false
c语言中为0或1
true为真,false为假
举个例子c = 5
while c>0
c -= 1
p c
end
#=>4 3 2 1 0
c = 5
while c>0
c -= 1
p c
end
#=>4 3 2 1 0
loop方法:
ruby中的loop方法是一个无限循环(类似于c语言中的死循环)方法,没有跳出条件,只有遇到break语句时才能跳出循环。loop {循环体}
或者
loop do
循环体
end
loop {循环体}
或者
loop do
循环体
end
loop 语句是无限循环循环体
除非遇到break语句否则不跳出循环
在屏幕上显示图片就是用无限循环实现的
可以在以后向大家渗透
case 语句:
ruby中的case语句类似于c语言里的switch()函数,然而ruby中不用break退出case,case语句的基本结构:case 变量
when 对象
表达式
end
...
end
case 变量
when 对象
表达式
end
...
end
当表达式(变量===(when后面的对象))为真时时执行该对象所对应的语句。
上述的 ‘===’ 是一个可以被重定义的操作符,当其未被重定义时,‘===’的功效相当于‘==’
条件语句:
if语句:
基本结构:if 表达式 then#then可以不添加
语句
elsif 表达式
语句
else
语句
end
if 表达式 then#then可以不添加
语句
elsif 表达式
语句
else
语句
end
if语句后的表达式为真,则执行if下的语句,否则判断elsif的表达式是否为真,若elsif语句为真则执行该行下的语句,否则执行else语句(如果有的话)。
if语句也可以写作:
以上为C语言与ruby比较相似的语法,下面说一下与C语言相比的新的循环语句:
unless语句:
unless 语句就是if语句的反语句,基本结构为:相当于:
当然,unless也可以写成表达式 unless 表达式#unless右边的表达式为假时执行左边的表达式
表达式 unless 表达式#unless右边的表达式为假时执行左边的表达式
times语句:
times语句其实是Integer类(数字类)的一个方法,具体用法如下所示:
循环次数.times do
语句
end
或
循环次数.times {#这个’{‘不能换行,否则会出错误。
语句
}
循环次数.times do
语句
end
或
循环次数.times {#这个’{‘不能换行,否则会出错误。
语句
}
until语句:
until语句实际是while语句的反语句,具体用法如下所示:
until 条件 do# do可以省略
反复执行的动作
end
#例如:
sum = 0
until sum > 50
sum += 1
end
print sum
# 以上until循环可以转换成下面的while循环
while !(sum > 50)
sum += 1
end
until 条件 do# do可以省略
反复执行的动作
end
#例如:
sum = 0
until sum > 50
sum += 1
end
print sum
# 以上until循环可以转换成下面的while循环
while !(sum > 50)
sum += 1
end
each语句:
each语句在ruby中的用途很多,下面说下each作为循环的用法:
数组.each { |变量|
循环体
}
哈希表.each{|key,value|
循环体
}
变化范围.each{|item|
循环体
}
数组.each { |变量|
循环体
}
哈希表.each{|key,value|
循环体
}
变化范围.each{|item|
循环体
}
each语句的原理是将| |中的变量迭代为前面对象的每个内容,每代入一次进行一次循环,相较for语句,each语句在ruby中更实用。
迭代器:待更新,具体可以参照该教程,建议通篇看完本教程后再进入解析:
http://blog.csdn.net/classwang/article/details/4692856
循环体控制:
控制循环体的关键字有3个:
break #停止动作,马上跳出循环
next #直接跳到下一个循环
redo #以相同的条件重新执行这一次循环
break #停止动作,马上跳出循环
next #直接跳到下一个循环
redo #以相同的条件重新执行这一次循环
例题:
随机排列一个从1到100这100个数 组成的数组并显示之
在写代码之前我们要先想我们到底应该用什么方法解决这个问题,想到随机两个字就一定要反应到要用rand(max)函数。
下面我写一个例子a=[]#初始化
for i in 0..99#循环赋值,当然,赋值给一个数组一个变化范围时可以用 数组名=[*变化范围]的方法,由于有c语言基础,先用for来演示一下。
a[i]=i+1
end#结束循环
b=[a[0]]#为b[0]赋初值
for i in a#循环a中所有元素
if i==a[0]
#当i等于a[0]时
next#跳过本次循环
end
b=rand(2)==1 ? b+[*i] : [*i]+b#注
end
a=[]#初始化
for i in 0..99#循环赋值,当然,赋值给一个数组一个变化范围时可以用 数组名=[*变化范围]的方法,由于有c语言基础,先用for来演示一下。
a[i]=i+1
end#结束循环
b=[a[0]]#为b[0]赋初值
for i in a#循环a中所有元素
if i==a[0]
#当i等于a[0]时
next#跳过本次循环
end
b=rand(2)==1 ? b+[*i] : [*i]+b#注
end
ruby中是允许用语句的。
只不过问号和冒号两边必须多出空格
温习一下C语言中的这个语句
条件语句为真时执行语句1
否则执行语句2
当然,上面的代码不是最简便的,上例可以简化为如下代码:
a=[*1..99]
for i in 0...a.size
x = rand(a.size - i) + i
t = a[x]
a[x] = a[i]
a[i] = t
end
a=[*1..99]
for i in 0...a.size
x = rand(a.size - i) + i
t = a[x]
a[x] = a[i]
a[i] = t
end
这个是应用的c语言中类似选择法排序的方法,只不过选择交换的两个数变成了第i个数和一个i以后的随机数,从而实现了随机排序的目的。
这段代码可以用作游戏中的 洗牌 脚本。
可以做一些类似于三国杀等等的卡牌游戏。
其中:p [*1..100]
#=> [1,2,...,98,99,100]
p [*1..100]
#=> [1,2,...,98,99,100]
下面说下ruby中的函数
第四节 函数
函数的定义:
函数的定义是从 def 开始到 end 结束。具体的语法:
参数、返回值:
例如把刚刚例题的程序做成函数形式def rand_card
a=[]#初始化
for i in 0..99#循环赋值
a[i]=i+1
end#结束循环
b=[a[0]]#为b[0]赋初值
for i in a#循环a中所有元素
if i == a[0]#当i等于a[0]时
next#跳过本次循环
end
b = rand(2) == 1 ? b + [*i] : [*i] + b#注1
end
return b
end
def rand_card
a=[]#初始化
for i in 0..99#循环赋值
a[i]=i+1
end#结束循环
b=[a[0]]#为b[0]赋初值
for i in a#循环a中所有元素
if i == a[0]#当i等于a[0]时
next#跳过本次循环
end
b = rand(2) == 1 ? b + [*i] : [*i] + b#注1
end
return b
end
这个函数叫做无参函数,也就是说没有传入函数中的参数。其中return语句是把计算之后的结果返回。
函数本身相当于一个算法,return相当于把算法结束,把计算结果输出,赋给前面的变量(如果前面的变量存在)
例如下面的计算一个数的绝对值的函数:
#计算一个数的绝对值的函数:
def abs(x)
if x < 0 # 如果 x 小于 0 的话,
return -x # 结束函数,返回值 -x。
else # 除此之外,
return x # 结束函数,返回值 x。
end # 分歧结束。
end
#计算一个数的绝对值的函数:
def abs(x)
if x < 0 # 如果 x 小于 0 的话,
return -x # 结束函数,返回值 -x。
else # 除此之外,
return x # 结束函数,返回值 x。
end # 分歧结束。
end
像这样的带有参数的函数叫有参函数,在调用的时候可以在函数名后面加上括号,括号内部用逗号表达式将传入变量按顺序写入。函数计算之后我们可以把返回值赋值给一个变量比如:
ruby中的函数和c语言中的函数区别在于ruby不能在函数中声明其它在后面定义的函数。如果c语言函数没学好这块比较难理解
第五节 字符串
字符串的定义:
在ruby里,没有字符的概念,ruby中只有字符串没有字符,字符串也并不是数组,字符串是以双引号或单引号为边界的一堆字符。
字符串的赋值方式:这只是一个空字符串
也可以直接注意:中间夹有空字符的多个字符串字面值会被当作是一个字符串字面值来处理。例如:p "foo" "bar" # => "foobar"
p "foo" "bar" # => "foobar"
内嵌表达式:
其中语句是在字符串中嵌入变量的一个表达式
表达式只能在""的字符串中调用,如果字符串是单引号''的,则这个字符串是不能内嵌表达式的
想在双引号的字符串中显示双引号要在双引号前加\
第六节 哈希表
哈希表初始化:
哈希表也称为关联数组。和数组不同的是,作为取出数值 的主键(相当于数组的编号,第一个是0(ruby里叫附加码)),可以使用任意的对象。 在 {} 符号中间排列多个单元就生成了一个哈希表。a = {"艾力克斯"=>2000, "杰克"=>2003}
a = {"艾力克斯"=>2000, "杰克"=>2003}
但一般我们不这样对哈希表赋值
哈希表的预定义
哈希表的赋值:
例如这就是对哈希表进行赋值(这里用汉字做变量是为了便于理解,以后应用的时候尽量不要用汉字。)
哈希表其实很像数学中的映射,一个主键(自变量)只能对应一个值(因变量),但是一个值(因变量)可能有多个主键(自变量)与之对应。
第二章 结构化的ruby
第一节 类
类定义与方法定义:
基本格式:class 类名
def 方法1名
方法执行内容(函数)
end
def 方法2名
方法执行内容(函数)
end
...
end
class 类名
def 方法1名
方法执行内容(函数)
end
def 方法2名
方法执行内容(函数)
end
...
end
类说直白些就是一个模板,形成新类的过程相当于照着模板新形成一个实例,就和克隆人差不多,不过你可以修改克隆出来的人的各种特点。
什么叫形成新实例呢
就比如一个人
它不是一个数
也不是一个数组
更不是一个字符串
它有它自己的属性例如
名字
身高
体重
...
有自己的方法例如
变身-_-|||
...
形成一个新实例不是形成一个函数,而是形成一个新的对象,也就是说不是单一的字符串,数组,数字,哈希表,而是一堆属性的集合体,就像生活中形成一个鲜活的人物,而不是简单的取个名字。
类的属性:
假如设计一个管理一堆人的各种属性的类class People
def name
return @name
end
def name=(a)
@name = a
end
end
class People
def name
return @name
end
def name=(a)
@name = a
end
end
这个类定义了一个人的名字的类
假如有a、b、c 3个人
名字分别是"小明","小红","小白"
那么我们可以:a = People.new
b = People.new
c = People.new
a.name = "小明"
b.name = "小红"
c.name = "小白"
p a.name #=>"小明"
p b.name #=>"小红"
p c.name #=>"小白"
a = People.new
b = People.new
c = People.new
a.name = "小明"
b.name = "小红"
c.name = "小白"
p a.name #=>"小明"
p b.name #=>"小红"
p c.name #=>"小白"
我们再加一些属性
比如身高class People
def name
return @name
end
def name=(a)
@name = a
end
def height
return @height
end
def height=(a)
[url=home.php?mod=space&uid=291977]@height[/url] = a
end
end
class People
def name
return @name
end
def name=(a)
@name = a
end
def height
return @height
end
def height=(a)
[url=home.php?mod=space&uid=291977]@height[/url] = a
end
end
这段代码什么意思一会我会讲,看不懂先不要着急a = People.new
b = People.new
c = People.new
a.name = "小明"
b.name = "小红"
c.name = "小白"
a.height = 1.73
b.height = 1.68
c.height = 1.70
p a.height #=>1.73
p b.height #=>1.68
p c.height #=>1.70
a = People.new
b = People.new
c = People.new
a.name = "小明"
b.name = "小红"
c.name = "小白"
a.height = 1.73
b.height = 1.68
c.height = 1.70
p a.height #=>1.73
p b.height #=>1.68
p c.height #=>1.70
这个就是一个实例的属性的可读可写
具体解释一下实例的属性到底是什么
先说一下实变量
以@开头的变量被称为实变量
实变量的有效范围为一个实例内部或整个class内部
实变量大多作为实例的一个属性而被赋值
新生成的类里定义的实变量是不能由外部直接赋值的
因此我们可以通过定义 实例(就是我说的那个人,不是数组,哈希表,数字。。。) 的函数(这个人可以踢足球,打篮球。。。)的方式来读取存储实例的属性(我叫。。。我的身高是。。。)
比如def name
return @name
end
这个函数目的是返回@name的值
也就是读取@name的值
又比如def name=(a)
@name = a
end
def name=(a)
@name = a
end
就是定义一个有参数的函数
使@name的值被赋值为传入的参数
也就是修改@name的值
这就是实变量,也就是事件的属性的可读可写性
实例的属性
以后会为大家渗透一些游戏中的应用
其实一个npc就是一个事件
事件实际上是一个实例
编辑这个实例为了便于管理,我们应用了一个全局变量赋值为哈希表,
这个哈希表主键是事件id,值为事件实例
事件具有行走图、是否可穿透等等一些属性
以后会给大家渗透
现在先不讲
一个实变量的可读可写可以被简写成为如下的几种语句:attr_accessor :属性名 #使该属性名的实变量可读可写
attr_reader :属性名 #使该属性名的实变量可读
attr_writer :属性名 #使该属性名的实变量可写
attr_accessor :属性名 #使该属性名的实变量可读可写
attr_reader :属性名 #使该属性名的实变量可读
attr_writer :属性名 #使该属性名的实变量可写
比如翻译过来就是def name
return @name
end
attr_writer :name
翻译过来就是def name=(name)
@name = name
#不要看到这个就蒙了,name是传进来的参数变量,就相当于上文讲的a
end
def name=(name)
@name = name
#不要看到这个就蒙了,name是传进来的参数变量,就相当于上文讲的a
end
翻译过来就是attr_reader :name
attr_writer :name
attr_reader :name
attr_writer :name
类变量:
类变量由两个@符开头,例如@@count。与全局变量和实例变量不同,类变量在使用之前必须被初始化。通常,初始化就是在类定义中的简单赋值。
举个例子:
class People
@@count=0#类变量的初始化,没有被初始化的类变量是不能被调用的。
attr_accessor :name
attr_accessor :height
def initialize
@name=""
@height=1.65
@@count+=1#在新生成实例的时候该类变量会增加1,可用于计算生成了多少个实例。
end
class People
@@count=0#类变量的初始化,没有被初始化的类变量是不能被调用的。
attr_accessor :name
attr_accessor :height
def initialize
@name=""
@height=1.65
@@count+=1#在新生成实例的时候该类变量会增加1,可用于计算生成了多少个实例。
end
类变量好比一个公共变量,在所有生成的实例中都可读可写且值保持统一。
在外部读取写入类变量与读取写入实变量的方法相同,不过不能使用简写方法attr_accessor :。
initialize方法:
所谓方法,就是类里定义的一个函数。
当程序新生成一个实例并赋值给变量时,一定会先加载该实例的类的initialize函数。
initialize函数的初定义class 类名
def initialize(参数)#参数可以省略
函数体
end
end
class 类名
def initialize(参数)#参数可以省略
函数体
end
end
一般initialize函数用于为新实例赋初值
就像给一个人预定义一个名字,一个身高,不对的话可以在调用时更改,否则为默认。
比如游戏中的一个生成新事件的类:class Event
def initialize(x, y)
@id = 0
@name = ""
@x = x
@y = y
@pages = [RPG::Event::Page.new]
#此处是调用其它类新生成实例的方法,暂时先不用掌握
end
attr_accessor :id
attr_accessor :name
attr_accessor :x
attr_accessor :y
attr_accessor :pages
end
end
class Event
def initialize(x, y)
@id = 0
@name = ""
@x = x
@y = y
@pages = [RPG::Event::Page.new]
#此处是调用其它类新生成实例的方法,暂时先不用掌握
end
attr_accessor :id
attr_accessor :name
attr_accessor :x
attr_accessor :y
attr_accessor :pages
end
end
新建一个事件的时候要调用到这个类生成新实例(那个事件就相当于我举的‘人’的例子,有各式各样的属性)
这里的initialize是个有参函数,在新生成实例时需要在new后面加上参数。
函数预定义了一个id,一个名字,一个x,一个y,且都可读可写,于是,我们新形成了一个id为0,name为"",x为1,y为1的实例。
类的方法:
我预先定义了一个类:
class People
attr_accessor :name
attr_accessor :height
end
class People
attr_accessor :name
attr_accessor :height
end
想要为这个类定义新方法的话可以再定义(也称重定义)这个类
比如class People
attr_accessor :id
def new
return[@id,@name,@height]
end
end
class People
attr_accessor :id
def new
return[@id,@name,@height]
end
end
这个定义的新方法new的功能是返回实例的id,name,height三个属性组成的数组。a = People.new#生成新实例
c = a.new#调用方法返回数组
p c
a = People.new#生成新实例
c = a.new#调用方法返回数组
p c
输出结果为[nil,nil,nil]
因为initialize没有预定义值,调用时也没有赋值所以,各个属性的值都是nil
第二节 类的继承
子类、父类:
实际上ruby中的数组、数字、哈希表等等都是类的实例,我们知道一个实例都有与之对应的类,有对应的类就有该类对应的方法。
但我们发现,有些类的方法是相似的,比如整数和浮点数
都可以进行判断是否为整数。
于是我们在ruby中引用了一对名词叫 父类 子类
子类有父类的所有方法,子类有子类自己的方法,父类的其它子类有自己独特的方法
举个例子
数字是Numeric(数)类的实例
其子类有Integer(整数)、float(浮点数)
Integer的子类有Fixnum(小整数)、Bignum(大整数)
Integer 整数有父类Numeric 数的integer? (判断是否是整数)方法
也有本身的+-*/的方法
继承关系:
举个例子:class People
end
def Chinese_People < People
end
class People
end
def Chinese_People < People
end
简单点说:中国人属于人类
中国人有人类的特性
当然中国人独有的特色其它人是没有滴
常量:
下面说下常量
ruby中的常量只能在类或模块中定义,模块我们还没有讲,最后再说
ruby中常量为一个以大写字母开头的标识符(默认我们约定全部大写),并且class(类)、module(模块)的名字都必须是常量。
注意:常量不能在类的函数(方法)中定义
常量在赋初值后再赋值会发生警告,但不会出现错误。
子类调用父类的常量时可以直接调用class Foo
FOO = 'FOO'
end
class Bar < Foo
p FOO # => "FOO"
end
class Foo
FOO = 'FOO'
end
class Bar < Foo
p FOO # => "FOO"
end
从外部引用常量要用到 :: 运算符
用法:
super语句:
super是子类调用父类同名方法的一种写法,相当于继承父类的方法,但是,自己又新增一些方法。
就好比人类都有能用嘴巴说话,中国人能用嘴巴说中国话,美国人可以用嘴巴说英文一样class People
def word
p "I can say"
end
end
class Chinese_People
def word
super
p "chinese"
end
end
$我 = Chinese_People.new
$我.word
#=> I can say
#=>chinese
class People
def word
p "I can say"
end
end
class Chinese_People
def word
super
p "chinese"
end
end
$我 = Chinese_People.new
$我.word
#=> I can say
#=>chinese
当然父类该方法有参数的时候子类调用时可以在super后面加上参数下面讲下alias
语法:或者我个人理解意思是把方法名指定的方法赋给新名。
就是创建一个与方法名内容相同的一个新方法。
第三节:模块
模块的定义:
语法:module 标识符#(首字母大写)
def self.方法名
语句
end
end
module 标识符#(首字母大写)
def self.方法名
语句
end
end
模块可以在外部直接定义模块方法
例如module People
end
def People.set
p "ok"
end
module People
end
def People.set
p "ok"
end
调用:
调用模块的方法不需要新生成实例,只需要:
模块名.方法名(参数)
即可调用方法
模块部分未完待续。
附运算符优先顺序:高 ::
[]
**
-(单项) +(单项) ! ~
* / %
+ -
<< >>
&
| ^
> >= < <=
<=> == === != =~ !~
&&
||
.. ...
?:(条件运算符)
=(+=, -= ... )
not
低 and or
高 ::
[]
**
-(单项) +(单项) ! ~
* / %
+ -
<< >>
&
| ^
> >= < <=
<=> == === != =~ !~
&&
||
.. ...
?:(条件运算符)
=(+=, -= ... )
not
低 and or
基础语法部分就这么多,具体Object类中的方法可以参照rmxp自带F1查看,日后也会补充进去。其它有不全的地方望指明后补充。最近备考高数,时间比较紧张,还望大家多多包涵,还有,占楼就不要算偶连贴了吧( ^_^ )
作者: RyanBern 时间: 2014-12-29 09:34
本帖最后由 RyanBern 于 2014-12-29 19:44 编辑
又见教程类帖子,很好,加油莫坑。
刚才大致看了一下,总体来说写得还是不错的,不过希望LZ注意一下细节,教程中有几处笔误。另外有些需要注意的地方不要略过。
下面是我发现的几个问题,看得不仔细,日后会补充。
1.super那里,class Chinese_People < People,People类定义有一个地方height定义重复
2.既然没有讲三种变量的含义,那么举例子的时候就不要一会用全局,一会用局部,这样会给新手造成困扰。
3.汉字标识符严重影响代码美观性,个人不推荐使用。
(话说LZ把“汉字”写成“汉子”,也是醉了,果然是生命中缺汉子么?)
4.有关rand方法,我记得有个方法可以返回0~1之间随机的一个浮点数
5.写语句时,标识符(或者字面量)和运算符之间最好都要用空格隔开,不仅仅是因为美观问题,而是有点时候会报错-_-||
6.有关生成1~100之间随机数的代码,例子给的不是很好,可以看看是否能优化一下?
7.循环结构不推荐用for,因为在Ruby中for是一个语法糖,因为C/C++的for循环深入人心,所以再这里引入了for。
对于数组,Hash,Range类对象可以用for的原因是它们定义了each方法,因此应该着重讲讲each。
8.module的讲解还可以更深入一些,这东西和class一样重要。
9.我看到了一句“class是一堆方法的集合”这样的说法,这样说真的对么?
10.有关a+=a+=2这种东西,本身给人就造成了很大困扰,我想编程的时候没人喜欢用吧。
11.有关逻辑运算,位运算的内容少了点,希望能补充相关内容。
例如,短路原则,and/or/not 和&&/||/!的区别,unless 表达式1 and 表达式2 是什么意思,等等
12.那我也来说说case~when吧,类似与C语言中的贯穿式switch语句:
switch(c){
case 0:
case 1:
case 2:
cout << "0,1,2\n";
break;
case 3:
cout << "3\n";
break;
}
switch(c){
case 0:
case 1:
case 2:
cout << "0,1,2\n";
break;
case 3:
cout << "3\n";
break;
}
Ruby中相应写法为:
case c
when 0,1,2
print "0,1,2"
when 3
print "3"
end
case c
when 0,1,2
print "0,1,2"
when 3
print "3"
end
另外注意case~when中用作判断表达式的其实是操作符'===',即把表达式和case后面的东西作用一下,如果是true则执行when后面的内容,然后跳出。
所以,如果自己定义了一个类,并且想要这个类的对象可以用到case~when里面(当然需要一些特殊要求),就要重新定义'==='方法了,如果不重定义的话,'==='的效果等同于'=='
看这个例子,再体会下case~when
class Multipler
attr_accessor :rate
def initialize(rate = 1)
@rate = rate
end
def ===(num)
return num % @rate == 0
end
end
def test
(0..30).each do |i|
case i
when Multipler.new(3)
print "#{i}是3的倍数"
when Multipler.new(5)
print "#{i}是5的倍数"
when Multipler.new(7)
print "#{i}是7的倍数"
end
end
end
test #=> ??
class Multipler
attr_accessor :rate
def initialize(rate = 1)
@rate = rate
end
def ===(num)
return num % @rate == 0
end
end
def test
(0..30).each do |i|
case i
when Multipler.new(3)
print "#{i}是3的倍数"
when Multipler.new(5)
print "#{i}是5的倍数"
when Multipler.new(7)
print "#{i}是7的倍数"
end
end
end
test #=> ??
作者: taroxd 时间: 2014-12-29 17:52
本帖最后由 taroxd 于 2014-12-29 20:48 编辑
小建议: 用 # => 来表示方法的返回值
大概是个不成文的规定的样子?
当局部变量没有初始化时,我们可以确定该标识符就是方法。
另外变量还有两种,以 @@ 开头的类变量 和 大写字母开头的常量
Object#to_a 在 Ruby 1.9 中被删去,故 1.to_a 是不好的。应该用 Array(1) 或者 [*1]
随机排列一个从1到100这100个数 组成的数组并显示之
p (1..100).to_a.shuffle
不要拿 C 语言的风格玩 Ruby,也不要拿 C 语言类比 Ruby。会毁了 Ruby 的。
举个例子来说,Ruby 中永远不应该出现 for。
常量可以改的,就是会吃警告而已……
如果真的想要改的话,可以连警告都不吃。
比如 https://rpg.blue/thread-366777-1-2.html
另外,常量的作用域远比你写的要复杂。涉及到词法作用域和从模块(类)获取常量的途径。
模块的功能可不只是存单例方法和常量的地方。只放单例方法的话,Object 就可以做到。
实例变量的作用域永远是 self。永远。
a ||= obj 的理解最好是这样
if defined?(a) && a
a
else
a = obj
end
case 语句中,when 接表达式而不是常量。真假会用 === 判断,而不是等于。Module, Range, Regexp, Proc 等都重定义了 ===。使用的例子参考我那个事件转译器的范例和楼下的例子。
loop 不是语句,是方法哦~ 而且这个方法简单到你自己也能实现。
redo 被废了,别用。
另外,next 和 break 其实不只是中断循环呢~ 特别是 next,一般是用于 block 的返回中的。当然这个暂时不讲也罢。
建议楼主了解一下 Ruby 的对象模型,也就是元编程相关的东西。虽然不一定要用到,但是可以涨很多姿势。
作者: taroxd 时间: 2014-12-29 19:56
本帖最后由 taroxd 于 2014-12-29 20:10 编辑
RyanBern 发表于 2014-12-29 09:34
又见教程类帖子,很好,加油莫坑。
刚才大致看了一下,总体来说写得还是不错的,不过希望LZ注意一下细节, ...
可以更优雅。
def multiple?(rate = 1)
lambda { |n| n % rate == 0 }
end
...
when multiple?(2)
...
欢迎光临 Project1 (https://rpg.blue/) |
Powered by Discuz! X3.1 |