Clojure 蛇跳过位置

2024-03-15

我是 Clojure 初学者,我一直在玩这里介绍的贪吃蛇游戏代码https://github.com/stuarthalloway/programming-clojure/blob/master/src/examples/snake.clj https://github.com/stuarthalloway/programming-clojure/blob/master/src/examples/snake.clj。当我运行游戏时,蛇在移动时似乎会跳过位置,它并不像我预期的那样逐格移动。但是,当我转动蛇并按住方向键时,它开始正常运行并逐格移动,一旦我松开按键,它就会再次开始跳跃。我想这与 Swing 绘制组件或处理事件的方式有关,但我无法弄清楚或调试它。我希望我的蛇能够一格一格地移动,即使我没有按住键,也不会跳跃。这是我的代码,它与我给出的链接基本相同,但对空间和墙壁进行了一些小的修改:

(ns app.core
  (:import (java.awt Color Dimension)
           (javax.swing JPanel JFrame Timer JOptionPane WindowConstants)
           (java.awt.event ActionListener KeyListener))
  (:use app.util.import-static))
(import-static java.awt.event.KeyEvent VK_LEFT VK_RIGHT VK_UP VK_DOWN)

; ---------------------------------------------------------------------
; functional model
; ---------------------------------------------------------------------
; constants to describe time, space and motion
(def width 19)
(def height 10)
(def point-size 25)
(def turn-millis 150)
(def win-length 500)
(def dirs {VK_LEFT  [-1 0]
           VK_RIGHT [1 0]
           VK_UP    [0 -1]
           VK_DOWN  [0 1]})

; math functions for game board
(defn add-points [& pts]
  (vec (apply map + pts)))

(defn point-to-screen-rect [pt]
  (map #(* point-size %)
       [(pt 0) (pt 1) 1 1]))

; function for creating an apple
(defn create-apple []
  {:location [(rand-int width) (rand-int height)]
   :color (Color. 210 50 90)
   :type :apple})

; function for creating a snake
(defn create-snake []
  {:body (list [1 1])
   :dir [1 0]
   :type :snake
   :color (Color. 15 160 70)})

; function for moving a snake
(defn move [{:keys [body dir] :as snake} & grow]
  (assoc snake :body (cons (add-points (first body) dir)
                           (if grow body (butlast body)))))

; function for checking if the player won
(defn win? [{body :body}]
  (>= (count body) win-length))

; function for checking if the player lost the game,
; which means that head of the snake has overlaped
; with its body
(defn head-overlaps-body? [{[head & body] :body}]
  (contains? (set body) head))

(defn out-of-bounds? [{[head] :body}]
  (or (< (head 0) 0)
      (> (head 0) width)
      (< (head 1) 0)
      (> (head 1) height)))

(defn lose? [snake]
  (or (head-overlaps-body? snake) (out-of-bounds? snake)))

; function for checking if the snake eats an apple
; (check if head location equals apple location)
(defn eats? [{[snake-head] :body} {apple :location}]
  (= snake-head apple))

; function that changes direction
(defn turn [snake newdir]
  (assoc snake :dir newdir))

; ---------------------------------------------------------------------
; mutable model
; ---------------------------------------------------------------------
; function that resets the game state
(defn reset-game [snake apple]
  (dosync (ref-set snake (create-snake))
          (ref-set apple (create-apple)))
  nil)

; function for updating direction of snake
(defn update-direction [snake newdir]
  (when newdir (dosync (alter snake turn newdir))))

; function for updating positions of snake and apple
(defn update-positions [snake apple]
  (dosync
    (if (eats? @snake @apple)
      (do (ref-set apple (create-apple))
          (alter snake move :grow))
      (alter snake move)))
  nil)

; ---------------------------------------------------------------------
; gui
; ---------------------------------------------------------------------
; function for making a point on the screen
(defn fill-point [g pt color]
  (let [[x y width height] (point-to-screen-rect pt)]
    (.setColor g color)
    (.fillRect g x y width height)))


; function for painting snakes and apples
(defmulti paint (fn [g object & _] (:type object)))

(defmethod paint :apple [g {:keys [location color]}]
  (fill-point g location color))

(defmethod paint :snake [g {:keys [body color]}]
  (doseq [point body]
    (fill-point g point color)))

