You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Racket中设计支持点击交互的数独游戏网格?

DrRacket 数独交互网格实现方案

你可以直接基于DrRacket自带的2htdp/universe(大爆炸交互框架)和2htdp/image(绘图库)实现需求,完全兼容你现有的SudokuNumber数据结构和check-answer校验逻辑,核心实现步骤如下:


1 前置状态定义

首先补充定义世界状态结构体,用来存储运行时的所有交互状态:

; 世界状态定义:sudoku-list是你现有的SudokuNumber列表,active-pos是当前激活的单元格坐标,fixed-positions是初始固定不可修改的提示数坐标列表
(define-struct world [sudoku-list active-pos fixed-positions])

fixed-positions可以在你随机生成数独的时候同步生成,把初始有数字的坐标都存进去,用来限制用户不能修改提示格。


2 核心辅助函数

先写一个用来更新数独列表的通用函数,用户修改单元格的时候直接调用,完全兼容你现有的数据结构:

; 输入:原始SudokuNumber列表、要修改的单元格坐标、新数字
; 输出:更新后的SudokuNumber列表,可直接传给你现有的check-answer函数使用
(define (update-sudoku sudoku-list target-pos new-num)
  (map (lambda (sn)
         (if (equal? (SudokuNumber-position sn) target-pos)
             (make-SudokuNumber new-num target-pos)
             sn))
       sudoku-list))

3 交互事件处理

3.1 鼠标点击事件(激活单元格)

实现点击单元格激活的逻辑,同时自动过滤不可编辑的固定格:

(define (handle-mouse current-world x y event)
  (if (mouse=? event "button-down")
      ; 以下像素转坐标的参数可根据你自己的网格绘制尺寸调整,示例中假设每个单元格边长40px,网格整体左上角偏移(20,20)
      (let* ([grid-x (- (quotient (- x 20) 40) 4)]
             [grid-y (- 4 (quotient (- y 20) 40))] ; 这里做y轴翻转适配,和你(-4,-4)到(4,4)的坐标体系对齐
             [clicked-pos (list grid-x grid-y)])
        (if (and (>= grid-x -4) (<= grid-x 4) ; 点击在网格范围内
                 (>= grid-y -4) (<= grid-y 4)
                 (not (member clicked-pos (world-fixed-positions current-world)))) ; 不是固定不可编辑格
            (make-world (world-sudoku-list current-world) clicked-pos (world-fixed-positions current-world))
            current-world))
      current-world))

3.2 键盘输入事件(修改/删除数字)

实现激活单元格后的输入逻辑,仅支持1-9数字输入和删除操作:

(define (handle-key current-world key)
  ; 没有激活单元格时直接忽略所有按键
  (if (not (world-active-pos current-world))
      current-world
      (cond
        ; 按1-9更新单元格数字
        [(member key '("1" "2" "3" "4" "5" "6" "7" "8" "9"))
         (make-world (update-sudoku (world-sudoku-list current-world)
                                    (world-active-pos current-world)
                                    (string->number key))
                     (world-active-pos current-world)
                     (world-fixed-positions current-world))]
        ; 按退格/删除键清空单元格
        [(or (key=? key "\b") (key=? key "delete"))
         (make-world (update-sudoku (world-sudoku-list current-world)
                                    (world-active-pos current-world)
                                    0) ; 如果你用#f或者其他值表示空单元格,替换此处的0即可
                     (world-active-pos current-world)
                     (world-fixed-positions current-world))]
        [else current-world])))

4 网格绘制

你只需要补充绘制函数即可,核心逻辑是:

  • 遍历所有SudokuNumber元素,每个元素绘制为一个方格
  • 当前激活的方格用不同颜色的边框高亮
  • 固定提示格的数字用黑色绘制,用户输入的数字用蓝色绘制
  • 如果需要校验输入合法性,可直接调用你现有的校验逻辑,把非法数字标红即可

绘制完成后,用大爆炸函数启动程序即可:

(big-bang (make-world 你的初始SudokuNumber列表 #f 你的固定格坐标列表)
  [on-draw 你写的绘制函数]
  [on-mouse handle-mouse]
  [on-key handle-key])

内容的提问来源于stack exchange,提问作者Carson_He

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 08:45:03