স্ট্যান্ডার্ড পাথফাইন্ডিং ভাল যথেষ্ট - আপনার রাজ্যগুলি হল আপনার বর্তমান অবস্থান + আপনার বর্তমান তালিকা in "চলমান" হ'ল হয় কক্ষগুলি পরিবর্তন করা বা তালিকা পরিবর্তন করা। এই উত্তরে আচ্ছাদিত নয়, তবে অতিরিক্ত অতিরিক্ত প্রচেষ্টা নয়, এটি এ * এর জন্য একটি ভাল শব্দতাত্ত্বিক লিখছেন - এটি লক্ষ্য থেকে কাছাকাছি একটি দরজা আনলক করা পছন্দ করে এটিকে দূরে সরিয়ে নিয়ে যাওয়ার বিষয়টিকে বেছে নেওয়ার দ্বারা অনুসন্ধানের গতি বাড়িয়ে তুলতে পারে it প্রায় দীর্ঘ পথ অনুসন্ধান করা, ইত্যাদি
এটি প্রথম এসেছিল এবং এটির একটি ডেমো রয়েছে বলে এই উত্তরটি অনেক উত্সাহ অর্জন করেছে, তবে আরও অনুকূলিত এবং বিশেষায়িত সমাধানের জন্য আপনাকে "এটি পিছনের দিকে করা আরও দ্রুত হয়" উত্তরটিও পড়তে হবে /gamedev/ / A / 150155/2624
সম্পূর্ণরূপে জাভাস্ক্রিপ্ট নীচে ধারণার প্রমাণ। একটি কোড ডাম্প হিসাবে উত্তরের জন্য দুঃখিত - আমি এটি একটি ভাল উত্তর ছিল বিশ্বাস করার আগে আমি বাস্তবে এটি বাস্তবায়ন করেছি, তবে এটি আমার কাছে বেশ নমনীয় বলে মনে হয়।
পাথ ফাইন্ডিংয়ের কথা চিন্তা করার সময়, মনে রাখবেন যে সহজ পাথফাইন্ডিং অ্যালগরিদমগুলির উত্তরাধিকার হ'ল:
- প্রস্থের প্রথম অনুসন্ধানটি আপনি যতটা সহজ পেতে পারেন।
- জিক্স্ট্রার অ্যালগরিদমটি প্রথম প্রসারিত অনুসন্ধানের মতো তবে রাষ্ট্রগুলির মধ্যে "দূরত্ব" ভিন্ন
- এ * জিক্সট্রাস যেখানে আপনার কাছে 'সঠিক দিকের সাধারণ জ্ঞান' রয়েছে যা একজন হিউরিস্টিক হিসাবে উপলব্ধ।
আমাদের ক্ষেত্রে, "অবস্থান + ইনভেন্টরি" এবং "দূরত্ব" কে "আন্দোলন বা আইটেমের ব্যবহার" হিসাবে কেবল "রাষ্ট্র" কে এনকোড করা আমাদের সমস্যা সমাধানের জন্য জিক্সট্রা বা এ * ব্যবহার করতে দেয়।
আপনার উদাহরণ স্তরের প্রদর্শিত এখানে কিছু আসল কোড রয়েছে। প্রথম স্নিপেটটি কেবল তুলনার জন্য - আপনি চূড়ান্ত সমাধানটি দেখতে চাইলে দ্বিতীয় ভাগে লাফ দিন। আমরা একটি জিক্স্ট্রার বাস্তবায়ন দিয়ে শুরু করি যা সঠিক পথটি খুঁজে পায় তবে আমরা সমস্ত বাধা এবং কী উপেক্ষা করেছি। (এটি ব্যবহার করে দেখুন, আপনি ঘর 0 -> 2 -> 3-> 4-> 6-> 5 থেকে শেষের জন্য এটি কেবল সূক্ষ্ম নির্দেশগুলি দেখতে পাবেন)
function Transition(cost, state) { this.cost = cost, this.state = state; }
// given a current room, return a room of next rooms we can go to. it costs
// 1 action to move to another room.
function next(n) {
var moves = []
// simulate moving to a room
var move = room => new Transition(1, room)
if (n == 0) moves.push(move(2))
else if ( n == 1) moves.push(move(2))
else if ( n == 2) moves.push(move(0), move(1), move(3))
else if ( n == 3) moves.push(move(2), move(4), move(6))
else if ( n == 4) moves.push(move(3))
else if ( n == 5) moves.push(move(6))
else if ( n == 6) moves.push(move(5), move(3))
return moves
}
// Standard Djikstra's algorithm. keep a list of visited and unvisited nodes
// and iteratively find the "cheapest" next node to visit.
function calc_Djikstra(cost, goal, history, nextStates, visited) {
if (!nextStates.length) return ['did not find goal', history]
var action = nextStates.pop()
cost += action.cost
var cur = action.state
if (cur == goal) return ['found!', history.concat([cur])]
if (history.length > 15) return ['we got lost', history]
var notVisited = (visit) => {
return visited.filter(v => JSON.stringify(v) == JSON.stringify(visit.state)).length === 0;
};
nextStates = nextStates.concat(next(cur).filter(notVisited))
nextStates.sort()
visited.push(cur)
return calc_Djikstra(cost, goal, history.concat([cur]), nextStates, visited)
}
console.log(calc_Djikstra(0, 5, [], [new Transition(0, 0)], []))
সুতরাং, আমরা এই কোডটিতে কীভাবে আইটেম এবং কী যুক্ত করব? সরল! প্রতিটি "রাষ্ট্র" পরিবর্তে কেবলমাত্র রুম নম্বর শুরু করে, এটি এখন ঘরের একটি টিপল এবং আমাদের ইনভেন্টরি স্টেট:
// Now, each state is a [room, haskey, hasfeather, killedboss] tuple
function State(room, k, f, b) { this.room = room; this.k = k; this.f = f; this.b = b }
ট্রানজিশনগুলি এখন (ব্যয়, ঘর) টিউপল থেকে একটি (ব্যয়, রাজ্য) টুপলে রূপান্তরিত হয়, তারপরে "অন্য ঘরে চলে যাওয়া" এবং "কোনও জিনিস তোলা" উভয়ই এনকোড করতে পারে
// move(3) keeps inventory but sets the room to 3
var move = room => new Transition(1, new State(room, cur.k, cur.f, cur.b))
// pickup("k") keeps room number but increments the key count
var pickup = (cost, item) => {
var n = Object.assign({}, cur)
n[item]++;
return new Transition(cost, new State(cur.room, n.k, n.f, n.b));
};
অবশেষে, আমরা জিক্সট্রা ফাংশনে কিছু ছোট-ছোট ধরনের-সম্পর্কিত পরিবর্তনগুলি করেছি (উদাহরণস্বরূপ, এটি এখনও পুরো রাজ্যের পরিবর্তে কেবলমাত্র গোলরুমের সংখ্যায় মিলছে), এবং আমরা আমাদের পূর্ণ উত্তর পাই! নোট করুন মুদ্রিত ফলাফলটি প্রথমে চাটিটি তুলতে 4 ঘরে যায়, তারপরে পালকটি তুলতে 1 রুমে যায়, পরে রুম 6 এ যায়, বসকে হত্যা করে, তারপর ঘরে 5 এ যায়)
// Now, each state is a [room, haskey, hasfeather, killedboss] tuple
function State(room, k, f, b) { this.room = room; this.k = k; this.f = f; this.b = b }
function Transition(cost, state, msg) { this.cost = cost, this.state = state; this.msg = msg; }
function next(cur) {
var moves = []
// simulate moving to a room
var n = cur.room
var move = room => new Transition(1, new State(room, cur.k, cur.f, cur.b), "move to " + room)
var pickup = (cost, item) => {
var n = Object.assign({}, cur)
n[item]++;
return new Transition(cost, new State(cur.room, n.k, n.f, n.b), {
"k": "pick up key",
"f": "pick up feather",
"b": "SLAY BOSS!!!!"}[item]);
};
if (n == 0) moves.push(move(2))
else if ( n == 1) { }
else if ( n == 2) moves.push(move(0), move(3))
else if ( n == 3) moves.push(move(2), move(4))
else if ( n == 4) moves.push(move(3))
else if ( n == 5) { }
else if ( n == 6) { }
// if we have a key, then we can move between rooms 1 and 2
if (cur.k && n == 1) moves.push(move(2));
if (cur.k && n == 2) moves.push(move(1));
// if we have a feather, then we can move between rooms 3 and 6
if (cur.f && n == 3) moves.push(move(6));
if (cur.f && n == 6) moves.push(move(3));
// if killed the boss, then we can move between rooms 5 and 6
if (cur.b && n == 5) moves.push(move(6));
if (cur.b && n == 6) moves.push(move(5));
if (n == 4 && !cur.k) moves.push(pickup(0, 'k'))
if (n == 1 && !cur.f) moves.push(pickup(0, 'f'))
if (n == 6 && !cur.b) moves.push(pickup(100, 'b'))
return moves
}
var notVisited = (visitedList) => (visit) => {
return visitedList.filter(v => JSON.stringify(v) == JSON.stringify(visit.state)).length === 0;
};
// Standard Djikstra's algorithm. keep a list of visited and unvisited nodes
// and iteratively find the "cheapest" next node to visit.
function calc_Djikstra(cost, goal, history, nextStates, visited) {
if (!nextStates.length) return ['No path exists', history]
var action = nextStates.pop()
cost += action.cost
var cur = action.state
if (cur.room == goal) return history.concat([action.msg])
if (history.length > 15) return ['we got lost', history]
nextStates = nextStates.concat(next(cur).filter(notVisited(visited)))
nextStates.sort()
visited.push(cur)
return calc_Djikstra(cost, goal, history.concat([action.msg]), nextStates, visited)
o}
console.log(calc_Djikstra(0, 5, [], [new Transition(0, new State(0, 0, 0, 0), 'start')], []))
তাত্ত্বিকভাবে, এটি বিএফএস-এর সাথেও কাজ করে এবং আমাদের জিক্সট্রাগুলির জন্য ব্যয় ফাংশনের প্রয়োজন পড়েনি, তবে ব্যয় থাকা আমাদের এটি বলতে দেয় "একটি চাবি তোলা সহজ প্রচেষ্টা নয়, তবে বসের সাথে লড়াই করা সত্যিই কঠিন, এবং আমরা বরং পিছনে চাই বসের সাথে লড়াই করার চেয়ে 100 টি পদক্ষেপ, যদি আমাদের পছন্দ হয় তবে ":
if (n == 4 && !cur.k) moves.push(pickup(0, 'k'))
if (n == 1 && !cur.f) moves.push(pickup(0, 'f'))
if (n == 6 && !cur.b) moves.push(pickup(100, 'b'))