Доступ и изменение значения, созданного с помощью `define` - PullRequest
0 голосов
/ 30 декабря 2010

Я делаю игру, и у меня есть это:

(define b "black piece") (define w "white piece")

(define (board)
 (lambda (matrix) 
   (list ((b w b w b w b w) 
          (w b w b w b w b) 
          (b w b w b w b w) 
          (w b w b w b w b) 
          (b w b w b w b w) 
          (w b w b w b w b) 
          (b w b w b w b w) 
          (w b w b w b w b)))))

board составляет список из 8 строк и 8 столбцов черно-белых фигур.

Как мне получить доступ и изменить элементы доски? Как мне сделать матрицу процедур с рекурсией?

1 Ответ

0 голосов
/ 30 декабря 2010

первые несколько примечаний:
(define f (lambda (x) l ))
совпадает с
(define (f x) l ))
Однако вы комбинируете их с
(define (board) (lambda (matrix) l ))
, что совпадает с
(define board (lambda () (lambda (matrix) l )))

Различие важно.Первые два, которые я перечислил, связывают f с функцией, которая принимает один параметр и возвращает l.Я предполагаю, что это то, что вы хотите сделать.Во втором случае вы связываете board с функцией, которая не принимает параметров и возвращает функцию, которая принимает 1 параметр, matrix (с которым она, похоже, ничего не делает) и возвращает l.

вторая проблема, (list ((b w....) ...)) не сработает, потому что попытается оценить (b w ...).у вас должен быть список в позиции приложения функции для каждой строки вашей доски, например (list (list b w ...) (list w b ...) ...), чтобы ваш код даже компилировался.

В ответ на ваш вопрос. link-ref включен в ракетку / базу и используется для ссылки на элементы в списке, когда вы знаете индекс в списке.
(list-ref 2 (list 'a' b 'c'd))
вернет 'c.Индекс начинается с 0. Поскольку у вас есть список списков, вам нужно будет дважды применить list-ref, чтобы получить 'b или' w.

Что касается его изменения, ну, вы не можете.С r6rs пары (которые составляют списки) являются неизменяемыми.Рекомендуемый способ сделать все возможное, это вернуть новый список с вашими изменениями.Вы можете использовать эту несколько неэффективную версию list-set, которая возвращает копию списка с новым значением в индексе.

(define (list-set lis idx val)
  (map (lambda (e i)
    (if (= i idx) val e))  
    lis  
    (iota (length lis))))

В этом случае, однако, я бы рекомендовал перейти на другую структуру данных, болеев соответствии с поставленной задачей, так как вы, вероятно, хотите O (1) доступ к элементам на доске.Посмотрите на векторы , которые ведут себя подобно спискам, но используются для постоянных поисков и обновлений.есть встроенные операции vector-ref и vector-set!, которые вы должны использовать вместо моей функции выше.

В случае, если это является частью более крупной проблемы, и вы уже используете списки везде, вы можете использоватьvector->list и list->vector функции для перемещения вперед и назад.Кроме того, вы можете использовать изменяемые списки , но не используйте.

Еще лучше - библиотека многомерных массивов, предлагаемая в srfi / 25 , но это может быть сложнее, чемВы хотите получить.

Вторая часть вашего вопроса была о том, как рекурсивно построить доску.Ну, вот версия с использованием карты.

(require (lib "1.ss" "srfi"))
(define (board)
  (map (lambda (x)
         (map (lambda (y)
                (if (odd? (+ x y)) b w))
              (iota 8)))
       (iota 8)))

и вот рекурсивная версия

(define (board)
  (letrec ((board-helper
            (lambda (x)
          (if (eq? x 8) '()
          (cons (row-helper x 0) (board-helper (+ 1 x))))))
       (row-helper
        (lambda (x y)
          (if (eq? y 8) '()
          (cons (if (odd? (+ x y)) b w) (row-helper x (+ 1 y)))))))
    (board-helper 0)))
...