1// è´ªåèæ¸¸æç¶æ 2let snake = []; 3let food = { x: 0, y: 0 }; 4let direction = 'right'; 5let gameInterval = null; 6let score = 0; 7let isPaused = false; 8let gameStarted = false; 9let highScore = 0; 10 11// 游æé ç½® 12const config = { 13 gridSize: 20, 14 speed: 150, 15 initialLength: 3 16}; 17 18// åå§å游æ 19function initGame() { 20 const canvas = document.getElementById('snake-canvas'); 21 const ctx = canvas.getContext('2d'); 22 23 // åå§åèçä½ç½® 24 snake = []; 25 for (let i = 0; i < config.initialLength; i++) { 26 snake.push({ 27 x: Math.floor(config.gridSize / 2) - i, 28 y: Math.floor(config.gridSize / 2) 29 }); 30 } 31 32 // çæç¬¬ä¸ä¸ªé£ç© 33 generateFood(); 34 35 // éç½®åæ° 36 score = 0; 37 updateScore(); 38 39 // æ¸ é¤ç»å¸ 40 ctx.clearRect(0, 0, canvas.width, canvas.height); 41 42 // ç»å¶åå§ç¶æ 43 drawGame(); 44} 45 46// çæé£ç© 47function generateFood() { 48 let newFood; 49 do { 50 newFood = { 51 x: Math.floor(Math.random() * config.gridSize), 52 y: Math.floor(Math.random() * config.gridSize) 53 }; 54 } while (snake.some(segment => segment.x === newFood.x && segment.y === newFood.y)); 55 56 food = newFood; 57} 58 59// æ´æ°æ¸¸æç¶æ 60function updateGame() { 61 if (isPaused || !gameStarted) return; 62 63 // è·åè头çä¸ä¸ä¸ªä½ç½® 64 const head = { ...snake[0] }; 65 switch (direction) { 66 case 'up': 67 head.y--; 68 break; 69 case 'down': 70 head.y++; 71 break; 72 case 'left': 73 head.x--; 74 break; 75 case 'right': 76 head.x++; 77 break; 78 } 79 80 // æ£æ¥æ¯å¦æå¢ 81 if (head.x < 0 || head.x >= config.gridSize || head.y < 0 || head.y >= config.gridSize) { 82 gameOver(); 83 return; 84 } 85 86 // æ£æ¥æ¯å¦æå°èªå·± 87 if (snake.some(segment => segment.x === head.x && segment.y === head.y)) { 88 gameOver(); 89 return; 90 } 91 92 // ç§»å¨è 93 snake.unshift(head); 94 95 // æ£æ¥æ¯å¦åå°é£ç© 96 if (head.x === food.x && head.y === food.y) { 97 score += 10; 98 updateScore(); 99 generateFood(); 100 } else { 101 snake.pop(); 102 } 103 104 // éæ°ç»å¶æ¸¸æ 105 drawGame(); 106} 107 108// ç»å¶æ¸¸æ 109function drawGame() { 110 const canvas = document.getElementById('snake-canvas'); 111 const ctx = canvas.getContext('2d'); 112 const cellSize = canvas.width / config.gridSize; 113 114 // æ¸ é¤ç»å¸ 115 ctx.clearRect(0, 0, canvas.width, canvas.height); 116 117 // ç»å¶ç½æ ¼ 118 ctx.strokeStyle = '#ccc'; 119 for (let i = 0; i <= config.gridSize; i++) { 120 ctx.beginPath(); 121 ctx.moveTo(i * cellSize, 0); 122 ctx.lineTo(i * cellSize, canvas.height); 123 ctx.stroke(); 124 125 ctx.beginPath(); 126 ctx.moveTo(0, i * cellSize); 127 ctx.lineTo(canvas.width, i * cellSize); 128 ctx.stroke(); 129 } 130 131 // ç»å¶é£ç© 132 ctx.fillStyle = 'red'; 133 ctx.fillRect(food.x * cellSize, food.y * cellSize, cellSize, cellSize); 134 135 // ç»å¶è 136 snake.forEach((segment, index) => { 137 ctx.fillStyle = index === 0 ? '#006400' : '#008000'; 138 ctx.fillRect(segment.x * cellSize, segment.y * cellSize, cellSize, cellSize); 139 }); 140} 141 142// æ´æ°åæ°æ¾ç¤º 143function updateScore() { 144 const scoreElement = document.getElementById('snake-score'); 145 scoreElement.textContent = score; 146 147 if (score > highScore) { 148 highScore = score; 149 const statusBar = document.querySelector('#snake-window .status-bar'); 150 statusBar.children[1].textContent = `æé«åï¼${highScore}`; 151 } 152} 153 154// 游æç»æ 155function gameOver() { 156 clearInterval(gameInterval); 157 gameStarted = false; 158 159 // æ´æ°å¼¹çªä¸çåæ° 160 document.getElementById('final-score').textContent = score; 161 document.getElementById('high-score').textContent = highScore; 162 163 // æ¾ç¤ºæ¸¸æç»æå¼¹çª 164 document.getElementById('game-over-dialog').style.display = 'block'; 165} 166 167// å ³éæ¸¸æç»æå¼¹çª 168function closeGameOverDialog() { 169 document.getElementById('game-over-dialog').style.display = 'none'; 170 initGame(); 171} 172 173// éæ°å¼å§æ¸¸æ 174function restartGame() { 175 document.getElementById('game-over-dialog').style.display = 'none'; 176 initGame(); 177 startSnakeGame(); 178} 179 180// å¼å§æ¸¸æ 181function startSnakeGame() { 182 if (!gameStarted) { 183 gameStarted = true; 184 isPaused = false;
185 initGame(); 186 gameInterval = setInterval(updateGame, config.speed); 187 } 188} 189 190// æå游æ 191function pauseSnakeGame() { 192 if (gameStarted) { 193 isPaused = !isPaused; 194 const pauseButton = document.querySelector('#snake-window .control-buttons .win95-button:nth-child(2)'); 195 pauseButton.textContent = isPaused ? 'ç»§ç»' : 'æå'; 196 } 197} 198 199// é®çæ§å¶ 200function isTypingInEditable() { 201 const active = document.activeElement; 202 if (!active) return false; 203 const tag = active.tagName; 204 if (tag === 'INPUT' || tag === 'TEXTAREA') return true; 205 const ce = active.getAttribute && active.getAttribute('contenteditable'); 206 return ce === '' || ce === 'true' || ce === 'plaintext-only'; 207} 208 209document.addEventListener('keydown', (event) => { 210 if (typeof activeWindow !== 'undefined' && activeWindow !== 'snake') return; 211 if (isTypingInEditable()) return; 212 if (!gameStarted || isPaused) return; 213 214 switch (event.key) { 215 case 'ArrowUp': 216 if (direction !== 'down') direction = 'up'; 217 break; 218 case 'ArrowDown': 219 if (direction !== 'up') direction = 'down'; 220 break; 221 case 'ArrowLeft': 222 if (direction !== 'right') direction = 'left'; 223 break; 224 case 'ArrowRight': 225 if (direction !== 'left') direction = 'right'; 226 break; 227 } 228}); 229 230// åå§å游æ 231window.addEventListener('load', () => { 232 initGame(); 233});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.