如何在DrRacket中递归地平铺有缺陷的棋盘

时间:2015-04-07 02:25:44

标签: recursion racket divide-and-conquer

我有一个家庭作业问题,现在我真的很烦我,我可以在如何在DrRacket中实现它。我不希望代码,只是指导,因为我对DrRacket很新。

作业是实现这个短语:

“如果n = 0,则返回空的平铺(平铺结构列表)。否则,在棋盘的中心放置一个tromino(L形多米诺骨牌),使其覆盖棋盘的三个象限其中没有丢失的图块,并平铺每个象限。“

使用给定的两个.rkt文件作为递归代码。我们被允许使用tromino.rkt中的任何功能。

我们还被告知编写代码时需要以下函数,因此我已经包含了每个函数的描述:

(center-tile n row column)
此函数生成单个图块结构,表示当棋盘在指定行中缺少图块时,放置在2 n ×2 n 棋盘中心的正确定向的tromino和专栏。请记住,行和列从零开始编号。这个功能为你做了很多工作:它确定了丢失的单元所在的象限,确定了放置在板中心的tromino的正确方向,以便不覆盖该象限,并返回一个磁贴表示该tromino在板上的适当位置的结构。

(缺少单元格内的n行列像素 - 行 - 象限 - 列)
2 n ×2 n 棋盘被分为四个象限,这些象限就像行和列一样被索引。具体而言,左上象限对应于 (象限行,象限列)设置为(0,0)。其他象限的右上角为(0,1),左下角为(1,0),右下角为(1,1)。函数missing-cell-in-quadrant回答了以下问题:

在放置由center-tile生成的图块之后,该象限内缺失或覆盖单元格的象限(象限行,象限列)内的(行,列)坐标是什么?

答案是带有两个坐标的列表形式,以每个象限的参照系表示。例如,如果2 3 ×2 3 电路板中的缺失单元位于第2行第5列,则在放置中心磁贴后进行4次调用

(缺少 - 象限内3 2 5 0 0) (遗留在象限内的细胞3 2 5 0 1)
(遗留在象限内的细胞3 2 5 1 0)
(遗留在象限内的细胞3 2 5 1 1)

分别返回以下四个列表:

'(3 3)
'(2 1)
'(0 3)
'(0 0)

(升级平铺平铺m象限 - 行象限 - 列)
鉴于2个 n ×的四个2 m ×2 m 象限之一的平铺 - 即一个tromino瓷砖列表 - 2 n 棋盘,其中 m = n-1 ,此函数转换平铺中的所有切片,使其坐标指向完整的棋盘。

您将获得一个文件tromino.rkt,如下所示

#lang racket

(require racket/draw)

(define thickness 6)
(define offset (floor (/ thickness 2)))
(define one 100)
(define two (* 2 one))
(define a 0)
(define b one)
(define c (- two thickness))

(define (mirror coordinates)
  (map (lambda (z) (- one z thickness)) coordinates))

(define x-00 (list c c a a b b))
(define y-00 (list a c c b b a))
(define x-01 (mirror x-00))
(define y-01 y-00)
(define x-10 x-00)
(define y-10 (mirror y-00))
(define x-11 x-01)
(define y-11 y-10)

(define (make-tromino-path x y)
  (let ((p (new dc-path%)))
    (send p move-to (first x) (first y))
    (send p line-to (second x) (second y))
    (send p line-to (third x) (third y))
    (send p line-to (fourth x) (fourth y))
    (send p line-to (fifth x) (fifth y))
    (send p line-to (sixth x) (sixth y))
    (send p close)
      p))

(define tromino-path-00 (make-tromino-path x-00 y-00))
(define tromino-path-01 (make-tromino-path x-01 y-01))
(define tromino-path-10 (make-tromino-path x-10 y-10))
(define tromino-path-11 (make-tromino-path x-11 y-11))

(define (tromino-path missing-row missing-column)
  (cond ((and (= missing-row 0) (= missing-column 0)) tromino-path-00)
        ((and (= missing-row 0) (= missing-column 1)) tromino-path-01)
        ((and (= missing-row 1) (= missing-column 0)) tromino-path-10)
        ((and (= missing-row 1) (= missing-column 1)) tromino-path-11)
        (else (error 'tromino-path "Called with arguments ~a, ~a (must each be either 0 or 1)"
                 missing-row missing-column))))

