Skip to content

Commit

Permalink
idastar back
Browse files Browse the repository at this point in the history
  • Loading branch information
thetime50 committed Mar 21, 2024
1 parent 542de60 commit b0c15eb
Show file tree
Hide file tree
Showing 5 changed files with 264 additions and 23 deletions.
8 changes: 4 additions & 4 deletions vue3-tsv/src/components/MenuTree/MenuTree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ const attrs = useAttrs(); // eslint-disable-line
const collapsed = ref(false);
const selected = ref("");
watch(selected,(selected)=>{
console.log("selected",toRaw( selected));
});
// watch(selected,(selected)=>{
// console.log("selected",toRaw( selected));
// });
const items = ref(menuData);
Expand All @@ -59,7 +59,7 @@ console.log('items',toRaw(items.value));
top:25px;
left: 25px;
opacity: 0.3;
z-index: 100;
z-index: 10001;
&:hover{
opacity: 1;
}
Expand Down
14 changes: 8 additions & 6 deletions vue3-tsv/src/views/aStar/aStarMath.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { clone } from "lodash";
import {
init as zrInit, ZRenderType, Circle, Rect, Line, Text,
Group, Element, Displayable, ElementEvent,
Expand Down Expand Up @@ -638,7 +639,7 @@ abstract class AStarBase{
item: item,
};
}
if (item.gpriority !== undefined) {
if (item.gpriority !== undefined) { // 这里需要拆分为open close
return {
state: 'have',
item: item,
Expand All @@ -648,7 +649,7 @@ abstract class AStarBase{
item: item,
... itemCoord,
};
if( this.stepTest){
if( this.stepTest){ // 斜向跨越墙壁测试
const testRes = this.stepTest(itemInfo, parentInfo);
if (testRes){
return testRes;
Expand Down Expand Up @@ -703,6 +704,7 @@ abstract class AStarBase{
childs.forEach(child => {
const res = this.setItemPriority(child,{x,y,item}); // 新的可能点
const key = child.x + '-' + child.y;
// 这里的逻辑有点问题
if (res.state === 'update' && !this.openSet[key]){
let sotIndex:number|undefined = undefined;
this.openSet[key] = res.item;
Expand Down Expand Up @@ -742,7 +744,7 @@ abstract class AStarBase{
return {
stae: this.state,
update: updateList,
gpriority: item.gpriority! + 1,
gpriority: item.gpriority!,
};
}
getPath(){
Expand Down Expand Up @@ -977,13 +979,13 @@ export class AStarRuntime{
gradientRow: Array<Array<Coord>> = [];
maxGpriority = 0;
run(){
const update: Array<Array< Coord >> = [];
const update: Array<Array< Coord >> = []; // 按接近的已消费代价分段
let lastArr: Array< Coord > = [];
let gpriority = 0;
let gpriority = -1;
for (; this.astar.state !== AStarState.Done && this.astar.state !== AStarState.Never ; ){
const res = this.astar.runStep();
if (res.update){
if (res.gpriority !== gpriority){
if (Math.abs( res.gpriority - gpriority) > 0.0001){
lastArr.length && update.push(lastArr);
lastArr = res.update.concat();
gpriority = res.gpriority!;
Expand Down
75 changes: 64 additions & 11 deletions vue3-tsv/src/views/idaStar/idaStar.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
<template>
<div class="component-component_name">
<a-form :model="cfg" layout="inline">
<a-form :model="cfg" :label-col ="{span:10}">
<a-form-item label="widthCnt" name="widthCnt">
<a-input v-model:value="cfg.widthCnt"/>
<a-input v-model:value="cfgEdit.widthCnt"/>
</a-form-item>
<a-form-item label="heightCnt" name="heightCnt">
<a-input v-model:value="cfg.heightCnt"/>
<a-input v-model:value="cfgEdit.heightCnt"/>
</a-form-item>
<a-form-item>
<a-button @click="confirm">确定</a-button>
</a-form-item>
</a-form>
<div>
<a-button @click="onShuffle">shuffle</a-button>
<div>
doActinoInfo:<br/>
actions: {{doActinoInfo.actions.map(v=>ActionDir[v]).join(",")}}<br/>
exec: {{ActionDir[doActinoInfo.currentAction] }} {{doActinoInfo.execed}}/{{ doActinoInfo.actions.length}}<br/>
</div>
</div>
<pre>{{JSON.stringify( cfg, null, ' ')}}</pre>
<div class="cube" :style="{width:(cfg.itemWidth + cfg.gep) * cfg.widthCnt + 'px'}">
<transition-group name="cube-item">
<template v-for="item in list" :key="item">
<template v-for="item in showList" :key="item">
<div :class="['item', 'item-'+item]" :style="{width:cfg.itemWidth + 'px',height:cfg.itemWidth + 'px',margin: cfg.gep/2 + 'px'}" >
<template v-if="typeof(item) == 'number' ">
<span>{{item + 1}}</span>
Expand All @@ -30,9 +38,15 @@
</template>

<script lang="ts" setup>
/* message */
/* IDA* 8数码问题 https://zhuanlan.zhihu.com/p/51497842 */
import { defineProps, defineEmits, useSlots, useAttrs,ref } from "vue";
import { shuffle } from "lodash";
import {ActionDir, NumBoardShow} from "./numBoard";
import { number } from "echarts";
async function delay (ms:number) {
return new Promise( resolve => setTimeout(resolve, ms) );
}
const props = defineProps({}); // eslint-disable-line
Expand All @@ -42,29 +56,68 @@ const attrs = useAttrs(); // eslint-disable-line
// IDAFS 迭代加深算法
// IDA* 启发式迭代加深
/*
记空位移动方向 urdl
*/
const cfgEdit = ref({
widthCnt:4,
heightCnt:4,
});
const cfg = ref({
itemWidth: 30,
gep: 4,
widthCnt:4,
heightCnt:4,
emptyIndex:-1,
});
const list = ref<Array<string | number>>(Array.from({length:cfg.value.widthCnt * cfg.value.heightCnt},(v,i)=> i));
const doActinoInfo = ref({
actions:[] as ActionDir[],
execed:0,
currentAction:0,
});
const sboard = new NumBoardShow(cfg.value);
const showList = ref<Array<string | number>>(sboard.list);
sboard.list = showList.value; // 用响应式的数据替换一下
function confirm(){
sboard.setSize(cfgEdit.value.widthCnt,cfgEdit.value.heightCnt);
showList.value = sboard.list;
sboard.list = showList.value; // 用响应式的数据替换一下
}
list.value[list.value.length-1] = 'none';
async function onShuffle(){
// list.value = shuffle(list.value);
doActinoInfo.value.actions = sboard.getRandomActions(sboard.widthCnt*sboard.heightCnt*3);
function onShuffle(){
list.value = shuffle(list.value);
for(let i in doActinoInfo.value.actions){
doActinoInfo.value.currentAction = doActinoInfo.value.actions[i];
doActinoInfo.value.execed = Number(i);
sboard.doAction(doActinoInfo.value.currentAction);
await delay(250);
}
}
</script>

<style lang="scss" scoped>
.component-component_name {
.ant-form{
width: 600px;
margin: auto;
margin-top: 50px;
}
.ant-form-item{
width: 200px;
margin-top: 50px;
margin-left: 20px;
}
pre{
Expand Down Expand Up @@ -104,7 +157,7 @@ function onShuffle(){
.cube-item-move,
.cube-item-enter-active,
.cube-item-leave-active {
transition: all 1s ease;
transition: all 0.2s ease;
}
.cube-item-enter-from,
.cube-item-leave-to {
Expand Down
173 changes: 173 additions & 0 deletions vue3-tsv/src/views/idaStar/numBoard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import {sample} from "lodash";

export enum ActionDir{
u,
r,
d,
l,
}


export class NumBoard{
public list:(number|string)[] = [];
private canAction:[boolean,boolean,boolean,boolean][]=[];//对于当前空位坐标 空位可以移动的方向 urdl
private readonly reverseDir:Record<ActionDir,ActionDir> = {
[ActionDir.u]:ActionDir.d,
[ActionDir.r]:ActionDir.l,
[ActionDir.d]:ActionDir.u,
[ActionDir.l]:ActionDir.r,
};
constructor(
public readonly cfg={ // 为了保持响应式
widthCnt:4,
heightCnt:4,
emptyIndex:-1,
},
){
this.cfg = cfg;
this.initList();
this.initCanAction();
}
get widthCnt(){
return this.cfg.widthCnt;
}
set widthCnt(v:number){
this.cfg.widthCnt = v;
}

get heightCnt(){
return this.cfg.heightCnt;
}
set heightCnt(v:number){
this.cfg.heightCnt = v;
}
get emptyIndex(){
return this.cfg.emptyIndex;
}
set emptyIndex(v:number){
this.cfg.emptyIndex = v;
}

initList(){
this.list = Array.from({length:this.widthCnt * this.heightCnt},(v,i)=> i);
this.emptyIndex = this.list.length-1;
this.list[this.emptyIndex] = 'none';
}
initCanAction(){
// urdl
const dirAll:[boolean,boolean,boolean,boolean] = [true,true,true,true];
const dirRdl:[boolean,boolean,boolean,boolean] = [false,true,true,true];
const dirUrl:[boolean,boolean,boolean,boolean] = [true,true,false,true];
const dirUrd:[boolean,boolean,boolean,boolean] = [true,true,true,false];
const dirUdl:[boolean,boolean,boolean,boolean] = [true,false,true,true];
const length = this.widthCnt * this.heightCnt;
this.canAction = Array.from({length:length}).fill(dirAll) as [boolean,boolean,boolean,boolean][];
const lastLineIndex = (this.heightCnt-1)*this.widthCnt;
for(let i=0; i<this.widthCnt; i++){
this.canAction[i] = dirRdl;
this.canAction[i+lastLineIndex] = dirUrl;
}
for(let i=0; i<length; i+=this.widthCnt){
this.canAction[i] = dirUrd;
this.canAction[i+this.widthCnt-1] = dirUdl;
}
this.canAction[0] = [false,true,true,false];
this.canAction[this.widthCnt-1] = [false,false,true,true];
this.canAction[lastLineIndex] = [true,true,false,false];
this.canAction[length-1] = [true,false,false,true];
}
setSize(widthCnt:number,heightCnt:number){
const needInitCanActon= this.widthCnt != widthCnt||
this.heightCnt != heightCnt ;
this.widthCnt = widthCnt;
this.heightCnt = heightCnt;
this.initList();
if(needInitCanActon){
this.initCanAction();
}
}
getCanActoinDir(index:number,before?:ActionDir){
const res = [...this.canAction[index]];
if(typeof before == "number"){
res[this.reverseDir[ before]] = false;
}
return res.reduce((t,v,i,a)=>{
if(v){
t.push(i as ActionDir);
}
return t;
},[] as ActionDir[]);
}
getSwitchOtherCell(i:number,dir:ActionDir){
if(dir == ActionDir.u){
if(i < this.widthCnt)
throw new Error(`index:${i} dir:${ActionDir[dir]}超出范围`);
return i-this.widthCnt;
}
if(dir == ActionDir.r){
if(i%this.widthCnt == this.widthCnt-1)
throw new Error(`index:${i} dir:${ActionDir[dir]}超出范围`);
return i+1;
}
if(dir == ActionDir.d){
if(i+this.widthCnt >= this.widthCnt*this.heightCnt)
throw new Error(`index:${i} dir:${ActionDir[dir]}超出范围`);
return i+this.widthCnt;
}
if(dir == ActionDir.l){
if(i%this.widthCnt == 0)
throw new Error(`index:${i} dir:${ActionDir[dir]}超出范围`);
return i-1;
}
throw new Error(`dir:${dir} 错误的dir`);
}

getRandomActions(step:number){
let emptyi = this.emptyIndex; // this.list.length-1;
const actions:ActionDir[] = [];

actions.push(
sample(this.getCanActoinDir(emptyi))!
);
emptyi = this.getSwitchOtherCell(emptyi,actions[0]);
for(let i =1; i<step;i++){
const action = sample(this.getCanActoinDir(emptyi,actions[i-1]))!;
actions.push(
action
);
emptyi = this.getSwitchOtherCell(emptyi,action);
}
return actions;
}

actionsToString(actions:ActionDir[]){
return actions.map((v)=>ActionDir[v]);
}

doAction(action:ActionDir){

const otherCell = this.getSwitchOtherCell(this.emptyIndex,action);
this.list[this.emptyIndex] = this.list[otherCell];
this.list[otherCell] = "none";
this.emptyIndex = otherCell;
}
doActions(actions:ActionDir[]){
actions.forEach((a)=>{
this.doAction(a);
});
}
}

export class NumBoardShow extends NumBoard{
constructor(
public readonly cfg={ // 为了保持响应式
widthCnt:4,
heightCnt:4,
emptyIndex:-1,
itemWidth: 30,
gep: 4,
},
){
super(cfg);
}
}
Loading

0 comments on commit b0c15eb

Please sign in to comment.