xX-AAAAAAAAAA-Xx

ComputerCraft Maze Game

Sep 4th, 2024
91
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.26 KB | None | 0 0
  1. -- Maze Generation Using Depth-First Search
  2. local width, height = 20, 20
  3. local maze = {}
  4. local visited = {}
  5.  
  6. for y = 1, height do
  7. maze[y] = {}
  8. visited[y] = {}
  9. for x = 1, width do
  10. maze[y][x] = 1 -- 1 = wall
  11. visited[y][x] = false
  12. end
  13. end
  14.  
  15. local directions = {
  16. {x = 2, y = 0},
  17. {x = -2, y = 0},
  18. {x = 0, y = 2},
  19. {x = 0, y = -2}
  20. }
  21.  
  22. function generateMaze(x, y)
  23. visited[y][x] = true
  24. maze[y][x] = 0 -- 0 = path
  25.  
  26. local shuffled = {}
  27. for i = 1, #directions do
  28. shuffled[i] = directions[i]
  29. end
  30. for i = #shuffled, 2, -1 do
  31. local j = math.random(i)
  32. shuffled[i], shuffled[j] = shuffled[j], shuffled[i]
  33. end
  34.  
  35. for _, dir in ipairs(shuffled) do
  36. local nx, ny = x + dir.x, y + dir.y
  37. local mx, my = x + dir.x / 2, y + dir.y / 2
  38. if nx > 0 and ny > 0 and nx <= width and ny <= height and not visited[ny][nx] then
  39. maze[my][mx] = 0
  40. generateMaze(nx, ny)
  41. end
  42. end
  43. end
  44.  
  45. math.randomseed(os.time())
  46. generateMaze(2, 2)
  47.  
  48. -- Player and goal
  49. local playerX, playerY = 2, 2
  50. local goalX, goalY = width - 1, height - 1
  51.  
  52. -- Limited view settings
  53. local viewWidth, viewHeight = 10, 10
  54.  
  55. -- Function to draw the maze with player centered
  56. function drawMaze()
  57. term.clear()
  58.  
  59. local startX = math.max(1, playerX - math.floor(viewWidth / 2))
  60. local startY = math.max(1, playerY - math.floor(viewHeight / 2))
  61. local endX = math.min(width, playerX + math.floor(viewWidth / 2))
  62. local endY = math.min(height, playerY + math.floor(viewHeight / 2))
  63.  
  64. -- Adjust for view dimensions
  65. local viewXStart = math.max(1, playerX - math.floor(viewWidth / 2))
  66. local viewYStart = math.max(1, playerY - math.floor(viewHeight / 2))
  67.  
  68. for y = startY, endY do
  69. for x = startX, endX do
  70. local screenX = x - viewXStart + 1
  71. local screenY = y - viewYStart + 1
  72. if x == playerX and y == playerY then
  73. term.setCursorPos(screenX, screenY)
  74. term.write("P") -- Player
  75. elseif x == goalX and y == goalY then
  76. term.setCursorPos(screenX, screenY)
  77. term.write("G") -- Goal
  78. elseif maze[y][x] == 1 then
  79. term.setCursorPos(screenX, screenY)
  80. term.write("#") -- Wall
  81. else
  82. term.setCursorPos(screenX, screenY)
  83. term.write(" ") -- Path
  84. end
  85. end
  86. end
  87. end
  88.  
  89. -- Function to move the player
  90. function movePlayer(dx, dy)
  91. local newX = playerX + dx
  92. local newY = playerY + dy
  93.  
  94. if newX > 0 and newX <= width and newY > 0 and newY <= height and maze[newY][newX] == 0 then
  95. playerX = newX
  96. playerY = newY
  97. end
  98. end
  99.  
  100. -- Main game loop
  101. while true do
  102. drawMaze()
  103. local event, key = os.pullEvent("key")
  104.  
  105. if key == keys.w then
  106. movePlayer(0, -1)
  107. elseif key == keys.s then
  108. movePlayer(0, 1)
  109. elseif key == keys.a then
  110. movePlayer(-1, 0)
  111. elseif key == keys.d then
  112. movePlayer(1, 0)
  113. end
  114.  
  115. if playerX == goalX and playerY == goalY then
  116. term.clear()
  117. print("Congratulations, you won!")
  118. break
  119. end
  120. end
  121.  
