用Racket做一个拼图游戏——8 按行列分割图片

78 篇文章 17 订阅
28 篇文章 0 订阅

按行列分割图片

这一节,我们把调整好尺寸的图片分割成指定的rows行,columns列,每个行列单元格都存储一张分割后的小图片,需要的时候直接取出来使用即可。

行数和列数很好理解。但如果仅仅考虑分割图片,只需给出行列数去分割图片就可以。但是考虑到行列数需要被记住,后边便于使用。因此这里设置两个值来指向行数值和列数值。把值设置为全局绑定,如下:

(define rows 3)
(define cols 3)

这里设置了行列的初始值,为了能够让用户设定行列数,这里需要定义两个函数来实现该功能。如下:

;设置单元格行数:
(define (set-rows! num)
  (set! rows num))
;设置单元格列数:
(define (set-cols! num)
  (set! cols num))

这里函数名"set-rows!"后面有一个”!“,表明它是有副作用的函数。函数里边有对函数"set!"求值,它也是有副作用的。

接下来分割图片。

分割图片用到的函数还是之前用过的"draw-bitmap-section",需要给它传递被分割图片对象,分割的左上角起点,分割的右下角止点。函数定义如下:

;根据指定行、列分割图片:
(define (split-picture-by-row&col pic row col)
  (let* ([pic/cell (make-bitmap width/cell height/cell)]
         [dc/pic (send pic/cell make-dc)]
         [xl (* col width/cell)]
         [yt (* row height/cell)]
         [xr (+ xl width/cell)]
         [yb (+ yt height/cell)])
    (send dc/pic draw-bitmap-section
          pic
          0 0
          xl yt xr yb)
    pic/cell))

如果看过了前面的章节,应该已经了解"define"、"let*"、"send"的使用,同时也知道"make-bitmap"函数和"draw-bitmap-section"的用法。

这里有一个新的函数:"make-dc",是创建一个绘图环境对象,供画图用。具体怎么来的,留到后边的章节再细讲。

请注意这个函数名"split-picture-by-row&col",其中用了一个字符“&”,如果你用过其它程序语言,有想这样写函数名却没这样写的举一下手。因为,其它语言不准许呀!能自由表达多好!

但这个自定义函数有一个问题,width/cell和height/cell是未定义的。如果这样对这个函数求值就会报错。

由于我们会多次求值以取得单元图片,我们把这两个值作为全局绑定值处理。把如下代码放到模块顶层:

(define width/cell 0)
(define height/cell 0)

这里设置的单元图片宽、高均为0,这里再写一个函数来设置他们的值,在每次重新设置行列数的时候对其求值就可以了。如下:

(define (set-cell-size!)
  (set! height/cell
        (floor (/ height/picture rows)))
  (set! width/cell
        (floor (/ width/picture cols))))

这里还有一个之前没见过的函数:"floor",它是一个数值函数,用来对"\\"这个函数(的确没错,"\\"就是一个函数,用来做除法,和数学的除号意义是一样的)求值,返回不超过所给参数值的最大整数(就是数学里的对数值取整)。

数值函数还有很多,如常用的:四则运算函数"+"、"-"、"×"、"\\",大小比较函数">"、"<"、"<="、">="、"=","expt"平方、"sqrt"开方,以及"abs"取绝对值、"max"取最大值、"min"取最小值……等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值