<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nuttapon-Sartmanee</title>
    <description>The latest articles on DEV Community by Nuttapon-Sartmanee (@nuttapon026).</description>
    <link>https://dev.to/nuttapon026</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1053417%2F0865fe57-7127-452b-aa77-2475f468282d.png</url>
      <title>DEV Community: Nuttapon-Sartmanee</title>
      <link>https://dev.to/nuttapon026</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nuttapon026"/>
    <language>en</language>
    <item>
      <title>เครื่องมือการสร้างแผนที่ในเกมโดยใช้ Random Walk Algorithm</title>
      <dc:creator>Nuttapon-Sartmanee</dc:creator>
      <pubDate>Wed, 29 Mar 2023 15:05:02 +0000</pubDate>
      <link>https://dev.to/nuttapon026/ekhruuengmuuekaarsraangaephnthiiainekmodyaich-random-walk-algorithm-53og</link>
      <guid>https://dev.to/nuttapon026/ekhruuengmuuekaarsraangaephnthiiainekmodyaich-random-walk-algorithm-53og</guid>
      <description>&lt;p&gt;ในปัจจุบันเทคโนโลยีมีการพัฒนามากขึ้นที่ช่วยในการพัฒนาเกมต่าง ๆ อย่างการใช้อัลกอริทึมเข้ามาช่วยในการสร้างประสบการณ์ในเกมที่ไม่เหมือนใครสำหรับผู้เล่นแต่ละคน ตัวอย่างเช่นแผนที่ภายในเกม ซึ่งมีวิธีการมากมายที่สามารถใช้ในการสร้างแผนที่ได้&lt;/p&gt;

&lt;p&gt;ในวันนี้เราขอเสนอหนึ่งวิธีที่จะสามารถสร้างแผนที่ดันเจี้ยน 2 มิติแบบสุ่มได้ โดยใช้ JavaScript ซึ่งจะแบ่งออกเป็น 2 ส่วน คือ พื้นที่ที่ผู้เล่นสามารถเข้าไปได้ และเส้นทางเชื่อมต่อ&lt;/p&gt;

