2015-12-11 1 views
1

Я зациклился на том, как это реализовать.Clojure: каждый кадр, читайте ввод пользователя, если он доступен. вход передается в цикл, может быть либо lazy-seq of (reapeatedly (readline)), либо предопределенный список

Концепция является то, что я хочу:

  1. , чтобы быть в состоянии позволить обновление игры уже введенную ли или нет игрок ввода, но использовать вход, если он доступен
  2. иметь возможность легко менять вне входа пользователя с предопределенной последовательностью для целей тестирования.

Это сломанный реализация я в настоящее время:

(defn game 
    "Runs the simplified version of the main game" 
    [world user-input-machine] 

    (let [input [first (deref user-input-machine 10 nil)]] 
     (if (not= input "QUIT") 
      (do (println input) ; do game logic stuff 
        (game world (rest (deref user-input-machine)))) ;repeat 
      world))) 

Идея заключалась в том, чтобы передать что-то вроде

(future (repeatedly(readline))) 

или

(future (["hello", "world", "QUIT"])) 

В качестве входных данных. Реализация неверна по ряду причин. Я только начинаю с clojure, и это моя первая попытка использовать фьючерсы/задержки/обещания и т. Д. Может ли кто-нибудь помочь мне?

Я пришел через несколько взаимосвязанных вопросов, которые не совсем ответили, что им ищет (я даже не знаю, как сформулировать запрос):

Promises vs Futures

Multiple Threads in clojure

ответ

1

Насколько я понимаю, вы пытаетесь создать машину, которая прослушивает поток событий ввода пользователя и обновляет «мир» и инициирует побочные эффекты для каждого события.

Исходя из этого, я вижу несколько проблем здесь:

  • существует несколько механизмов координации вы можете выбрать, чтобы реализовать идею «слушая поток событий» (ленивые последовательности, потоки событий, core.async и т. д.) Дело в том, что вы используете в этом случае ленивые последовательности и фьючерсы; Я предлагаю вам выбрать только один, например, используя только ленивую последовательность, без фьючерсов.
  • вы используете рекурсию для вас. Поскольку JVM не имеет оптимизации хвостового вызова, это в конечном итоге приведет к удалению вашего стека (у вас закончится нехватка памяти), я рекомендую вместо этого использовать loop/recur.

Я бы лично пойти на core.async или manifold, которые больше подходят для событий потоков, чем фьючерсов/обещания. Если ваша модель отображения поддерживает ее, я бы поместил отображаемую информацию в агент или атом, который будет опроса каждого кадра для обновления дисплея и обновлен для каждого события ввода пользователя. Трудно дать вам более точные указания без дополнительной информации о том, как работает ваша игра.

И, наконец, если вы никогда раньше не делали такого рода логику игры, я бы предложил вам выяснить, как это сделать на языке, который вы знаете, а затем сделать это в Clojure :) Изучая Clojure и асинхронный поток управления при том же время может быть слишком большим ИМХО.