根据路线位置瞬时状态模拟运动算法

位置路线图如下所示,实际的可能更复杂,但不脱离本模型范围;

image

其中的位置点有以下特点:

  1. 每一时刻,每个位置只能有两个状态:0-没有物体, 1-有物体;
  2. 每一时刻,每个位置最多只能有一个物体;
  3. 位置A,C,H这样作为起始点的位置,它可以作为生产者,也就是说,它可以生产物体;
  4. 位置H,J这样作为结束点的位置,它可以作为消费者,也就是说,它可以消费物体;
  5. 中间的位置,比如B,E,F这样的点,它不能直接生产物体,物体的来源必须是上一个节点;
  6. 如果两次信号中,以上第4条所描述的位置点突然多出了物体或者少了物体,则判定为信号异常;

 

分析三种典型情况:

情况一:先后两个瞬时信号情况如下

image

得到运动结论:

        运动情况:A=>B,  C=>D, D=>E, E=>F

 

情况二:先后两个瞬时信号情况如下

image

得到运动结论:

     运动情况:A=>B, D=>E, E=>F, G=>H

     生产情况:A

     消费情况:H, J

 

情况三:先后两个瞬时信号情况如下

image

得到运动情况:

      运动情况: H=>G, G=>F

      消费情况:J

 除了以上能够分析到的正常位置点外,还有一个点D,它从无到有,但上一个位置C本身就没有物体,它不可能给它,因此可判定为信号异常;

 

有了以上的假定和规则后,下面可以进行算法分析过程了。

 

第一步:存储路线图信息

/**********************************************************
 ** 所有的位置点
 **     procucer  可作为生产者的位置点
 **     consumer  可作为消费者的位置点
 **********************************************************/
var sites = new Array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
var producer = new Array('A', 'C', 'H');  
var consumer = new Array('H', 'J');

/***********************************************
 ** 所有的移动路径
 **********************************************/
var roads = new Array();
roads[0] = new Array('A', 'B', 'E', 'F', 'I', 'J');
roads[1] = new Array('C', 'D', 'E');
roads[2] = new Array('F', 'G', 'H');
roads[3] = new Array('H', 'G', 'F');

 

 

 

第二步:分析单个信号的运动情况

/****************************************************
**  从移动开始点寻找移动路径----迭代
**            本实现由于js的对象作用域问题,递归中没有将siteMoveWay数组作为返回值
****************************************************/
function getSiteMoveRoad2(site :String, siteMoveWay:Array){
    itrCount += 1; //迭代次数+1;
    //对路线进行遍历
    for(var road:Array in roads){
        var siteIndexOfRoad:int = -1;
        for(var i=0; i<road.length; i++){            
            if(road[i] == site){
                siteIndexOfRoad = i;
                break;
            }
        }
        //找到了运动起点
        if(siteIndexOfRoad > -1){
            if(siteIndexOfRoad == road.length - 1){//自己消费
                if(isSiteExistInArray(road[siteIndexOfRoad], consumer)){
                    if(itrCount == 1){//此时没迭代,它有可能是其它路径的起点
                        isPossibleConsumeSelf = true;
                    }
                    else{ //此时已经迭代多次,它必定自我消费
                        siteMoveWay.Add(site + " ==> Null");
                        isTheMoveWayFound = true;
                    }
                }
            }
            else{
                var nextSite = road[siteIndexOfRoad + 1];
                if(isSiteExistInArray(nextSite, moveToSites)){//下一个点为目的点
                    siteMoveWay.Add(site + " ==> " + nextSite);
                    moveToSites.remove(nextSite);
                    possibleTarget.remove(nextSite);
                    isTheMoveWayFound = true;
                }
                else if(isSiteExistInArray(nextSite, bridgeSites)){//下一个点为桥梁点
                    siteMoveWay.Add(site + " ==> " + nextSite);
                    getSiteMoveRoad(nextSite, siteMoveWay);
                }    
            }
        }
        if(isTheMoveWayFound){//处理桥梁点的情况
            possibleTarget.remove(site);
            break;
        }
    }
}