; game panel
(defn game-panel [frame snake apple]
  (proxy [JPanel ActionListener KeyListener] []
    (paintComponent [g]
      (proxy-super paintComponent g)
      (paint g @snake)
      (paint g @apple))
    (actionPerformed [e]
      (update-positions snake apple)
      (when (lose? @snake)
        (reset-game snake apple)
        (JOptionPane/showMessageDialog frame "Game over!"))
      (when (win? @snake)
        (reset-game snake apple)
        (JOptionPane/showMessageDialog frame "You win!"))
      (.repaint this))
    (keyPressed [e]
      (update-direction snake (dirs (.getKeyCode e))))
    (getPreferredSize []
      (Dimension. (* (inc width) point-size)
                  (* (inc height) point-size)))
    (keyReleased [e])
    (keyTyped [e])))

; main game function
(defn game []
  (let [snake (ref (create-snake))
        apple (ref (create-apple))
        frame (JFrame. "Snake")
        panel (game-panel frame snake apple)
        timer (Timer. turn-millis panel)]
    (doto panel
      (.setFocusable true)
      (.addKeyListener panel))
    (doto frame
      (.add panel)
      (.pack)
      (.setVisible true)
      (.setResizable false)
      (.setDefaultCloseOperation WindowConstants/EXIT_ON_CLOSE))
    (.start timer)
    [snake, apple, timer]))

EDIT:

