根据路线位置瞬时状态模拟运动算法
位置路线图如下所示,实际的可能更复杂,但不脱离本模型范围;
其中的位置点有以下特点:
- 每一时刻,每个位置只能有两个状态:0-没有物体, 1-有物体;
- 每一时刻,每个位置最多只能有一个物体;
- 位置A,C,H这样作为起始点的位置,它可以作为生产者,也就是说,它可以生产物体;
- 位置H,J这样作为结束点的位置,它可以作为消费者,也就是说,它可以消费物体;
- 中间的位置,比如B,E,F这样的点,它不能直接生产物体,物体的来源必须是上一个节点;
- 如果两次信号中,以上第4条所描述的位置点突然多出了物体或者少了物体,则判定为信号异常;
分析三种典型情况:
情况一:先后两个瞬时信号情况如下
得到运动结论:
运动情况:A=>B, C=>D, D=>E, E=>F
情况二:先后两个瞬时信号情况如下
得到运动结论:
运动情况:A=>B, D=>E, E=>F, G=>H
生产情况:A
消费情况:H, J
情况三:先后两个瞬时信号情况如下
得到运动情况:
运动情况: 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的变量作用域研究不深,在单位置点的移动算法实现时递归不是很好,希望有朋友能够帮助改进。





浙公网安备 33010602011771号