如果这个问题不适合这个网站,我很抱歉,但我不知道还有什么地方可以问。我很困惑,我使用 min 和 max 我相信是正确的。当我用箭头键移动武器时,当它向右或向下移动时,这条线似乎可以找到。如果有人知道如何修复它或只是让我走上正轨,我将不胜感激。对于任何感兴趣的人,我正在为一个游戏创建这个程序,我需要武器的视线。
编辑:
我正在尝试实现一种状态,我可以使用 w、a、s、d 键移动 C(角色)和箭头键移动 W(武器)。最终,当我添加敌人时,角色和武器之间的线将用于查看它们是否在攻击范围内。就像向任何方向射击的枪。但是当我将 C 移动到它的当前状态时,线路不再连接到 C。我不确定这是为什么。
open System
let [<Literal>] CharacterN = ConsoleKey.W
let [<Literal>] CharacterE = ConsoleKey.D
let [<Literal>] CharacterS = ConsoleKey.S
let [<Literal>] CharacterW = ConsoleKey.A
let [<Literal>] WeaponN = ConsoleKey.UpArrow
let [<Literal>] WeaponE = ConsoleKey.RightArrow
let [<Literal>] WeaponS = ConsoleKey.DownArrow
let [<Literal>] WeaponW = ConsoleKey.LeftArrow
type Point =
{ X : int
Y : int }
let p1 = { X = 0; Y = 0 }
let p2 = { X = 10; Y = 10 }
let rec main p1 p2 =
Console.Clear()
let dx = min p1.X p2.X - max p1.X p2.X
let dy = min p1.Y p2.Y - max p1.Y p2.Y
for x in min p1.X p2.X .. max p1.X p2.X do
let y = min p1.X p2.X + dy * (x - min p1.X p2.X) / dx
Console.SetCursorPosition(x, y)
printf "."
Console.SetCursorPosition(p1.X, p1.Y)
printf "C"
Console.SetCursorPosition(p2.X, p2.Y)
printf "W"
match Console.ReadKey().Key with
| CharacterN -> main { X = p1.X; Y = p1.Y - 1 } p2
| CharacterE -> main { X = p1.X + 1; Y = p1.Y } p2
| CharacterS -> main { X = p1.X; Y = p1.Y + 1 } p2
| CharacterW -> main { X = p1.X - 1; Y = p1.Y } p2
| WeaponN -> main p1 { X = p2.X; Y = p2.Y - 1 }
| WeaponE -> main p1 { X = p2.X + 1; Y = p2.Y }
| WeaponS -> main p1 { X = p2.X; Y = p2.Y + 1 }
| WeaponW -> main p1 { X = p2.X - 1; Y = p2.Y }
| _ -> ()
main p1 p2
Console.Read() |> ignore
最佳答案
我认为您的代码有几个问题。可能最重要的一个是行的逻辑:
let y = min p1.X p2.X + dy * (x - min p1.X p2.X) / dx
显然它应该是这样的
y = y0 + (x-x0)*dy/dx
即第一个术语应该是关于 Y
而不是 X
的东西。不幸的是,对于您的循环逻辑,它应该是具有较小 X
的点的 Y
。说起来没那么容易。恕我直言,使用负步更容易修复循环。
另一个天真的假设是,您总是可以画一条线,因为每个 x
都有一些 y
。 dy > dx
时显然不是这样。此外,当dx
为0
时出现垂直线,代码将失败。最受欢迎Bresenham's line algorithm要求您将这些情况视为明显不同。这是处理这些情况的简单实现:
let drawLine p1 p2 =
let dx = p2.X - p1.X
let dy = p2.Y - p1.Y
if((dx <> 0) || (dy <> 0)) then
if abs(dx) >= abs(dy) then
let step = if (p1.X < p2.X) then 1 else -1
for x in p1.X ..step.. p2.X do
let y = p1.Y + dy * (x - p1.X) / dx
Console.SetCursorPosition(x, y)
printf "."
else
let step = if (p1.Y < p2.Y) then 1 else -1
for y in p1.Y .. step .. p2.Y do
let x = p1.X + dx * (y - p1.Y) / dy
Console.SetCursorPosition(x, y)
printf "."
至于其他问题,您可能希望将点的位置限制在 0 和某个最大值之间的某个可见区域。使用负值或大于缓冲区大小的值调用 SetCursorPosition
会使您的应用崩溃。
关于algorithm - 如何使用带最小值/最大值的画线算法? F#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54261302/