/****************************************************
**  从移动开始点寻找移动路径----迭代
**            本实现由于js的对象作用域问题,递归中没有将siteMoveWay数组作为返回值
****************************************************/
function getSiteMoveRoad(site :String, siteMoveWay:Array){
    itrCount = 0;
    print('getSiteMoveRoad: ' + site);
    getSiteMoveRoad2(site, siteMoveWay);
    if(!isTheMoveWayFound && isPossibleConsumeSelf){//此时确定,它是自我消费点
        siteMoveWay.Add(site + " ==> Null");
        isTheMoveWayFound = true;
        possibleTarget.remove(site);
        isPossibleStart = false;
    }
}

 

 

第三步:所有位置点的分析模拟

/****************************************************
**  寻找所有移动路径
****************************************************/
function getAllSiteMoveRoad(){
    initTempDatas();
//    print(preSign);
//    print(nextSign);
    moveFromSites = getMoveFromSites();
    moveToSites = getMoveToSites();
    bridgeSites = getBridgeSites();
    possibleTarget = moveToSites.concat(bridgeSites);
    
    print('所有起点:');
    print(moveFromSites);
    print('所有终点');
    print(moveToSites);
    
    var allSiteMoveWay:Array = new Array();
    //复制运动起点数组
    var moveFromSitesClone = new Array();
    for(var i=0; i<moveFromSites.length; i++){
        moveFromSitesClone[i] = moveFromSites[i];
    }
    //对每个运动起点数组遍历
    for(var site:String in moveFromSites){
        getSiteMoveRoad(site, siteMoveWay);
        print(siteMoveWay);
        if(isTheMoveWayFound && siteMoveWay.length>0){
            moveFromSitesClone.remove(site);
            allSiteMoveWay = allSiteMoveWay.concat(siteMoveWay);
        }
        siteMoveWay = new Array();
        isTheMoveWayFound = false;
    }
    
    if(moveFromSitesClone.length > 0){ //信号错误
        print('有起点剩余,信号错误');
        allSiteMoveWay = new Array();
        allSiteMoveWay.Add('-1');
        return allSiteMoveWay;
    }
    
    //复制运动终点数组
    var moveToSitesClone = new Array();
    for(var h=0; h<moveToSites.length; h++){
        moveToSitesClone[h] = moveToSites[h];
    }
    //对剩下的终点数组遍历
    for(var site:String in moveToSites){
        //记录目的点所在的路线数组及数组下表
        var road :Array ;
        var siteIndexOfRoad:int = -1;
        //遍历路线
        for(var j=0; j<roads.length && siteIndexOfRoad==-1; j++){
            var roadTemp:Array =roads[j] ; 
            for(var k=0; k<roadTemp.length; k++){            
                if(roadTemp[k] == site){
                    siteIndexOfRoad = k;
                    road = roadTemp;
                    break;
                }
            }
        }
        //找到目的点
        if(siteIndexOfRoad > -1){
            var flag:boolean = true;
            //该条路径为起点是生产者
            if(isSiteExistInArray(road[0], producer)){ 
                for(var m=1; m<siteIndexOfRoad; m++){
                    if(!isSiteExistInArray(road[m], possibleTarget)){
                        flag = false;
                    }
                }
            }
            //该条路径为起点不是生产者
            else{
                flag = false;
            }
            
            if(flag == false){ //信号错误
                allSiteMoveWay = new Array();
                allSiteMoveWay.Add('-1');
                return allSiteMoveWay;
            }
            else{
                allSiteMoveWay.Add("Null ==> " + road[0]);
                for(var n=1; n<=siteIndexOfRoad; n++){
                    allSiteMoveWay.Add(road[n-1] + " ==> " + road[n]);
                    possibleTarget.remove(road[n]);
                }
                moveToSitesClone.remove(site);
            }
        }            
    }
    if(moveToSitesClone.length > 0){
        print('有终点剩余,信号错误!');
        allSiteMoveWay = new Array();
        allSiteMoveWay.Add('-1');
        return allSiteMoveWay;
    }
    
    return allSiteMoveWay;
}

 

以下是算法过程中用到的公共变量和工具函数