Advertisement
Comments
  • OwlMan01
    110 days
    1. I have create a similar JS script that ,I am using in https://freemazegenerator.org/, Can you suggesr me a way by which I can create custom maze sape. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8" />
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    6. <title>Square Maze Generator</title>
    7. <style>
    8.   * { margin: 0; padding: 0; box-sizing: border-box; }
    9.   body {
    10.     font-family: system-ui, sans-serif;
    11.     background: #1a1a2e;
    12.     display: flex;
    13.     justify-content: center;
    14.     align-items: center;
    15.     min-height: 100vh;
    16.     flex-direction: column;
    17.     gap: 1rem;
    18.   }
    19.   canvas { border-radius: 8px; box-shadow: 0 0 30px rgba(0,0,0,.5); }
    20.   .controls { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; justify-content: center; }
    21.   label { color: #e0e0e0; font-size: .9rem; }
    22.   input[type="range"] { width: 120px; }
    23.   span { color: #e0e0e0; font-size: .85rem; min-width: 24px; text-align: center; }
    24.   button {
    25.     background: #e94560; color: #fff; border: none; padding: .5rem 1.2rem;
    26.     border-radius: 6px; cursor: pointer; font-size: .9rem; font-weight: 600;
    27.     transition: background .2s;
    28.   }
    29.   button:hover { background: #c73650; }
    30.   .check { display: flex; align-items: center; gap: .4rem; }
    31.   .check input { width: 16px; height: 16px; cursor: pointer; }
    32. </style>
    33. </head>
    34. <body>
    35.  
    36. <canvas id="maze"></canvas>
    37.  
    38. <div class="controls">
    39.   <label>Size <input type="range" id="size" min="5" max="50" value="15" /><span id="sizeVal">15</span></label>
    40.   <label>Cell <input type="range" id="cell" min="8" max="40" value="24" /><span id="cellVal">24</span></label>
    41.   <div class="check"><input type="checkbox" id="solve" /><label>Solution</label></div>
    42.   <button id="generate">Generate</button>
    43. </div>
    44.  
    45. <script>
    46. const canvas = document.getElementById('maze');
    47. const ctx = canvas.getContext('2d');
    48.  
    49. const sizeInput = document.getElementById('size');
    50. const cellInput = document.getElementById('cell');
    51. const sizeVal = document.getElementById('sizeVal');
    52. const cellVal = document.getElementById('cellVal');
    53. const solveCheck = document.getElementById('solve');
    54. const genBtn = document.getElementById('generate');
    55.  
    56. let grid = [], solution = [];
    57.  
    58. class Cell {
    59.   constructor(r, c) {
    60.     this.r = r; this.c = c;
    61.     this.walls = { top: true, right: true, bottom: true, left: true };
    62.     this.visited = false;
    63.   }
    64. }
    65.  
    66. function buildGrid(rows, cols) {
    67.   grid = Array.from({ length: rows }, (_, r) =>
    68.     Array.from({ length: cols }, (_, c) => new Cell(r, c))
    69.   );
    70. }
    71.  
    72. function getNeighbors(cell, rows, cols) {
    73.   const { r, c } = cell;
    74.   const nbs = [];
    75.   if (r > 0) nbs.push(grid[r - 1][c]);
    76.   if (r < rows - 1) nbs.push(grid[r + 1][c]);
    77.   if (c > 0) nbs.push(grid[r][c - 1]);
    78.   if (c < cols - 1) nbs.push(grid[r][c + 1]);
    79.   return nbs.filter(n => !n.visited);
    80. }
    81.  
    82. function removeWall(a, b) {
    83.   const dr = a.r - b.r, dc = a.c - b.c;
    84.   if (dr === 1) { a.walls.top = false; b.walls.bottom = false; }
    85.   if (dr === -1) { a.walls.bottom = false; b.walls.top = false; }
    86.   if (dc === 1) { a.walls.left = false; b.walls.right = false; }
    87.   if (dc === -1) { a.walls.right = false; b.walls.left = false; }
    88. }
    89.  
    90. function generate(rows, cols) {
    91.   buildGrid(rows, cols);
    92.   const stack = [grid[0][0]];
    93.   grid[0][0].visited = true;
    94.   while (stack.length) {
    95.     const cur = stack[stack.length - 1];
    96.     const nbs = getNeighbors(cur, rows, cols);
    97.     if (!nbs.length) { stack.pop(); continue; }
    98.     const next = nbs[Math.floor(Math.random() * nbs.length)];
    99.     next.visited = true;
    100.     removeWall(cur, next);
    101.     stack.push(next);
    102.   }
    103. }
    104.  
    105. function bfs(rows, cols) {
    106.   const start = grid[0][0], end = grid[rows - 1][cols - 1];
    107.   const queue = [[start]];
    108.   const visited = new Set();
    109.   visited.add(`${start.r},${start.c}`);
    110.   while (queue.length) {
    111.     const path = queue.shift();
    112.     const cur = path[path.length - 1];
    113.     if (cur === end) return path;
    114.     for (const [dr, dc, wall, opp] of [[-1,0,'top','bottom'],[1,0,'bottom','top'],[0,-1,'left','right'],[0,1,'right','left']]) {
    115.       const nr = cur.r + dr, nc = cur.c + dc;
    116.       if (nr < 0 || nr >= rows || nc < 0 || nc >= cols) continue;
    117.       if (cur.walls[wall]) continue;
    118.       const key = `${nr},${nc}`;
    119.       if (visited.has(key)) continue;
    120.       visited.add(key);
    121.       queue.push([...path, grid[nr][nc]]);
    122.     }
    123.   }
    124.   return [];
    125. }
    126.  
    127. function draw(rows, cols, cellSize) {
    128.   const w = cols * cellSize + 1, h = rows * cellSize + 1;
    129.   canvas.width = w; canvas.height = h;
    130.   ctx.clearRect(0, 0, w, h);
    131.   ctx.strokeStyle = '#e0e0e0';
    132.   ctx.lineWidth = 2;
    133.  
    134.   for (let r = 0; r < rows; r++) {
    135.     for (let c = 0; c < cols; c++) {
    136.       const x = c * cellSize, y = r * cellSize;
    137.       const cell = grid[r][c];
    138.       if (cell.walls.top)    { ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(x + cellSize, y); ctx.stroke(); }
    139.       if (cell.walls.right)  { ctx.beginPath(); ctx.moveTo(x + cellSize, y); ctx.lineTo(x + cellSize, y + cellSize); ctx.stroke(); }
    140.       if (cell.walls.bottom) { ctx.beginPath(); ctx.moveTo(x, y + cellSize); ctx.lineTo(x + cellSize, y + cellSize); ctx.stroke(); }
    141.       if (cell.walls.left)   { ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(x, y + cellSize); ctx.stroke(); }
    142.     }
    143.   }
    144.  
    145.   // start & end
    146.   ctx.fillStyle = '#4ade80';
    147.   ctx.fillRect(1, 1, cellSize - 2, 4);
    148.   ctx.fillStyle = '#ef4444';
    149.   ctx.fillRect(1, h - cellSize + 1, cellSize - 2, 4);
    150.  
    151.   if (solveCheck.checked && solution.length) {
    152.     ctx.strokeStyle = '#facc15';
    153.     ctx.lineWidth = 3;
    154.     ctx.beginPath();
    155.     for (let i = 0; i < solution.length; i++) {
    156.       const x = solution[i].c * cellSize + cellSize / 2;
    157.       const y = solution[i].r * cellSize + cellSize / 2;
    158.       i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
    159.     }
    160.     ctx.stroke();
    161.   }
    162. }
    163.  
    164. function render() {
    165.   const rows = +sizeInput.value, cols = rows;
    166.   const cellSize = +cellInput.value;
    167.   generate(rows, cols);
    168.   solution = bfs(rows, cols);
    169.   draw(rows, cols, cellSize);
    170. }
    171.  
    172. sizeInput.addEventListener('input', () => { sizeVal.textContent = sizeInput.value; render(); });
    173. cellInput.addEventListener('input', () => { cellVal.textContent = cellInput.value; render(); });
    174. solveCheck.addEventListener('change', () => render());
    175. genBtn.addEventListener('click', render);
    176.  
    177. render();
    178. </script>
    179. </body>
    180. </html>
    181.  
Add Comment
Please, Sign In to add comment