【问题标题】:How to find a point within a square in racket?如何在球拍的正方形内找到一个点?
【发布时间】:2021-10-21 01:23:56
【问题描述】:

目前,我正在努力找出一个函数,该函数可以确定一个点是否在正方形中,或者没有给定正方形的边长和左上角。

; tl is a Posn, giving the top-left corner of the square
; side is a Number, giving the side length of the square
(define-struct SQ (tl side))
(define z (make-SQ tl side))
(define x (+ (posn-x SQ-tl z) (SQ-side z)))
(define y (+ (posn-y SQ-tl z) (SQ-side z)))
(define a (make-posn x y))
; Posn, SQ -> Boolean
(define (point-in-square? P S)  (and (<= (posn-x P) (posn-x a) S)
                                     (>= (posn-x P) (posn-x (SQ-tl z)) S)
                                     (<= (posn-y P) (posn-y a) S)
                                     (>= (posn-y P) (posn-y (SQ-tl z)) S)))

我收到错误tl: undefined; cannot reference undefined identifier 我该如何解决这个错误?

【问题讨论】:

  • (define z (make-SQ tl side)) -- 代码在某些参数上调用make-SQtl 的值是多少? side 的值是多少?
  • tl指的是SQ的tlside是SQ的side
  • 你错了,这是我试图暗示的错误消息的来源。在调用(make-SQ tl side) 中,尝试评估tl,结果值应该用于构造SQ 结构。但是,tl 还没有被赋予任何价值!如果您通过执行(define my-posn (make-posn 4 2)) 之类的操作来解决此问题,然后调用(make-SQ my-posn side),您将解决tl 的问题,但不会解决side 的问题。您必须向make-SQ 提供适当的,才能构造SQ 结构。
  • 是的,如果 my-number 评估为适当的值。大概SQ 边只是代表边长的数字;看起来posn 是一个结构,其中包含xy 字段的数字。因此,您可以执行类似 (define my-SQ (make-SQ (make-posn 4 2) 1)) 的操作来创建一个边长 1 位于 (4, 2) 的 SQ
  • 我认为代码的主要问题是方块在每个测试用例中随机移动。我怎么能在不使用特定数字的情况下使用它(我可能想多了)。

标签: racket computer-science


【解决方案1】:

最初的问题导致错误,例如:tl: undefined; cannot reference undefined identifier。在构造正方形z的调用中,构造函数make-SQ被调用,参数为tlside;但尚未为这些标识符分配任何值。似乎 OP 正在使用它们,因为这些是插槽名称;构造函数需要适当的值来分配给插槽。这里的解决方案只是认识到构造一个实际的SQ 实例需要具体的值。

克服了第一个障碍,我们清楚地知道 point-in-square? 谓词的定义有问题。该定义试图使用全局定义的z 正方形和a 点。但是这个过程也需要PS 参数,它们分别是一个点和一个正方形。这就是解决问题所需的所有信息。

在解决了 cmets 中的 OP 问题后,OP 已解决问题以使代码正常工作。这是一个替代解决方案,它使用let* 使代码更易于阅读和思考:

#lang racket

(define-struct posn (x y))

(define-struct SQ (tl side))

(define (point-in-square? P S)
  (let* ((top-left (SQ-tl S))
         (side-length (SQ-side S))
         (left (posn-x top-left))
         (right (+ left side-length))
         (top (posn-y top-left))
         (bottom (+ top side-length)))
    (and (<= (posn-x P) right)
         (>= (posn-x P) left)
         (<= (posn-y P) bottom)
         (>= (posn-y P) top))))

还有一个示例 REPL 交互:

point-in-square.rkt> (define test-square (make-SQ (make-posn 4 2) 1))
point-in-square.rkt> (define p1 (make-posn 5 3))  ; in square
point-in-square.rkt> (define p2 (make-posn 5 2))  ; on edge of square
point-in-square.rkt> (define p3 (make-posn 5 1))  ; not in square
point-in-square.rkt> (point-in-square? p1 test-square)
#t
point-in-square.rkt> (point-in-square? p2 test-square)
#t
point-in-square.rkt> (point-in-square? p3 test-square)
#f

请注意,let 对于将计算中使用的值绑定到有意义的名称很有用;在这种情况下,let* 很方便,因为它允许我们在后续绑定中使用先前以相同 let* 形式绑定的值。另一种方法是嵌套let 表单,以便内部lets 可以使用外部绑定。

【讨论】:

    猜你喜欢
    • 2014-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多