/***********************************************
 **  算法过程中用到的一些变量
 **        moveFromSites    运动起点数组
 **        moveToSites        运动终点数组
 **        bridgeSites        运动桥梁点数组
 **        possibleTarget    可能作为单步移动目的点的数组
 **        siteMoveWay        从运动起点开始寻找到的移动路线
 **        isTheMoveWayFound    从运动起点开始寻找是否成功
 **        isPossibleConsumeSelf    如果取值为true,则可能是自我消费,用在单点移动中;
 **        itrCount        迭代次数,用在单点移动中
 **********************************************/
private var moveFromSites :Array = new Array();
private var moveToSites :Array = new Array();
private var bridgeSites :Array = new Array();
private var possibleTarget :Array = new Array();
private var siteMoveWay = new Array();
private var isTheMoveWayFound:boolean = false;
private var isPossibleConsumeSelf:boolean = false;
private var itrCount:int = 0;
/****************************************************
**  将数组转换成整数
****************************************************/
private function arrayToNum(arr :Array){
    var result = 0;
    for(var i=0; i<arr.length; i++){
        result += Mathf.Pow(2,i) * arr[i] ;
    }
    return result;
}

/****************************************************
**  将整数数组
****************************************************/
private function numToArray(num:int){
    var arr:Array = new Array(10);
    for(var i=0; num>0; i++){
        arr[i] = num % 2;
        num /= 2;
    }
    return arr;
}

/****************************************************
**  按位异或运算
****************************************************/
private function operateXOR(num1:int, num2:int){
    return num1^num2;
}
/****************************************************
**  按位与运算
****************************************************/
private function operateAND(num1:int, num2:int){
    return num1&num2;
}


/****************************************************
**  得到数组中值为1的所有下标数组
****************************************************/
private function getSignIndexs(arr:Array){
    var list:ArrayList = new ArrayList();
    for(var i=0; i<arr.length; i++){
        if(arr[i] == 1){
            list.Add(i);
        }
    }
    return list.ToArray();
}

/****************************************************
**  得到位置点是否在位置点构成的数组中
****************************************************/
private function isSiteExistInArray(site:String, sites:Array){
    var flag:boolean = false;
    for(var i=0; i<sites.length; i++){
        if(sites[i] == site){
            flag = true;
            break;
        }
    }
    return flag;
}

/****************************************************
**  得到开始移动的位置点数组
****************************************************/
private function getMoveFromSites(){
    var arr:Array = new Array();
    var pre :int = arrayToNum(preSign);
    var next :int = arrayToNum(nextSign);
    var resultXOR:Array = numToArray(operateXOR(pre, next));
    var resultXORIndex:Array = getSignIndexs(resultXOR);
    for(var i=0; i<resultXORIndex.length; i++){
        var index:int = resultXORIndex[i];
        if(preSign[index] == 1){
            arr.Add(sites[index]);
        }
    }
    return arr;
}
/****************************************************
**  得到移动到的位置点数组
****************************************************/
private function getMoveToSites(){
    var arr:Array = new Array();
    var pre :int = arrayToNum(preSign);
    var next :int = arrayToNum(nextSign);
    var resultXOR:Array = numToArray(operateXOR(pre, next));
    var resultXORIndex:Array = getSignIndexs(resultXOR);
    for(var i=0; i<resultXORIndex.length; i++){
        var index:int = resultXORIndex[i];
        if(preSign[index] == 0){
            arr.Add(sites[index]);
        }
    }
    return arr;
}
/****************************************************
**  得到可做迭代移动的位置点数组
****************************************************/
private function getBridgeSites(){
    var arr:Array = new Array();
    var pre :int = arrayToNum(preSign);
    var next :int = arrayToNum(nextSign);
    var resultAND:Array = numToArray(operateAND(pre, next));
    var resultANDIndex:Array = getSignIndexs(resultAND);
    for(var i=0; i<resultANDIndex.length; i++){
        var index:int = resultANDIndex[i];
        arr.Add(sites[index]);
    }
    return arr;
}

 

补充说明:

由于本人对js的变量作用域研究不深,在单位置点的移动算法实现时递归不是很好,希望有朋友能够帮助改进。

posted @ 2013-04-04 15:34  寻梦丄天涯  阅读(248)  评论(0)    收藏  举报