也在这里尝试了这个实现http://java.ociweb.com/mark/programming/ClojureSnake.html http://java.ociweb.com/mark/programming/ClojureSnake.html它也有同样的问题。这可能是与 Swing 相关的问题。我正在考虑使用 Seesaw 库,但由于它是 Swing 的包装器,因此问题可能会继续存在。


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Clojure 蛇跳过位置 的相关文章

  • Gson.toString() 给出错误“IllegalArgumentException:多个名为 mPaint 的 JSON 字段”

    我想将自定义对象转换为字符串并保存在 SharedPreferences 中 这是我的最终目标 我尝试了下面的行但失败了 String matchString gson toJson userMatches Logcat 10 11 15
  • 使用比较器对对象进行排序给出空指针

    我正在尝试对包含 3 张卡的 ArrayList 进行排序 我正在用比较器来做这件事 这是否太过分了 Card getRank 返回 2 到 14 之间的整数 我完全不知道哪里出了问题 我之前已经成功完成了这个 并与我的其他代码进行了比较
  • 如何在 Groovy 中的 JSON Converter 方法中保留字母大小写?

    我正在尝试将 groovy 对象解析为 JSON 属性名称不遵循正确的驼峰式大小写形式 class Client String Name Date Birthdate 当我使用这个时 Client client new Client Nam
  • java.sql.SQLException: ORA-01005: 给定的密码为空;登录被拒绝

    我在尝试连接到数据库时遇到以下异常 java sql SQLException ORA 01005 null password given logon denied at oracle jdbc driver T4CTTIoer proce
  • 使用 Gson 序列化时如何公开类名

    我的场景非常复杂 但总结如下 我试图了解编译器的源代码 并了解每个 AST 节点代表什么 我正在生成不同程序的 AST 的 JSON 序列化 然后检查可视化的 JSON 输出 它工作得很好 除了一个问题是在 Gson 中生成的 JSON 数
  • 无法解析配置“:app:debugRuntimeClasspath”的所有文件。问题

    我的 android studio 遇到了下一个问题 导致 org gradle api internal artifacts ivyservice DefaultLenientConfiguration ArtifactResolveEx
  • RSA 加密-解密:BadPaddingException:数据必须以零开头

    对于一个被问了很多次的问题 我很抱歉向您询问您的技能 我有一个关于 RSA 加密的问题 我已经检查过有关此问题的其他主题 但没有找到任何有用的答案 我希望你能帮助我 我想读取一个文件 加密其内容 然后解密它并将这些解密的字节放入一个新文件中
  • Java 中的本机方法

    我花了一些时间学习什么是 Java Native 方法以及它们是在平台相关代码 主要是 C 中实现的 但是我在哪里可以找到这些 Java 的本机实现呢 例如 Thread 类的 sleep long millis 方法是本机的 但它的实现代
  • 文件保存在文件系统中 VS 保存在数据库中

    我正在设计一个 servlet 或 Struts2 中的操作 用于文件 图像 文档等 下载 但我想知道哪种更好的方法可以将文件保留在文件系统和数据库中 只需保留文件的路径或将文件保留在数据库中 如 BLOB 我知道当我查询数据库时 哪里的
  • Java 将字节转换为二进制安全字符串

    我有一些以字节为单位的数据 我想将它们放入Redis中 但是Redis只接受二进制安全字符串 而我的数据有一些二进制非安全字节 那么如何将这些字节转换为二进制安全字符串以便将它们保存到 Redis 中呢 Base64 对我有用 但它使数据更
  • 可以混合使用 JVM 语言吗?即:Groovy 和 Clojure

    我知道你可以轻松地混合groovy java clojure java 无论什么JvmLang java 这是否也意味着我也可以让 clojure 和 groovy 代码进行交互 如果我使用 Grails 或 jRoR 我也可以在该环境中使
  • 如何连接hibernate和DB2

    我正在运行一个使用 struts 和 hibernate 的应用程序 我目前正在使用 Derby 数据库 现在我必须转向 DB2 数据库 请告诉我 我必须做什么配置 休眠配置文件 我必须设置任何类路径吗 多变的 我知道 DB2 有两个 ja
  • 在 javafx 中注册鼠标处理程序,但处理程序不是内联的

    我有一个 JavaFX 应用程序变得有点大 我想保持代码的可读性 我有一个折线图 我希望内置缩放功能 该功能在单击鼠标时发生 我知道我需要向图表注册鼠标侦听器 我无法从 Oracle 示例中弄清楚什么 即如下所示 http docs ora
  • Spring @Value 添加验证小于

    我使用以下属性值注入 我如何向此操作添加小于验证 我的意思是我想设置一个验证user maxpassiveday可以说 财产价值不得低于 100 Value user maxpassiveday int maxpassiveday 使用Sp
  • 比较和删除列表和数组java中不存在的元素

    我有一个String数组和一List
  • 线程睡眠阻止我的 Swing 应用程序执行

    我的应用程序发生的事情是有道理的 但我不知道如何修复它 以下是我的应用程序功能的简要描述 计时器窗口应显示在屏幕右下角并显示实时时间 一小时后 它应该执行一些操作 我还没有决定该操作 我面临的问题是定时器 java当我刷新实时计时器的秒数时
  • Spring Boot如何加入自定义查询

    我需要创建一个端点 该端点按州返回人口普查数据以及城市列表 我目前使用两个端点来获取此数据 目前回应 自定义查询一 censusByState id 1 code 11 name Rond nia statePopulation 18152
  • Maven `help: effective-pom` 只为单个项目生成,而不是所有项目

    我想为多模块构建中的所有子项目生成有效的 pom The help effective pom文档here http maven apache org plugins maven help plugin usage html The hel
  • 对 Java 协议缓冲区对象进行一些小更改

    我想在 Java 协议缓冲区对象树的深处进行一个小更改 我可以使用 getBuilder 方法来创建一个新对象 该新对象是旧对象的克隆并进行一些更改 当深入完成此操作时 代码会变得丑陋 Quux Builder quuxBuilder fo
  • 在Java的System.out中以表格格式输出

    我正在从数据库获取结果 并希望将数据作为 Java 标准输出中的表输出 我尝试过使用 t 但我想要的第一列的长度变化很大 有没有办法将其显示在类似输出的漂亮表格中 Use System out format http java sun co

