将列表中每个元素的值与列表中的每个其他元素进行比较并更新它 (f#)

Comparing values of each element in a list with every other element within the list and updating it (f#)

我目前正在尝试学习 F#,并且正在尝试制作一个在控制台中玩的非常简单的游戏。我正在尝试进行一些基本的碰撞检测,运行 我计划这样做:

将迭代游戏对象列表中具有特定标签的每个元素,如果发现游戏对象列表中的另一个元素与第一个对象共享相同的坐标,则第一个对象将放回其旧职位。

所以类型是这样的:

type Object = {
x : int;
y : int;
model : char;
}

并且游戏中的每个对象都在游戏对象列表中使用这种类型(对象具有更新方法等)但是当尝试进行碰撞检测时,我正在努力使用默认的 none 方法列表操作确实有效,我假设我需要以某种方式对特定标记进行模式匹配,然后再次遍历列表以检查坐标是否匹配?

任何想法或指示或任何形式的帮助都将不胜感激。

不太清楚您想做什么,但下面的示例应该会给您一些想法。

我假设您有 objects,这是游戏中所有对象的列表。这包括您要移动的具有给定 model 值的一个对象。以下函数获取 modelToMove 作为参数(以标识应移动的对象)以及对象的新 X 和 Y 坐标以及所有对象的列表。

如果在新的 X 和 Y 坐标处有东西,它只是 returns 原始对象。否则,它将具有给定 model 的对象移动到新位置:

let moveObject modelToMove (newX, newY) objects = 
  let blocked = objects |> List.exists (fun o -> o.x = newX && o.y = newY)
  if blocked then objects 
  else  
    objects |> List.map (fun o ->
      if o.model = modelToMove then { o with x = newX; y = newY }
      else o)

要检查仓位是否被封锁,我们使用 List.exists。要创建包含新的更新对象位置的列表,我们使用 List.map.

我认为按照这些思路可以做到:

type GameObjectType =
    | Player
    | Bullet
    | Wall
    // etc.

type Position =
    {
        x : int
        y : int
    }

type GameObject =
    {
        objectType : GameObjectType
        position : Position
    }

type Rectangle = Position * Position // rectagle is defined by two opposite corners.

type IntersectionResult =
    | NoIntersection
    | Rectangle of Rectangle

type CollisionHandler =
    {
        intersect : GameObject -> GameObject -> IntersectionResult
        handleCollision : (GameObject * GameObject) -> Rectangle -> (GameObject * GameObject)
    }

let handleCollisions (handler : CollisionHandler) (objects : List<GameObject>) =
    // Handle collision of two objects a and b.
    let handleCollision (a, b) =
        match handler.intersect a b with
        | NoIntersection -> (a, b)
        | Rectangle r -> handler.handleCollision (a, b) r

    // Handle collision of object a with the list c by iterating through
    // the list and updating position of object a and current element of the list r.
    let handleCollisions (a, c) =
        c
        |> List.fold (fun acc r -> 
                        let (n, m) = handleCollision (fst acc, r)
                        (n, m :: (snd acc))
                        ) (a, [])

    let rec inner processed remaining =

        match remaining with
        | [] -> processed
        | h :: t ->
            let (newH, newT) = handleCollisions (h, t)
            inner (newH :: processed) newT

    inner [] objects

您将需要提供确定碰撞的函数:intersect 以及如何处理它们:CollisionHandler.

中的 handleCollision