相关文章推荐

上圖是由 André Karwath aka Aka - 自己的作品, CC BY-SA 2.5
https://commons.wikimedia.org/w/index.php?curid=481651

接下來就上程式碼吧

function flood_fill(old, chg, x, y) { // old: 舊顏色, chg: 新顏色, x: x座標, y: y座標
    if (map[x][y] == chg) { // 如果新顏色和舊顏色相同,則不再改變
        return
    if (map[x][y] == old) { // 如果舊顏色和目標顏色相同,則改變
        map[x][y] = chg; // 改變顏色
        if (x > 0) { 
            flood_fill(old, chg, x - 1, y);
        if (x < map.length - 1) {
            flood_fill(old, chg, x + 1, y);
        if (y > 0) {
            flood_fill(old, chg, x, y - 1);
        if (y < map.length - 1) {
            flood_fill(old, chg, x, y + 1);
    } else {
        return;

有些人可能不知道什麼是遞迴,在這邊補充一下,
簡單來說遞迴就是在函式內呼叫函式本身,
透過不斷疊層後達成目的

if (map[x][y] == chg) { // 如果新顏色和舊顏色相同,則不再改變
        return

這邊主要是做個防呆,避免重複執行浪費資源,節省不必要的錯誤。

if (map[x][y] == old) { // 如果舊顏色和目標顏色相同,則改變
        map[x][y] = chg; // 改變顏色
        if (x > 0) { 
            flood_fill(old, chg, x - 1, y);
        if (x < map.length - 1) {
            flood_fill(old, chg, x + 1, y);
        if (y > 0) {
            flood_fill(old, chg, x, y - 1);
        if (y < map.length - 1) {
            flood_fill(old, chg, x, y + 1);
    } else {
        return;

這邊就是演算法本人拉
往周圍尋找,尋找相鄰的是不是同一種的。
前文提到Flood fill是尋找周圍相同性質的單位並對其執行動作。
我們是填色遊戲,目的是變成相同顏色,所以我用map[x][y] = chg來改變這個像素的顏色,然後往四周尋找。
如果找的地方不是跟原來相同性質的,就代表遇到邊界了所以原地折返

自製地圖生成演算法

既然地圖不是亂數生成,特別寫一個演算法那就要有要達成的目的。
我想要做到

  • 可以控制顏色的數量
  • 可以設定顏色的分散程度
  • 想好之後就來動工拉 先設定參數

    color_number = 9;
    dispersion = 0.9;
    map_width = 10;
    map_height = 10;
    

    由上到下 依序是顏色的數量 分散的程度 地圖的寬和高
    有了參數之後先生成空白地圖

    var map = [];
    for (let i = 0; i < map_width; i++) {
        map.push([]);
        for (let j = 0; j < map_height; j++) {
            map[i].push(0);
    

    這樣 你就得到了一個叫做map的10*10陣列了
    再來我還需要做一件事,那就是生成隨機的圖塊。

    function make_area(x, y, area_color, count) {
        let now_x = x;
        let now_y = y;
        for (let i = 0; i < count; i++) {
    

    我的想法是從一個起始點開始,接著讓那個點移動。
    移動的路徑就是生成的圖塊,生成的次數則由count控制

    if (map[now_x][now_y] == area_color) {
    map[now_x][now_y] = area_color;
    

    如果剛好找到的點是相同顏色的 則不計數
    然後利用map[now_x][now_y] = area_color來上色
    最後就是在找個方向延伸下去

    function make_area(x, y, area_color, count) {
        let now_x = x;
        let now_y = y;
        for (let i = 0; i < count; i++) {
            if (map[now_x][now_y] == area_color) {
            map[now_x][now_y] = area_color;
            let direction = Math.floor(Math.random() * 4);
            if (direction == 0 && now_x > 0) {
                now_x -= 1;
            } else if (direction == 1 && now_x < map.length - 1) {
                now_x += 1;
            } else if (direction == 2 && now_y > 0) {
                now_y -= 1;
            } else if (direction == 3 && now_y < map.length - 1) {
                now_y += 1;
    

    這邊用到js的math
    Math.random() 可以生成0-1之間的數,乘以x再取整就可以獲得0到x-1的數了

    最後讓我們利用今天所學,做一個console遊戲當作今天的結尾吧

    * AUTHOR rlongdragon * DATE 2022-09-16 * VISON 1.0 * this probject used copilot //import const readline = require("readline"); // 載入readline模組 //set up color_number = 3; // 色彩的數量 dispersion = 0.5; // 分散度 map_width = 20; // 地圖寬度 map_height = 20; // 地圖高度 // 地圖初始化 var map = []; for (let i = 0; i < map_width; i++) { map.push([]); for (let j = 0; j < map_height; j++) { map[i].push(0); // 生成斑點 function make_area(x, y, area_color, count) { let now_x = x; // 生成斑點的x座標 let now_y = y; // 生成斑點的y座標 for (let i = 0; i < count; i++) { // 嘗試生成count次 if (map[now_x][now_y] == area_color) { // 如果已經是目標顏色,則不再生成 i + 1; map[now_x][now_y] = area_color; // 生成斑點 let direction = Math.floor(Math.random() * 4); // 隨機製造下次生成的方向 if (direction == 0 && now_x > 0) { now_x -= 1; } else if (direction == 1 && now_x < map.length - 1) { now_x += 1; } else if (direction == 2 && now_y > 0) { now_y -= 1; } else if (direction == 3 && now_y < map.length - 1) { now_y += 1; // 地圖生成 function create_map() { for (let i = 0; i < map.length; i++) { for (let j = 0; j < map.length; j++) { if (Math.random() > dispersion * 0.95) { // 有機率生成斑點 make_area(i, j, Math.floor(Math.random() * color_number), Math.floor((Math.random() + 1) * 5) * dispersion); // 輸出地圖 function print_map(map) { for (let i = 0; i < map.length; i++) { // 輸出地圖 let row = ""; // 一行的字串 for (let j = 0; j < map.length; j++) { // 輸出一行 if (j == map.length - 1) { // 如果是最後一個,則不加空格 row += map[i][j]; // 加入地圖的數字 } else { // 如果不是最後一個,則加空格 row += map[i][j] + " "; // 加入地圖的數字 console.log(row); //flood fill 演算法 function flood_fill(old, chg, x, y) { // old: 舊顏色, chg: 新顏色, x: x座標, y: y座標 if (map[x][y] == chg) { // 如果新顏色和舊顏色相同,則不再改變 return if (map[x][y] == old) { // 如果舊顏色和目標顏色相同,則改變 map[x][y] = chg; // 改變顏色 if (x > 0) { flood_fill(old, chg, x - 1, y); if (x < map.length - 1) { flood_fill(old, chg, x + 1, y); if (y > 0) { flood_fill(old, chg, x, y - 1); if (y < map.length - 1) { flood_fill(old, chg, x, y + 1); } else { return; // 檢查是否結束 function check_end() { let end = true; color = map[0][0]; // 設定初始顏色 for (let i = 0; i < map.length; i++) { for (let j = 0; j < map.length; j++) { if (map[i][j] != color) { // 如果有不同的顏色,則還沒結束 end = false; return end; return end; //main create_map(); // 生成地圖 print_map(map); // 輸出地圖 var rl = readline.createInterface({ // 載入readline模組 input: process.stdin, output: process.stdout rl.on('line', function (line) { // 輸入 let color = parseInt(line); // 輸入的顏色 flood_fill(map[0][0], color, 0, 0); // 塗色 print_map(map); // 輸出地圖 if (check_end()) { // 檢查是否結束 console.log("you win"); process.exit(); // 結束程式
     
    推荐文章