随机推荐

  • 用Lua检查文件是否存在

    如何使用Lua检查文件是否存在 Try function file exists name local f io open name r if f nil then io close f return true else return fa
  • 根据特定条件将内容从 list1 复制到 list2

    如果我有两个如此定义的泛型列表 type pMyList record a b integer c string end TMyList TList
  • Delphi thiscall 调用约定

    我需要调用非静态 C 成员函数 因此我需要使用thiscall调用约定 Delphi 不支持这种调用约定 因此 在调用任何成员函数之前 我必须手动将参数推送到堆栈中 asm mov ecx myClassPointer end 这工作正常
  • 为什么 getStringExtra 没有给出正确的输出?

    我试图将一些字符串从一个意图传递到另一个意图 但 adt 说 键文本需要字符串 但值是 android text SpannableString 返回默认值 但我使用字符串作为键 而不是它声称的那样 这是我的第一个活动的代码 private
  • 避免导入“sys.path.append(..)”

    这不是我第一次畏缩imports在Python中 但我想这是一个有趣的用例 所以我想在这里询问它以获得更好的见解 我的项目结构如下 sample project src init py module1 init py utils py mo
  • 如何在页面刷新/加载时刷新验证码图像?

    我想强制我的网站在每次加载时刷新验证码图像 因此我有一个由 onload 事件触发的 javascript 方法 这里我有以下行 document getElementById yw0 button click Firebug 没有检测到任
  • 高效地按行应用函数

    我有一个包含多个列的数据框 其中包含一个诊断的信息 条目是TRUE FALSE or NA 我创建了一个向量 将这些列总结如下 如果患者在某个时间被诊断出来 TRUE then TRUE 如果唯一有效的条目是FALSE then FALSE
  • 如何在SWI-Prolog中启用所有统一中的发生检查?

    根据维基百科 https en wikipedia org wiki Occurs check 为所有统一提供声音统一的实现是 Qu Prolog 和 Strawberry Prolog 以及 可选地 通过运行时标志 XSB SWI Pro
  • 如何使我的 SVG 移动设备具有响应能力

    我想为网站制作 svg 动画 但 svg 不支持移动响应 它延伸出背景 从而使网站的宽度超出了我的预期 我认为很可能我在视口或宽度和高度上做错了什么 但我不知道哪里出了问题 此外 当我将 chrome 浏览器最小化到移动屏幕宽度尺寸时 它在
  • 所需的 Bluemix Analytics for Apache Spark 日志文件信息

    我在调试我的 Spark 笔记本时想要更多信息 我找到了一些日志文件 ls HOME notebook logs 这些文件是 bootstrap nnnnnnnn nnnnnn log jupyter nnnnnnnn nnnnnn log
  • 矩阵到欧拉角

    我正在尝试从旋转矩阵中提取欧拉角 我的约定 矩阵列主 坐标系右手 正角右手 旋转顺序 YXZ 首先是航向 然后是姿态 然后是倾斜 我发现了这个 但无法使用它 因为它们使用其他轴顺序 http www euclideanspace com m
  • 我应该使用 Eclipse 插件(或 OSGi Bundles)作为普通的依赖管理工具吗?

    它再次发生了 我加入了一个新项目 该项目由几个具有相互依赖性的普通 Eclipse Java 项目组成 所有项目都通过项目构建路径进行管理 我发现这一切有点混乱 当谈到运行配置时 你就进入了地狱 过去 我一直坚持创建插件项目 而不是普通的
  • 在 Vuejs 中使用 mixins

    我目前正在学习如何使用 Vuejs 开发应用程序 我有一个 main js 文件 其中包含用于设置 Vue js 的代码 我使用新文件 api js 创建了一个新目录 mixins 我想将其用作 mixin 以便每个组件都可以使用函数来访问
  • 为什么 git 一直告诉我它是“在后台自动打包存储库以获得最佳性能”?

    Note I don t认为这是重复的这个问题 https stackoverflow com questions 8633981 what does auto packing the repository for optimum perf
  • 如何使用反射(镜像)来访问 Dart 类中的方法名称?

    我需要 获取 Dart 类中的方法 我怎样才能做到这一点 我希望能够调用这些方法 我可以看一个例子吗 这是一个简单的可复制粘贴代码示例 import dart mirrors import dart io main var im refle
  • 使用 ajax 时 csrf 令牌无效

    我开始学习NodeJs在我对 js 的了解的推动下 我开始编写一些代码来创建用户注册逻辑 基本上我已经配置了ExpressJS通过以下方式 const express require express const app express co
  • 无法重新绑定滚动事件?

    我想在ajax调用中重新绑定窗口滚动事件 window scroll function column height first column height screenTop window scrollTop window height w
  • Python正则表达式不匹配

    这是我确信我错过了一些简单内容的事情之一 但是 在下面的示例程序中 我尝试使用 Python 的 RE 库来解析字符串 line 以获取浮点百分号之前的数字 即 90 31 但代码总是打印 不匹配 我也尝试了其他几个正则表达式 所有结果都相
  • 方法名称是否隐式转换为委托类型?

    我在理解代表方面有点困难 我有一个委托 当输入 y 字符时我将调用它 public delegate void respondToY string msgToSend private respondToY yHandler 我有一个订阅方法
  • Clojure 蛇跳过位置

    我是 Clojure 初学者 我一直在玩这里介绍的贪吃蛇游戏代码https github com stuarthalloway programming clojure blob master src examples snake clj h