Random Map Generator (CLI)
< Edisi command-line interface (Antarmuka berbasis teks) >
Random map generator adalah sebuah program untuk mengarang sebuah peta dan menampilkan hasilnya sebagai gambar JPG.
Sebuah peta dapat direpresentasikan sebagai sebuah matriks dengan elemen nol untuk lautan dan nilai selain nol untuk daratan.
Program ini memanfaatkan algoritma BFS untuk membuat lintasan dari simpul-simpul bernilai bukan nol yang diacak dalam sebuah larik (array) yang elemennya merupakan simpul dengan nilai nol.
1. Acak simpul-simpul tujuan untuk mengarang peta
Petunjuk Pengisian:
- Resolusi peta (map_size): 100 s.d. 1000px
- Ketinggian pulau maksimum (h_max): 1 s.d. 5px
- Ketebalan dataran maksimum (b_max): 1 s.d. 5px
- Spacing antar simpul: 5 s.d. (res_x atau res_y yang terbesar)
!pip install numpy
!pip install pillow
import numpy as np
import random as rand
from PIL import Image, ImageDraw
from IPython.display import display
from collections import deque
def intInputHandler(prompt, min, max):
while True:
try:
user_input = int(input(prompt))
if min <= user_input <= max:
return user_input
else:
print(f"Input harus dalam jangkauan {min}-{max}")
except ValueError:
print("Input harus berupa angka!")
# Mengacak simpul-simpul yang bernilai h_max
def randomizeVertices(res_x, res_y, h_max, map_array, spacing):
num_points_x = res_x // (spacing + 1)
num_points_y = res_y // (spacing + 1)
for i in range(num_points_y):
for j in range(num_points_x):
x = (j + 1) * (spacing + 1)
y = (i + 1) * (spacing + 1)
if x <= res_x and y <= res_y:
map_array[x, y] = rand.choice([0, h_max])
map_size = int(intInputHandler("Masukkan resolusi peta: ", 100, 2000))
res_x, res_y = map_size, map_size
h_max = int(intInputHandler("Masukkan ketinggian maksimum pulau: ", 1, 5))
b_max = int(intInputHandler("Masukkan ketebalan dataran: ", 1, 5))
spacing = int(intInputHandler("Masukkan jarak antar simpul: ", 5, 100))
map_array = np.zeros((res_y, res_x), dtype=int)
randomizeVertices(res_x, res_y, h_max, map_array, spacing)
# Reset peta jika diperlukan
map_array = np.zeros((res_y, res_x), dtype=int)
randomizeVertices(res_x, res_y, h_max, map_array, spacing)
2. Buat lintasan menggunakan algoritma BFS
Membuat sebuah lintasan dari simpul-simpul tujuan yang telah diacak menggunakan algoritma breadth-first search (BFS)
def bfs(unconnected_map_array):
visited = np.zeros_like(unconnected_map_array, dtype=bool)
queue = deque()
# Algoritma BFS akan terus berjalan sampai semua simpul dikunjungi
while visited.all() is not True:
# Cari simpul awal dengan nilai h_max untuk memulai BFS
for i in range(res_y):
for j in range(res_x):
if unconnected_map_array[i, j] == h_max and not visited[i, j]:
queue.append(((i, j), [(i, j)]))
visited[i, j] = True
break
if queue:
break
# Ketika tidak ada lagi simpul awal, maka algoritma berhenti
if not queue:
break
while queue:
current_cell, path = queue.popleft()
# Memeriksa simpul tetangga
for di, dj in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
ni, nj = current_cell[0] + di, current_cell[1] + dj
# Memeriksa apakah simpul selanjutnya berada di dalam array dan belum dikunjungi
if (0 <= ni < res_y and 0 <= nj < res_x and not visited[ni, nj]):
visited[ni, nj] = True
queue.append(((ni, nj), path + [(ni, nj)]))
# Jika ditemukan simpul tujuan, maka ulangi BFS dari situ
if unconnected_map_array[ni, nj] == h_max:
for i in path:
unconnected_map_array[i] = h_max
queue.clear()
queue.append(((ni, nj), [(ni, nj)]))
return unconnected_map_array
connected_map_array = bfs(map_array)
3. Tinjau lintasan yang dibuat
Peninjauan lintasan yang dihasilkan dari algoritma BFS
def drawLines(res_x, res_y, h_max, b_max, connected_map_array):
base_image = Image.new("RGB", (res_x, res_y), (0, 0, 153))
draw = ImageDraw.Draw(base_image)
# Menggambar titik pada setiap simpul yang dilewati lintasan
for i in range(res_y):
for j in range(res_x):
if(connected_map_array[i, j] == 1):
draw.point((i, j), fill="green")
elif(connected_map_array[i, j] == 2):
draw.point((i, j), fill="yellow")
elif(connected_map_array[i, j] == 3):
draw.point((i, j), fill="orange")
elif(connected_map_array[i, j] == 4):
draw.point((i, j), fill="red")
elif(connected_map_array[i, j] == 5):
draw.point((i, j), fill="purple")
display(base_image)
return base_image
base_image = drawLines(res_x, res_y, h_max, b_max, connected_map_array)
4. Gambar dan unduh peta
Klik kanan gambar yang muncul dan unduh menggunakan opsi "Simpan gambar sebagai" atau Save image as
# Ganti ketebalan dataran (b_max) jika diperlukan
b_max = int(input("Ganti b_max ke: ")) or b_max
# Beri nama peta
map_name = input("Masukkan nama peta: ") or "BFS Random Map Generator\nKelompok 6"
# Gambar datarannya saja
from PIL import Image, ImageDraw
def drawMap(res_x, res_y, h_max, b_max, connected_map_array):
# Menambahkan tiap warna pada tiap layer agar tidak overlap
layer0 = Image.new("RGBA", (res_x, res_y), (0, 0, 0, 0))
grid = ImageDraw.Draw(layer0)
draw_layer0 = ImageDraw.Draw(layer0)
draw_grid = ImageDraw.Draw(grid)
# Menggambar pulau :)
for i in range(res_x):
for j in range(res_y):
if(connected_map_array[i][j] == h_max):
draw_layer0.circle((i, j), rand.randint(h_max, h_max*2)*b_max/k, fill="green")
# Menyatukan gambar awal dengan layer-layer yang dibuat
combined_image = Image.alpha_composite(base_image.convert('RGBA'), layer0)
image_scaling = min(1000 / res_x, 1000 / res_y)
combined_image = combined_image.resize((int(res_x * image_scaling), int(res_y * image_scaling)), Image.NEAREST)
layer_info = Image.new("RGBA", (int(res_x * image_scaling), int(res_y * image_scaling)), (0, 0, 0, 0))
draw_layer_info = ImageDraw.Draw(layer_info)
draw_layer_info.text((0,0), map_name, fill=(255,255,255,128), font_size=int(res_x * image_scaling)/30)
combined_image = Image.alpha_composite(combined_image, layer_info)
display(combined_image)
drawMap(res_x, res_y, h_max, b_max, connected_map_array)