一款C++地图生成器
  • 板块灌水区
  • 楼主JoeBiden2020
  • 当前回复3
  • 已保存回复3
  • 发布时间2021/8/23 22:09
  • 上次更新2023/11/4 09:16:51
查看原帖
一款C++地图生成器
432183
JoeBiden2020楼主2021/8/23 22:09

原本想做一个生存游戏,懒了,遂改为地图生成.
没有使用广为人知的perlin算法,选择以dfs为基础进行改进.

#include <bits/stdc++.h>
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <thread>
#pragma GCC optimize(3)
#define elif else if
#define pass do{}while(0)
#define ocean 0
#define sea 1
#define lake 2
#define forest 3
#define plain 4
#define grassland 5
#define mountain 6
#define volcano 7
#define hill 8
#define iceland 9
#define desert 10
#define kbhit(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)
using namespace std;
int input1,checkr=8;
char input2;
int rand_number(int x,int y){
	srand(time(NULL)+x*x);
	srand(rand()+y*y);
	return rand()+x*y;
}
/*void full_screen()
{   
    HWND hwnd = GetForegroundWindow();
    int cx = GetSystemMetrics(SM_CXSCREEN);           
    int cy = GetSystemMetrics(SM_CYSCREEN);            

    LONG l_WinStyle = GetWindowLong(hwnd,GWL_STYLE); 
    SetWindowLong(hwnd,GWL_STYLE,(l_WinStyle | WS_POPUP | WS_MAXIMIZE) & ~WS_CAPTION & ~WS_THICKFRAME & ~WS_BORDER);

    SetWindowPos(hwnd, HWND_TOP, 0, 0, cx, cy, 0);
}
*/
void SetColorAndBackground(int ForgC, int BackC) {
	WORD wColor=((BackC & 0x0F)<<4)+(ForgC & 0x0F);
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),wColor);
}
class land{
	public:
		int lands,resource,x,y;
		char look;
		void load_look(land &a){
			switch(a.lands){
				case 0:{
					a.look='~';
					break;
				}
				case 1:{
					a.look='@';
					break;
				}
				case 2:{
					a.look='#';
					break;
				}
				case 3:{
					a.look='$';
					break;
				}
				case 4:{
					a.look='=';
					break;
				}
				case 5:{
					a.look='-';
					break;
				}
				case 6:{
					a.look='^';
					break;
				}
				case 7:{
					a.look='*';
					break;
				}
				case 8:{
					a.look='&';
					break;
				}
				case 9:{
					a.look='+';
					break;
				}
				case 10:{
					a.look='X';
					break;
				}
				default:{
					a.look='?';
					break;
				}
			}
			return;
		}
};
short maxx,maxy,searchcnt,size,loadnum=0;
land blocks[7735][7735];
bool loaded[7735][7735];
int r1,r2,r3,r4,r5,r6,r7,r8,r9;
void dfs(int number,int x,int y,int landnum){
	int qy=landnum;
	r1=rand_number(maxx,maxx+322122)%2+2;
	r2=rand_number(maxx,114)%2+3;
	r3=rand_number(maxx,784*y)%2+4;
	r4=rand_number(maxx,44+number)%2+3;
	r5=rand_number(maxx,46*x)%2+5;
	r6=rand_number(maxx,34+y)%2+3;
	r7=rand_number(maxx,6+x)%2+2;
	r8=rand_number(maxx,7+x)%2+2;
	r9=rand_number(maxy,y+2)%5;
	if(x>maxx||y>maxy||x<0||y<0||number>=size||loaded[x][y]==1){
		return;
	}
	if(qy==6||qy==7){
		number+=1;
	}
	if(qy==1||qy==2){
		number--;
	}
	loaded[x][y]=1;
	bool a=rand_number(x,x+1992)%r1;
	bool h=rand_number(x,y+6)%r2;
	bool b=rand_number(y,3945)%r3;
	bool f=rand_number(x,y+245)%r4;
	bool d=rand_number(x,y+4438)%r5;
	bool e=rand_number(x,y+13454)%r6;
	bool c=rand_number(number,3974298)%r7;
	bool g=rand_number(x+y,354)%r8;
	blocks[x][y].lands=qy;
	if(!a){
		dfs(number+8,x+1,y,landnum);
	} 
	if(!b){
		dfs(number+8,x-1,y,landnum);
	}
	if(!c){
		dfs(number+3,x,y-1,landnum);
	}
	if(!d){
		dfs(number+3,x,y+1,landnum);
	}
	if(!e){
		dfs(number+2,x+1,y-1,landnum);
	}
	if(!f){
		dfs(number+2,x-1,y+1,landnum);
	}
	if(!g){
		dfs(number+2,x-1,y-1,landnum);
	}
	if(!h){
		dfs(number+2,x+1,y+1,landnum);
	}
	if(!r9){
		loaded[x][y]=0;
	}
	return;
}
void check(){
	cout<<endl;
	long long CNT=0;
	for(int x=1;x<=maxx;x+=checkr){
		for(int y=1;y<=maxy;y+=checkr){
			CNT++;
			if(blocks[x][y].lands==6){
				if(blocks[x+1][y].lands!=6&&blocks[x+1][y].lands!=0&&blocks[x+1][y].lands!=1)blocks[x+1][y].lands=8;
				if(blocks[x-1][y].lands!=6&&blocks[x-1][y].lands!=0&&blocks[x-1][y].lands!=1)blocks[x-1][y].lands=8;
				if(blocks[x][y+1].lands!=6&&blocks[x][y+1].lands!=0&&blocks[x][y+1].lands!=1)blocks[x][y+1].lands=8;
				if(blocks[x][y-1].lands!=6&&blocks[x][y-1].lands!=0&&blocks[x][y-1].lands!=1)blocks[x][y-1].lands=8;
			}
			if(blocks[x][y].lands==8){
				if(blocks[x+1][y].lands==4||blocks[x+1][y].lands==3||blocks[x+1][y].lands==9)blocks[x+1][y].lands=5;
				if(blocks[x-1][y].lands==4||blocks[x-1][y].lands==3||blocks[x-1][y].lands==9)blocks[x-1][y].lands=5;
				if(blocks[x][y+1].lands==4||blocks[x][y+1].lands==3||blocks[x][y+1].lands==9)blocks[x][y+1].lands=5;
				if(blocks[x][y-1].lands==4||blocks[x][y-1].lands==3||blocks[x][y-1].lands==9)blocks[x][y-1].lands=5;
			}
			cout<<"\rChecking... "<<(float)checkr*(float)checkr*((float)CNT/(float)(maxx*maxy))*100<<"%   ";
			int rrr=rand_number(23423,CNT)%3;
			if(!rrr){
				dfs(0,x,y,1);
			}
		}
	}
	return;
}
void printland(char x){
	if(x=='~'||x=='#'||x=='@'){
		SetColorAndBackground(1,9);
	}
	if(x=='-'||x=='$'){
		SetColorAndBackground(11,2);
	}
	if(x=='X'||x=='='){
		SetColorAndBackground(14,6);
	}
	if(x=='*'){
		SetColorAndBackground(12,8);
	}
	if(x=='^'){
		SetColorAndBackground(8,7);
	}
	if(x=='&'){
		SetColorAndBackground(5,2);
	}
	if(x=='+'){
		SetColorAndBackground(7,15);
	}
	putchar(x);
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED |FOREGROUND_GREEN | FOREGROUND_BLUE);
}
void loadmap(){
	cout<<"Loading map...\n";
	for(int i=1;i<=searchcnt;i++){
		loadnum++;
		cout<<"\rGenerating... "<<((float)i/searchcnt)*100<<"%    ";
		int xx=rand_number(i,1)%maxx;
		int yy=rand_number(i,11)%maxy;
		int k=abs(rand_number(i+time(NULL)+3874338,3748)%11);
		if(i==1){
			dfs(0,xx,yy,2);
		}
		dfs(0,xx,yy,k);
	}
	check();
	cout<<"Map loading finished!\n";
	Sleep(500);
	system("cls");
	CONSOLE_FONT_INFOEX cfi;
	cfi.cbSize = sizeof cfi;
	cfi.nFont = 0;
	cfi.dwFontSize.X = 1;
	cfi.dwFontSize.Y = 1;
	cfi.FontWeight = FW_THIN;
	cfi.FontFamily = FF_DONTCARE;
	wcscpy(cfi.FaceName, L"Raster");
	SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &cfi);
	bool SetConsoleFont(HANDLE,DWORD);
	system("mode con cols=4140 lines=4140");
	SetColorAndBackground(7,16);
	for(int i=0;i<=maxx+1;i++){
		cout<<endl;
		for(int j=0;j<=maxy;j++){
			if(i==maxx+1){
				//cout<<j;
				if(j<10){
					//cout<<"  ";
				}
				if(j>=10&&j<100){
				//	cout<<" ";
				}
				continue;
			}
			thread t1(printland(blocks[i][j].look));
			thread t2(blocks[i][j].load_look(blocks[i][j]));
			t2.join();
			t1.join();
		}
		//cout<<" "<<i;
	}
}
void printmap(){
	CONSOLE_FONT_INFOEX cfi;
	cfi.cbSize = sizeof cfi;
	cfi.nFont = 0;
	cfi.dwFontSize.X = 1;
	cfi.dwFontSize.Y = 1;
	cfi.FontWeight = FW_THIN;
	cfi.FontFamily = FF_DONTCARE;
	wcscpy(cfi.FaceName, L"Raster");
	SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &cfi);
	bool SetConsoleFont(HANDLE,DWORD);
	system("cls");
	for(int i=0;i<=maxx+1;i++){
		cout<<endl;
		for(int j=0;j<=maxy;j++){
			blocks[i][j].load_look(blocks[i][j]);
			printland(blocks[i][j].look);
		}
	}
	return;
}
void getfile(){
	ifstream fin("S0.1.5.set");
	cout<<"正在读取文件...\n";
	Sleep(600);
	fin>>maxx>>maxy>>size>>searchcnt;
	cout<<"完成读取文件.\n";
	fin.close();
	Sleep(500);
	system("cls");
	return;
}
void outfile(){
	ofstream fout("S0.1.5.set");
	cout<<"正在保存...\n";
	fout<<maxx<<" "<<maxy<<" "<<size<<" "<<searchcnt; 
	Sleep(500);
	cout<<"保存完毕!\n";
	fout.close();
	return;
}
void save_map(){
	ofstream fout("Map_Save0.1.3.txt");
	cout<<"正在保存...\n"; 
	for(int i=0;i<=maxx+1;i++){
		fout<<endl;
		for(int j=0;j<=maxy;j++){
			fout<<blocks[i][j].lands<<" "; 
		}
	}
	cout<<"保存完毕!\n";
	fout.close(); 
}
void get_map(){
	ifstream fin("Map_Save0.1.3.txt");
	cout<<"正在读入...\n"; 
	for(int i=0;i<=maxx+1;i++){
		for(int j=0;j<=maxy;j++){
			fin>>blocks[i][j].lands;
		}
	}
	cout<<"读入完毕!\n";
	fin.close(); 
}
void MAP(){
	cout<<"0 读入地图存档 1 新建地图 2 保存地图\n";
	cin>>input1;
	if(input1==0){
		get_map();
		printmap();
	}
	else if(input1==1){
		loadmap();
		cout<<"\n保存此地图?1保存 否则退出\n";
		cin>>input1;
		if(input1==1){
			save_map(); 
		}
		else{
			return;
		}
	}
	else if(input1==2){
		save_map();
	}
	else{
		cout<<"输入错误。\n";
		Sleep(500);
		system("cls");
		MAP();	
	}
}  
void start(){
	r:
	cout<<setw(107)<<"请选择游戏模式"<<endl;
	cout<<setw(107)<<"#——————#"<<endl;
	cout<<setw(107)<<"| 开始生存(1)|"<<endl;
	cout<<setw(107)<<"#——————#"<<endl;
	cout<<'\n';
	cout<<setw(107)<<"#——————#"<<endl;
	cout<<setw(107)<<"| 游戏设置(s)|"<<endl;
	cout<<setw(107)<<"#——————#"<<endl;
	cout<<'\n';
	cout<<setw(107)<<"#——————#"<<endl;
	cout<<setw(107)<<"| 退出游戏(e)|"<<endl;
	cout<<setw(107)<<"#——————#"<<endl;
	system("pause");
	if(kbhit('1')){
		MAP();
	}
	else if(kbhit('S')){
		puts("1 地图长宽 2 地形大小 3 生成次数 4检查倍率(越大地形越多样) t 保存 设置 f 退出");
		for(;;){
			system("pause");
			if(kbhit('1')){ 
				cout<<"输入高度。\n"; 
				cin>>input1;
				maxx=input1;
				cout<<"输入宽度。\n"; 
				cin>>input1;
				maxy=input1;
			}
			else if(kbhit('2')){
				cout<<"输入地形最大大小。\n"; 
				cin>>size;
			}
			else if(kbhit('3')){
				cout<<"输入生成次数。\n"; 
				cin>>searchcnt;
			}
			else if(kbhit('4')){
				cout<<"输入检查精度。1x输入1,2x数入2,4x输入3,8x输入4.\n";
				cin>>input1;
				switch(input1){
					case 1:{
						checkr=8; 
						break;
					}
					case 2:{
						checkr=4; 
						break;
					}
					case 3:{
						checkr=2; 
						break;
					}
					case 4:{
						checkr=1; 
						break;
					}
				}
			}
			else if(kbhit('T'))
				outfile();
			else if(kbhit('F')){
				system("cls");
				goto r;
			}
		}
	}
	else if(kbhit('E')){
		int love;
		love = MessageBox(GetConsoleWindow(), "确定要退出游戏嘛?", "确定吗?", MB_YESNOCANCEL|MB_ICONEXCLAMATION);
		if(love==6) 
			return;
		else{
			system("cls"); 
			goto r;	
		}
	}
	else{
		system("cls");
		goto r;
		pass; 
	}
	pass;
	return;
}                 
int main(){ 
	cout.tie(0);
	cin.tie(0);
	getfile();
	//full_screen();
	system("mode con cols=4140 lines=4140");
	start();
}
2021/8/23 22:09
加载中...