地圖‎ > ‎

無限隨機地圖( 河川森林演算法)


這個是個比較高階的理論,如果不想看到高深理論可以先離開。

所謂的隨機地圖,是一種由隨機數,並根據特定算法生成出來的地圖。生成出來的地圖有一定的規律(原則)。

文章將以「河川森林」為地圖演算法作為介紹,不同地形有不同的演算法,其他稍後再介紹。

>河川森林演算法

在寫任何代碼之前,了解自己的目標總是很重要的,這對編程很有幫助,哪怕你隨後會做無數的修改。

這個算法分開2部分:
1.生成河川
2.生成森林

換而言之,這個演算法首先要生成河川,再找出空地生成樹林。

>河川
在為算法的第一部分,這個部分比較簡單,因為地圖都是空的,我們只需要找出一個開始點,讓程式自行繪畫河川。

步驟:

1.隨機生成地圖座標
2.以這個座標為開始點,隨機找出兩個方向
3.以該兩個方向畫出河川,直至到地圖邊界


第一步很簡單,首先生成x和y的隨機數,再用字串把這兩個變數合併,成為一個座標(loc = %{x}%,%{y}%)。

第二步是算法重點,首先定義1代表東,2代表南等等,之後生成兩個不重複的變數(1~4的數字),以選出生成方向。

最後一步是根據方向,開始畫出河川。

>森林

在生成好河川後,下一步就是生成森林。
這時河川佔據了地圖上一些格子,在生成森林,就必需小心避開在河些的生成樹木(不然會很怪)。

步驟:

1.掃描整個地圖(由左上至右下)
2.在掃描過程中,檢查當中格子的附近有沒有樹林,沒有則以40%的機率生成樹林有則略過

第一步要和第二步一起解釋,
首先建立一個掃描的事件,在掃描的過程,檢查檢查當中格子的附近有沒有樹林,用以找出一個特定大小空間來生成樹林(一般來說是檢查附近3x3的格子有沒有樹林),再根據40%機率來生成樹林。

這邊有個要點,如果不以40%的原則來生成樹林,例如用了100%來生成樹林,你會看到樹林生成得十分有規律。





>總結
這是以光暈一個地圖演算法(?
當然筆者自己本身也想了很久,也參考了很多文章。這並非什麼易事,如果能教會大家,那就是筆者的榮幸了。
(參考檔案已放在檔案區,測試時要關導演看板,等10s就可以了)

                                   (圖片化生成過程)













        100%的效果

Author profile image
FK 人 (Facebook人)
Apr 10, 2017, 8:39:05 AM
AsshoIe之前跟我說的洞穴演算法

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <conio.h>
#include <time.h>

using namespace std;

#include <windows.h>

void gotoxy( int x, int y ){
COORD p = { x, y };
SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), p );
}

#define WIDTH 80
#define HEIGHT 60

bool map[HEIGHT][WIDTH];
int max(int a, int b){return (a>b?a:b);}
int min(int a, int b){return (a<b?a:b);}

bool get_bit(int x,int y){
return map[min(max(y,0),HEIGHT)][min(max(x,0),WIDTH)];
}

void printpicture();

bool median(int x, int y){
int sum=0;
int amount=0;
for (int i=-1;i<2;i++){
for (int j=-1;j<2;j++){
if(x+i>=0&&x+i<=WIDTH-1&&y+j>=0&&y+j<=HEIGHT-1){
amount++;
sum+=map[y+j][x+i];
}
}
}
return sum>amount/2;
}

void getpicture(){
srand(time(NULL));
for (int j=0;j<WIDTH;j++){
for (int i=0;i<HEIGHT;i++){
map[i][j]=rand()%2;
}
}
printpicture();

bool flag=false;
do{
flag=false;
for (int j=0; j<WIDTH;j++){
for (int i=0; i<HEIGHT; i++){
if (map[i][j]!=median(j,i)){
map[i][j]=median(j,i);
flag=true;
}
}
}

// cout<<"\n\n=============\n\n";
// printpicture();
}while (flag);
cout<<"\n\n=============\n\n";
printpicture();
}

void printpicture(){
for (int i=0;i<HEIGHT;i++){
for(int j=0;j<WIDTH;j++)
cout<<map[i][j];
cout<<endl;
}
}

int main(){
cout<<"press any key to start";
getch();
getpicture();
printpicture();
}