(define (draw-board n dc)
  (cond ((= n 1)
         (begin
           (send dc set-smoothing 'unsmoothed)
           (send dc set-pen "white" 0 'solid)
           (send dc set-brush "white" 'solid)
           (send dc draw-rectangle 0 0 two two)
           (send dc set-pen "black" 0 'solid)
           (send dc set-brush "black" 'solid)
           (send dc draw-rectangle 0 0 one one)
           (send dc draw-rectangle one one one one)))
    (else
     (begin
       (draw-board (- n 1) dc)
       (let ((side (* one (expt 2 (- n 1)))))
         (send dc copy 0 0 side side side 0)
         (send dc copy 0 0 (* 2 side) side 0 side))))))


(struct tile (row column missing-cell-row missing-cell-column))

(define (show-tile t)
  (printf "(row ~a column ~a missing-cell-row ~a missing-cell-column ~a)\n"
          (tile-row t) (tile-column t)
          (tile-missing-cell-row t) (tile-missing-cell-column t)))

(define (quadrant n row column)
  (let ((half (lambda (n coordinate)
                (cond ((bitwise-bit-set? coordinate (- n 1)) 1)
                      (else 0)))))
    (list (half n row) (half n column))))

(define (center-tile n row column)
  (let ((q (quadrant n row column))
        (base (- (expt 2 (- n 1)) 1)))
      (tile (+ base (first q)) (+ base (second q)) (first q) (second q))))

(define (missing-cell-within-quadrant n row column quadrant-row quadrant-column)
  (let ((q (quadrant n row column))
        (base (- (expt 2 (- n 1)) 1))
        (sub-coordinate (lambda (coord quad)
                          (cond ((= quad 1) (- coord (expt 2 (- n 1))))
                                (else coord)))))
    (cond ((and (= (first q) quadrant-row) (= (second q) quadrant-column))
           (list (sub-coordinate row (first q))
                 (sub-coordinate column (second q))))
          (else (list (cond ((= 0 quadrant-row) base)
                            (else 0))
                      (cond ((= 0 quadrant-column) base)
                            (else 0)))))))

(define (upgrade-tiling tiling m quadrant-row quadrant-column)
  (let* ((shift (expt 2 m))
         (row-shift (* quadrant-row shift))
         (column-shift (* quadrant-column shift)))
    (map (lambda (t)
           (tile (+ (tile-row t) row-shift)
                 (+ (tile-column t) column-shift)
                 (tile-missing-cell-row t)
                 (tile-missing-cell-column t)))
         tiling)))


(define (make-tiling-png n tiles basename)
  (cond ((or (<= n 0) (empty? tiles))
         (printf "Warning: make-tiling-png called with n too small or an empty tiling. No picture produced\n"))
        (else
         (begin
           (define side (* (expt 2 n) one))
           (define bmap (make-bitmap side side))
           (define dc (new bitmap-dc% (bitmap bmap)))
           (draw-board n dc)
           (send dc set-pen "black" 1 'solid)
           (send dc set-brush "white" 'transparent)
           (send dc draw-rectangle 0 0 side side)
           (send dc set-pen (new pen% (color "red") (width thickness)
                                 (style 'solid) (cap 'projecting) (join 'miter)))
           (send dc set-brush "gray" 'solid)
           (send dc set-smoothing 'unsmoothed)
           (map (lambda (t) (send dc draw-path (tromino-path (tile-missing-cell-row t)
                                                             (tile-missing-cell-column t))
                                  (+ offset (* one (tile-column t)))
                                  (+ offset (* one (tile-row t)))))
                tiles)
           (send bmap save-file (string-append basename ".png") 'png)))))

(provide tile
         tile-row
         tile-column
         tile-missing-cell-row
         tile-missing-cell-column
         show-tile
         quadrant
         center-tile
         missing-cell-within-quadrant
         upgrade-tiling
         make-tiling-png)

您还会收到一个文件template.rkt,如下所示:

#lang racket

(require "./tromino.rkt")

(define test-tiling (list (tile 2 5 0 1)))
(make-tiling-png 3 test-tiling "test-tiling")

**; Your code replaces the null in the following definition**
(define (tile-board n row column)
  null) 

(define (make-and-show-tiling n row column)
  (make-tiling-png n
                   (tile-board n row column)
                   (format "tiling-~a-~a-~a" n row column)))

; Initially, these calls will produce no picture
; because tile-board returns an empty tiling
(make-and-show-tiling 1 1 1)
(make-and-show-tiling 2 0 0)
(make-and-show-tiling 3 5 2)
(make-and-show-tiling 3 6 2)
(make-and-show-tiling 4 5 10)
(make-and-show-tiling 5 24 21)      

我非常了解这是如何工作的概念,你将2 n ×2 n 棋盘分成4个独立的象限,然后放置一个棋盘中心的tromino使得每个象限现在都有一个缺失的细胞或一个被部分tromino覆盖的细胞。然后,调用递归函数来平铺每个象限。最终目标是让代码运行,使得在我的template.rkt文件末尾的(make-and-show-tiling)函数的每个调用都将生成生成的棋盘图片。

我认为我只是变得非常困惑,因为我之前只学过Java和Python,而且DrRacket的格式/语法远远超出了那些语言。我完全陷入困境,所以除了为我编写代码之外,任何帮助都会非常受欢迎并且非常感激。

提前谢谢!!

0 个答案:

没有答案