File: same-lib.rkt

package info (click to toggle)
racket 7.2%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 125,432 kB
  • sloc: ansic: 258,980; pascal: 59,975; sh: 33,650; asm: 13,558; lisp: 7,124; makefile: 3,329; cpp: 2,889; exp: 499; python: 274; xml: 11
file content (226 lines) | stat: -rw-r--r-- 8,147 bytes parent folder | download | duplicates (12)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
#lang racket/base
(require racket/class
         racket/draw)

(provide make-a-move
         
         draw-board
         update-pen/draw-blob
         update-dc-scale
         
         colors
         board-ref
         cell-w
         cell-h
         find-same-colors)

;; these are the sizes that the on-paint callback draws at;
;; a scaling factor is applied to make the board fit the window
(define cell-w 11)
(define cell-h 11)
(define pen-size 10)

(define colors (map (lambda (x) (make-object color% x))
                    (list "blue" "red" "brown" "forestgreen" "purple")))
(define pale-colors 
  (for/list ([x (in-list colors)])
    (define (paleize x) (- 255 (floor (* (- 255 x) 2/3))))
    (make-object color%
      (paleize (send x red))
      (paleize (send x green))
      (paleize (send x blue)))))

(define (draw-board dc board-width board-height board cw ch
                    mouse-current-x mouse-current-y mouse-clicked-x mouse-clicked-y)
  (send dc erase) 
  (send dc set-smoothing 'smoothed)
  (update-dc-scale dc cw ch board-width board-height)
  (define painted (make-hash))
  (for* ([i (in-range 0 board-width)]
         [j (in-range 0 board-height)])
    (unless (hash-ref painted (xy->key board-width i j) #f)
      (define color (vector-ref (board-ref board i j) 0))
      (when color
        (define blob (find-same-colors board board-width board-height i j))
        (for ([x (in-list blob)])
          (hash-set! painted (xy->key board-width (blob-sel-x x) (blob-sel-y x)) #t))
        (update-pen/draw-blob
         blob dc color
         mouse-current-x mouse-current-y mouse-clicked-x mouse-clicked-y)))))

(define (update-dc-scale dc cw ch board-width board-height)
  (send dc set-scale 
        (/ cw (* board-width cell-w)) 
        (/ ch (* board-height cell-h))))

(define (update-pen/draw-blob
         blob dc color
         mouse-current-x mouse-current-y mouse-clicked-x mouse-clicked-y)
  (define mouse-over? #f)
  (define mouse-clicked-over? #f)
  (define multiple-cells? (not (or (null? blob) (null? (cdr blob)))))
  
  (when (or (number? mouse-current-x)
            (number? mouse-clicked-x))
    (for ([obj (in-list blob)])
      (define x (blob-sel-x obj))
      (define y (blob-sel-y obj))
      (when (and (equal? x mouse-current-x)
                 (equal? y mouse-current-y))
        (set! mouse-over? #t))
      (when (and (equal? x mouse-clicked-x)
                 (equal? y mouse-clicked-y))
        (set! mouse-clicked-over? #t))))
  
  (cond
    [mouse-clicked-x ;; has the mouse been clicked in a clickable place?
     (cond 
       [(and mouse-over? mouse-clicked-over? multiple-cells?)
        (send dc set-pen (list-ref pale-colors color) (* pen-size 2/3) 'solid)
        (draw-blob dc blob)]
       [else
        (send dc set-pen
              (list-ref colors color)
              pen-size
              'solid)
        (draw-blob dc blob)])]
    [else
     (cond
       [mouse-over?
        (send dc set-pen (list-ref pale-colors color) pen-size 'solid)
        (draw-blob dc blob)]
       [else
        (send dc set-pen (list-ref colors color) pen-size 'solid)
        (draw-blob dc blob)])]))

(define (draw-blob dc blob)
  (define (connect x1 y1 x2 y2)
    (send dc draw-line 
          (+ (/ cell-w 2) (* x1 cell-w))
          (+ (/ cell-h 2) (* y1 cell-h))
          (+ (/ cell-w 2) (* x2 cell-w))
          (+ (/ cell-h 2) (* y2 cell-h))))
  (cond
    [(null? (cdr blob))
     (define pt (car blob))
     (connect (blob-sel-x pt) (blob-sel-y pt) (blob-sel-x pt) (blob-sel-y pt))]
    [else
     (for* ([b1 (in-list blob)]
            [b2 (in-list blob)])
       (when (= (+ (abs (- (blob-sel-x b1) (blob-sel-x b2)))
                   (abs (- (blob-sel-y b1) (blob-sel-y b2))))
                1)
         (connect (blob-sel-x b1) (blob-sel-y b1) (blob-sel-x b2) (blob-sel-y b2))))]))

(define (xy->key board-width x y) (+ (* board-width y) x))

(define (make-same-bitmap pth)
  (define bw 32)
  (define bh 32)
  (define bitmap (make-bitmap bw bh))
  (define bdc (make-object bitmap-dc% bitmap))
  (define board-width 3)
  (define board-height 3)
  (define board 
    (vector (vector (vector 0 #f) (vector 1 #f) (vector 4 #f))
            (vector (vector 0 #f) (vector 1 #f) (vector 1 #f))
            (vector (vector 3 #f) (vector 3 #f) (vector 2 #f))))
  (draw-board bdc board-width board-height board bw bh
              #f #f #f #f)
  (send bdc set-bitmap #f)
  (send bitmap save-file pth 'png))
  
; (make-same-bitmap "same.png")

;; make-a-move : num num board num num -> num or #f
;; mutates 'board' to reflect removing the blob at (i,j)
;; result is the size of the removed blob, or #f if nothing got removed
(define (make-a-move i j board board-width board-height)
  (let ([same-colors (find-same-colors board board-width board-height i j)])
    (cond
      [(< (length same-colors) 2)
       #f]
      [else
       
       ;; slide down empty pieces
       (let ([is null])
         (for-each
          (lambda (p)
            (let ([i (blob-sel-x p)]
                  [j (blob-sel-y p)])
              (unless (member i is)
                (set! is (cons i is)))
              (let loop ([x j])
                (cond
                  [(<= 1 x)
                   (let ([next (board-ref board i (- x 1))]
                         [this (board-ref board i x)])
                     (vector-set! this 0 (vector-ref next 0))
                     (loop (- x 1)))]
                  [else
                   (vector-set! (board-ref board i x) 0 #f)]))))
          (sort same-colors
                (lambda (x y) (<= (blob-sel-y x) (blob-sel-y y)))))
         
         ;; slide empty over empty rows
         (set! is (sort is >))
         (let ([empty-is 
                (filter (lambda (i)
                          (not (vector-ref 
                                (board-ref board i (- board-height 1))
                                0)))
                        is)])
           (let ([is (if (null? empty-is)
                         is
                         (filter (lambda (x) (< x (car empty-is)))
                                 is))])
             (for-each (lambda (empty-i)
                         (let loop ([i empty-i])
                           (cond
                             [(<= i (- board-width 2))
                              (vector-set! board i (vector-ref board (+ i 1)))
                              (loop (+ i 1))]
                             [(= i (- board-width 1))
                              (vector-set! 
                               board
                               i
                               (build-vector board-height
                                             (λ (i) (vector #f #f))))])))
                       empty-is))))
       
       (length same-colors)])))

(define (blob-sel-x b) (vector-ref b 1))
(define (blob-sel-y b) (vector-ref b 2))
(define (board-ref b x y) (vector-ref (vector-ref b x) y))

(define (find-same-colors board board-width board-height i j)
  (let* ([index (vector-ref (board-ref board i j) 0)]
         [ans
          (let loop ([i i]
                     [j j]
                     [ps null])
            (cond
              [(not (and (<= 0 i) (< i board-width)
                         (<= 0 j) (< j board-height)))
               ps]
              [else
               (let ([v (board-ref board i j)])
                 (cond 
                   [(vector-ref v 1) ps]
                   [(not (vector-ref v 0)) ps]
                   [(= index (vector-ref v 0))
                    (vector-set! v 1 #t)
                    (loop (+ i 1)
                          j
                          (loop (- i 1)
                                j
                                (loop i
                                      (- j 1)
                                      (loop i
                                            (+ j 1)
                                            (cons (vector v i j)
                                                  ps)))))]
                   [else ps]))]))])
    (for-each (lambda (p) (vector-set! (vector-ref p 0) 1 #f)) ans)
    ans))