&lt;p&gt;เราจะใช้ Random Walk Algorithm ในการสร้างแผนที่นี้ โดยจำเป็นต้องมีแผนที่กว้าง ๆ ในรูปแบบของ Grid ก่อนจึงจะสามารถใช้งาน Algorithm ได้ เริ่มต้นจะมีการสุ่มจุดใดจุดหนึ่งบนแผนที่ก่อน จากนั้นก็จะเริ่มสร้างอุโมงค์ด้วยการสุ่ม จนกระทั่งได้จำนวนอุโมงค์ตามที่ต้องการ โดยเรา&lt;strong&gt;สามารถกำหนดค่าให้กับ Algorithm นี้ได้&lt;/strong&gt; คือ&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dimensions (ความกว้างและความสูงของแผนที่) &lt;/li&gt;
&lt;li&gt;MaxTunnels (จำนวนรอบสูงสุดที่อัลกอริทึมสามารถทำได้ขณะสร้างแผนที่) &lt;/li&gt;
&lt;li&gt;MaxLength (ความยาวสูงสุดของแต่ละอุโมงค์ที่อัลกอริทึมจะเลือกก่อนทำการเลี้ยวในแนวนอนหรือแนวตั้ง)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  การทำงานของ Algorithm จะมีดังนี้
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;สร้างแผนที่สองมิติในรูปแบบของ Grid&lt;/li&gt;
&lt;li&gt;เลือกจุดเริ่มต้นแบบสุ่มบนแผนที่&lt;/li&gt;
&lt;li&gt;จำนวนอุโมงค์ต้องไม่เป็นศูนย์&lt;/li&gt;
&lt;li&gt;สุ่มความยาวจากความยาวสูงสุดที่ผู้ใช้กำหนด&lt;/li&gt;
&lt;li&gt;สุ่มทิศทางการเลี้ยว (ขวา, ซ้าย, ขึ้น, ลง)&lt;/li&gt;
&lt;li&gt;วาดอุโมงค์ในทิศทางนั้นโดยหลีกเลี่ยงขอบของแผนที่&lt;/li&gt;
&lt;li&gt;ลดจำนวน tunnels และทำวนซ้ำไปเรื่อย ๆ&lt;/li&gt;
&lt;li&gt;ส่งข้อมูลแผนที่ที่สร้างเสร็จแล้วกลับไป&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;เนื่องจากแผนที่ประกอบด้วยอุโมงค์และกำแพง จึงสามารถอธิบายเป็น 0 และ 1 ในอาร์เรย์สองมิติดังต่อไปนี้ (1 หมายถึง "กำแพง" , 0 หมายถึง "อุโมงค์")&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;map = [[1,1,1,1,0],
       [1,0,0,0,0],
       [1,0,1,1,1],       
       [1,0,0,0,1],       
       [1,1,1,0,1]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เราสามารถเข้าถึงค่าของมันได้โดยการใช้แถวและคอลัมน์ เช่น map [row] [column] &lt;/p&gt;

&lt;p&gt;ก่อนเขียนอัลกอริทึม ต้องมีฟังก์ชันตัวช่วยในการสร้างอาร์เรย์สองมิติ คือ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;createArray(num, dimensions) {
    var array = [];    
    for (var i = 0; i &amp;lt; dimensions; i++) { 
      array.push([]);      
      for (var j = 0; j &amp;lt; dimensions; j++) {  
         array[i].push(num);      
      }    
    }    
    return array;  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;สร้างตัวแปรต่าง ๆ เพื่อเตรียมกำหนดค่าให้กับ Random Walk Algorithm&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;createMap(){
 let dimensions = 5,     
 maxTunnels = 3, 
 maxLength = 3;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;สร้างอาร์เรย์สองมิติโดยใช้ฟังก์ชันตัวช่วยในการสร้างอาร์เรย์สองมิติ ที่กำหนดไว้ล่วงหน้า&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let map = createArray(1, dimensions);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;สุ่มแถวและคอลัมน์ เพื่อเป็นจุดเริ่มต้นบนแผนที่&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let currentRow = Math.floor(Math.random() * dimensions),       
    currentColumn = Math.floor(Math.random() * dimensions);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;สร้างทิศทางการเคลื่อนที่ทั้งหมดที่ทำได้ ตัวอย่างเช่น หากต้องการไปที่จุดรอบ ๆ จุด [2][2] สามารถทำได้โดยวิธีต่อไปนี้&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;หากต้องการขึ้น ให้ลบ 1 ออกจากแถว คือไปที่จุด [1][2]&lt;/li&gt;
&lt;li&gt;หากต้องการลงไป ให้เพิ่ม 1 ในแถว คือไปที่จุด [3][2]&lt;/li&gt;
&lt;li&gt;หากต้องการไปทางขวา เพิ่ม 1 ในคอลัมน์ คือไปที่จุด [2][3]&lt;/li&gt;
&lt;li&gt;หากต้องการไปทางซ้าย ให้ลบ 1 ออกจากคอลัมน์ คือไปที่จุด [2][1]
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs814s1s76kqwzi3wh9zq.png" alt="Image description"&gt;
จะได้ทิศทางทั้งหมดเป็น
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;สร้างตัวแปรเพื่อเก็บค่าสุ่มจาก การสุ่มทิศทางการเคลื่อนที่ และสร้างตัวแปรเพื่อเก็บ ทิศทางที่เคยเดินแล้ว โดยเริ่มต้นจะเป็น empty&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let lastDirection = [], 
    randomDirection;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;สร้างเงื่อนไขที่ไม่ทำให้เกิดการเดินซ้ำที่เดิม&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;do {         
randomDirection = directions[Math.floor(Math.random() * directions.length)];      
} while ((randomDirection[0] === -lastDirection[0] &amp;amp;&amp;amp;    
          randomDirection[1] === -lastDirection[1]) || 
         (randomDirection[0] === lastDirection[0] &amp;amp;&amp;amp;  
          randomDirection[1] === lastDirection[1]));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;สร้างตัวแปรเพิ่มสุ่มความยาวจาก maxLength และใส่ค่าให้ tunnelLength เป็น 0&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let randomLength = Math.ceil(Math.random() * maxLength),       
    tunnelLength = 0;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;สร้างอุโมงค์โดยเปลี่ยนค่าของช่องนั้นจากหนึ่งเป็นศูนย์โดยที่ tunnelLength น้อยกว่า randomLength และถ้าอุโมงค์ชนขอบแผนที่ จะหยุดการทำงาน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;while (tunnelLength &amp;lt; randomLength) { 
 if(((currentRow === 0) &amp;amp;&amp;amp; (randomDirection[0] === -1))||  
    ((currentColumn === 0) &amp;amp;&amp;amp; (randomDirection[1] === -1))|| 
    ((currentRow === dimensions — 1) &amp;amp;&amp;amp; (randomDirection[0] ===1))||
 ((currentColumn === dimensions — 1) &amp;amp;&amp;amp; (randomDirection[1] === 1)))   
 { break; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;else{ 
  map[currentRow][currentColumn] = 0; 
  currentRow += randomDirection[0];
  currentColumn += randomDirection[1]; 
  tunnelLength++; 
 } 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;หากอุโมงค์เกิดการชนขอบ จะเช็คว่าทิศทางนั้นมีความยาวอย่างน้อยหนึ่งหรือไม่ ถ้าใช่ ให้เปลี่ยนค่า LastDirection เป็น RandomDirection และลดค่า maxTunnels แล้วกลับไปสร้างอุโมงค์ใหม่ด้วยทิศทางสุ่มอื่น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (tunnelLength) { 
 lastDirection = randomDirection; 
 maxTunnels--; 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เมื่อเสร็จสิ้นการวาดอุโมงค์และ maxTunnels เป็นศูนย์ จะส่งข้อมูลแผนที่&lt;br&gt;
ผลลัพธ์พร้อมทางเลี้ยวและอุโมงค์ทั้งหมดกลับไป&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;}
 return map;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ตัวอย่างผลที่ได้จาก Code&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo73hy06gu32xdyvdzgi4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo73hy06gu32xdyvdzgi4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  สรุปผล
&lt;/h2&gt;

&lt;p&gt;Algorithm นี้จะสามารถช่วยผู้พัฒนาเกมในด้านของการสร้างแผนที่ด้วยการสุ่มเป็นหลัก ผู้พัฒนาจึงไม่ต้องออกแบบเอง ทำให้สร้างแผนที่ได้ไวยิ่งขึ้น และอาจนำไปประยุกต์ต่อทำให้แผนที่มีความน่าสนใจได้ เช่น อยู่ในสถานที่เดิมในเกม แต่เมื่อกลับมาอีกครั้งกลับมีเส้นทางที่ต่างไปจากเดิม สามารถนำไปประยุกต์เป็นเกมเขาวงกตได้&lt;/p&gt;

&lt;p&gt;References: &lt;a href="https://www.freecodecamp.org/news/how-to-make-your-own-procedural-dungeon-map-generator-using-the-random-walk-algorithm-e0085c8aa9a/" rel="noopener noreferrer"&gt;https://www.freecodecamp.org/news/how-to-make-your-own-procedural-dungeon-map-generator-using-the-random-walk-algorithm-e0085c8aa9a/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>algorithms</category>
      <category>ai</category>
      <category>gamedev</category>
    </item>
  </channel>
</rss>
