Сравнение значений каждого элемента в списке с любым другим элементом в списке и его обновление (f#)

В настоящее время я пытаюсь изучить F# и пытаюсь сделать очень простую игру, в которую можно играть на консоли. Я пытаюсь настроить и запустить элементарное обнаружение столкновений, которое я планировал работать как таковое:

Каждый элемент с определенным тегом в списке игровых объектов будет повторяться, и если будет обнаружено, что другой элемент в списке игровых объектов имеет ту же координату, что и первый объект, первый объект будет возвращен в его старое положение.

Итак, тип примерно такой:

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

И каждый объект в игре использует этот тип в списке игровых объектов (объекты имеют метод обновления и т. д.). Однако при попытке выполнить обнаружение столкновений я борюсь с подходом, поскольку ни одна из операций списка по умолчанию действительно не работает, и я предполагаю, что я нужно каким-то образом сопоставить шаблон для определенного тега, а затем снова пройтись по списку, проверяя совпадение в координатах?

Любые идеи или указатели или помощь любого рода будут высоко оценены.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Не совсем понятно, что вы хотите сделать, но следующий пример должен дать вам некоторое представление.

Я предполагаю, что у вас есть objects, который представляет собой список всех объектов игры. Сюда входит один объект с заданным значением model, который вы хотите переместить. Следующая функция получает modelToMove в качестве аргумента (для определения объекта, который необходимо переместить) вместе с новыми координатами X и Y для объекта и списком всех объектов.

Если в новых координатах X и Y есть что-то, он просто возвращает исходные объекты. В противном случае он перемещает объект с данным 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.

Спасибо, мое объяснение проблемы было не совсем хорошим, извините, но это был именно тот подход, который я искал, спасибо!

user10632986 24.01.2019 21:21

Я думаю, что что-то в этом роде подойдет:

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 и способы их обработки: handleCollision в CollisionHandler.

Другие вопросы по теме