简易语言

数字沟通

 

游戏中最近可达点(用erlang写一个简单算法)

游戏中有点击障碍点,人物走到离障碍物最近点的算法。我这给一个简单的算法,这个问题可以复杂化,另外这个问题应该由客户端来完成。

如图,玩家在b点,点击了a点,a在一个障碍区(红色,玩家只能在障碍区外移到)。这时候玩家应该走到c点,我们就需要计算出c点,一个简单的数学题,用什么语言都没几行代码,我就用erlang写一下。


障碍物通常都不规则的,我们只能从a点开始一个个点测试,直到不是障碍点,也就是x自增,y=x*tan(A),然后测试这个点,地图数据都是静态的数据,方便测试,这里就写死一个x为障碍结束的地方作为障碍检测函数。

我们还需要一个记录表示点,tan函数在erlang中是有的,但其实可以不用,我们就直接要一个比值,但需要一个向上取整的函数,据说是round函数,但测试一下,不行,难道是因为不是最新otp
D:\NetBeanPj\mytest\src>erl
Eshell V5.8.1.1  (abort with ^G)
1> round(1.2).
1

所以这里我们要写的一个辅助函数,最后就是我们的重点,取最近点,用一个列表解析就够了,剩下的就看具体实现吧,还可以写个测试函数,这次就不写成单元测试了。好的我们看代码:
-module(nearst_point).

-export([ceil/1, is_barrier/1, nearst_point/2]).

-export([p1/0, p2/0, test_1/0]).

%% 一个点
-record(point,{
    x,
    y
              }).

%% 向上取整
ceil(Num) ->
    Num1 = round(Num),
    case Num1 >= Num of
        true ->
            Num1;
        false ->
            Num1+1
    end.

%% 判断是否是障碍物
is_barrier(Point) ->
    Point#point.x =/= 5 .

%% 查找最近点
nearst_point(Pointa,Pointb) ->
    Tan = (Pointa#point.x - Pointb#point.x)/(Pointa#point.y - Pointb#point.y),
    case Pointa#point.x > Pointb#point.y of
        true ->
            MaxX = Pointa#point.x,
            MinX = Pointb#point.x;
        false ->
            MaxX = Pointb#point.x,
            MinX = Pointa#point.x
    end,
    try
        [
            begin
                Point = #point{
                    x = X,
                    y = ceil(X*Tan)},
                case is_barrier(Point) of
                    true ->
                        ok;
                    false ->
                        throw(Point)
                end
            end|| X <- lists:seq(MinX, MaxX)]
    catch
        throw: Point ->
            io:format("~p", [Point]),
            Point
    end.

%% 下面函数测试用,可以改成单元测试,这里就免了
p1() ->
    #point{
        x = 1,
        y = 9}.

p2() ->
    #point{
        x = 15,
        y = 25}.

test_1() ->
    nearst_point(p1(),p2()).

编译和测试
2> c(nearst_point).
{ok,nearst_point}
3> nearst_point:test_1().
{point,5,5}{point,5,5}
4>

我们的测试如预期的在5那个点得到,好像有个小问题,怎么这个点输出了两次?哦,这不是问题,一个点是代码里的io输出的,一个点是返回给shell,shell的输出,看来写代码的人太懒,疑惑也会增多啊。在nearst_point中用到了一个小技巧,就是用throw来跳出循环(这个在erlang中还是挺有意思),这次到这,应该说写的很基础很难看。下次会来点有意思的,欢迎大家学习erlang。


一种更好的态度,更好的学习、思维方式。它会是网络极佳的生存方式,你喜欢就对。

posted on 2011-06-24 23:54 yangyusong 阅读(2866) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 

导航

统计

常用链接

留言簿(3)

随笔分类

随笔档案

文章分类

搜索

最新评论

阅读排行榜

评论排行榜