{"id":303135,"student_id":10,"content":"","created_at":"2021-10-05T17:54:56.574+08:00","updated_at":"2021-10-06T01:36:41.921+08:00","name":"貪吃蛇 AI(試玩版)","language":"javascript","screenshot":{"url":"/uploads/project/screenshot/303135/123456be4c714c45db14db13eef84a54.jpg"},"parent_id":3,"plugin":"Game.set({ width: 1200, height: 900 })\n\nsetBackdrop('black')\n\nconst SIZE = 60\nconst W = 1200 / SIZE\nconst H = 900 / SIZE\n\nconst food = {\n x: Math.floor(Math.random() * W),\n y: Math.floor(Math.random() * H),\n}\n\n\nfunction createSnakeGame (bodies) {\n \n let snake = {\n direction: 90,\n bodies,\n }\n \n snake.move = function () {\n let head = bodies.pop()\n head.x = bodies[0].x\n head.y = bodies[0].y\n if (snake.direction === 0) head.y -= 1\n if (snake.direction === 90) head.x += 1\n if (snake.direction === 180) head.y += 1\n if (snake.direction === 270) head.x -= 1\n if (bodies.some(pos =\u003e pos.x === head.x \u0026\u0026 pos.y === head.y)) gameover()\n if (head.x \u003c 0 || head.y \u003c 0 || head.x \u003e= W || head.y \u003e= H) gameover()\n if (head.x === food.x \u0026\u0026 head.y === food.y) {\n bodies.push({ x: head.x, y: head.y })\n randomFoodPos(food, bodies)\n }\n bodies.unshift(head)\n }\n \n snake.getHead = function () {\n return bodies[0]\n }\n \n snake.getTail = function () {\n return bodies[bodies.length - 1]\n }\n \n function getFood () {\n return food\n }\n \n forever(function(){\n for (let i = 0; i \u003c bodies.length - 1; i++) {\n pen.color = 'lightgreen'\n pen.fillColor = 'lightgreen'\n let a = bodies[i]\n let b = bodies[i + 1]\n if (a.x \u003e b.x) pen.drawRect(a.x * SIZE - 10, a.y * SIZE + 10, SIZE, SIZE - 20)\n if (a.x \u003c b.x) pen.drawRect(a.x * SIZE + 10, a.y * SIZE + 10, SIZE, SIZE - 20)\n if (a.y \u003e b.y) pen.drawRect(a.x * SIZE + 10, a.y * SIZE - 10, SIZE - 20, SIZE)\n if (a.y \u003c b.y) pen.drawRect(a.x * SIZE + 10, a.y * SIZE + 10, SIZE - 20, SIZE)\n pen.drawRect(b.x * SIZE + 10, b.y * SIZE + 10, SIZE - 20, SIZE - 20)\n }\n pen.fillColor = 'red'\n pen.drawRect(food.x * SIZE + 10, food.y * SIZE + 10, SIZE - 20, SIZE - 20)\n })\n \n return {\n snake,\n getFood,\n }\n \n}\n\nfunction randomFoodPos (food, bodies) {\n let pos = []\n for (var x = 0; x \u003c 20; x++) {\n for (var y = 0; y \u003c 15; y++) {\n if (bodies.some(pos =\u003e pos.x === x \u0026\u0026 pos.y === y) == false) {\n pos.push({ x, y }) \n }\n }\n }\n if (pos.length === 0) return gameover()\n pos = pos[Math.floor(Math.random() * pos.length)]\n food.x = pos.x\n food.y = pos.y\n}\n\n\nfunction gameover () {\n stop()\n drawText('gameover', 10, 10, 'red', 60)\n}\n\n\nlet arrowSprites = []\nfor (var x = 0; x \u003c 20; x++) {\n arrowSprites[x] = []\n for (var y = 0; y \u003c 15; y++) {\n let arrow = createSprite('arrow.png')\n arrow.x = (x + 0.5) * SIZE\n arrow.y = (y + 0.5) * SIZE\n arrow.opacity = 0.5\n arrow.hidden = true\n arrowSprites[x][y] = arrow\n }\n}\n\nfunction drawNumbers (numbers) {\n forever(() =\u003e {\n for (var x = 0; x \u003c 20; x++) {\n for (var y = 0; y \u003c 15; y++) {\n if (numbers[x][y] \u003e= 0) {\n drawText(numbers[x][y], x * SIZE, y * SIZE, 'white', 24)\n }\n }\n } \n })\n}\n\nfunction drawArrows (arrows) {\n forever(() =\u003e {\n for (var x = 0; x \u003c 20; x++) {\n for (var y = 0; y \u003c 15; y++) {\n if ([0, 90, 180, 270].includes(arrows[x][y])) {\n arrowSprites[x][y].hidden = false\n arrowSprites[x][y].direction = arrows[x][y]\n } else {\n arrowSprites[x][y].hidden = true\n }\n }\n }\n })\n}\n\nvar game = createSnakeGame([\n {x: 8, y: 5},\n {x: 7, y: 5},\n {x: 6, y: 5},\n {x: 5, y: 5},\n])\n\n\n\n\nvar clock = 0;\nvar snake = game.snake; // 蛇\nvar arrows = []; // 紀錄格子數字的二維陣列\nvar numbers = []; // 紀錄箭頭方向的二維陣列\n\n// 初始化格子箭頭與格子數字的二維陣列\nfor (var x = 0; x \u003c 20; x++) {\n arrows[x] = []\n numbers[x] = []\n for (var y = 0; y \u003c 15; y++) {\n arrows[x][y] = undefined\n numbers[x][y] = undefined\n }\n}\n\n// drawArrows(arrows); //繪製箭頭\n// drawNumbers(numbers); //繪製數字\nforever(gameloop); //不斷執行遊戲迴圈\nhamilton(); //創造漢米頓圈\ncreateNumbers(); //初始化格子數字\n\nfunction gameloop () {\n clock += 1\n if (clock % 1 == 0) {\n AI()\n if (key.up) snake.direction = 0\n if (key.down) snake.direction = 180\n if (key.right) snake.direction = 90\n if (key.left) snake.direction = 270\n snake.move() \n }\n}\n\n// 產生漢米頓圈\nfunction hamilton () {\n for (let x = 0; x \u003c 20; x++) {\n for (let y = 0; y \u003c 15; y++) {\n \n if (x % 2 == 0) {\n arrows[x][y] = 180\n } else {\n arrows[x][y] = 0\n }\n \n if (y == 0) arrows[x][y] = 270\n if (y == 1 \u0026\u0026 x % 2 == 1) {\n arrows[x][y] = 90\n }\n if (y == 14 \u0026\u0026 x % 2 == 0) {\n arrows[x][y] = 90\n }\n \n arrows[0][0] = 180\n arrows[19][1] = 0\n }\n }\n}\n\n// 依據箭頭方向將數字填入格子\nfunction createNumbers () {\n var x = 0;\n var y = 0;\n for (var i = 0; i \u003c 300; i++) {\n numbers[x][y] = i\n var d = arrows[x][y]\n if (d == 0) y -= 1\n if (d == 90) x += 1\n if (d == 180) y += 1\n if (d == 270) x -= 1\n }\n}\n\n// 判斷該格子是否可以作為捷徑\nfunction isShortCut (headNum, tailNum, foodNum, nextNum) {\n if (headNum \u003e foodNum) {\n if (nextNum \u003c headNum \u0026\u0026 nextNum \u003e foodNum) return false\n } else {\n if (nextNum \u003c headNum || nextNum \u003e foodNum) return false\n }\n \n if (headNum \u003e tailNum) {\n if (nextNum \u003c headNum \u0026\u0026 nextNum \u003e tailNum - 1) return false\n } else {\n if (nextNum \u003c headNum || nextNum \u003e tailNum - 1) return false\n }\n \n return true\n}\n\nfunction AI () {\n var head = snake.getHead()\n var tail = snake.getTail()\n var food = game.getFood()\n \n if (arrows[head.x][head.y] != undefined) {\n snake.direction = arrows[head.x][head.y]\n }\n \n var headNum = numbers[head.x][head.y]\n var tailNum = numbers[tail.x][tail.y]\n var foodNum = numbers[food.x][food.y]\n \n if (head.x \u003c 19) {\n var nextNum = numbers[head.x + 1][head.y]\n if (isShortCut(headNum, tailNum, foodNum, nextNum)) {\n snake.direction = 90\n }\n }\n else if (head.x \u003e 0) {\n var nextNum = numbers[head.x - 1][head.y]\n if (isShortCut(headNum, tailNum, foodNum, nextNum)) {\n snake.direction = 270\n }\n }\n else if (head.y \u003c 14) {\n var nextNum = numbers[head.x][head.y + 1]\n if (isShortCut(headNum, tailNum, foodNum, nextNum)) {\n snake.direction = 180\n }\n }\n else if (head.y \u003e 0) {\n var nextNum = numbers[head.x][head.y - 1]\n if (isShortCut(headNum, tailNum, foodNum, nextNum)) {\n snake.direction = 0\n }\n }\n}\n","description":null,"note":null,"status":"public","like_student_ids":[],"is_featured":false,"views":366,"hashid":"npms398kd","is_content_changed":false,"review_status":"unsubmitted","submitted_at":null,"reviewed_at":null,"advise":null,"is_deleted":false}
[{"id":6153006,"file_name":"arrow.png","project_id":303135,"asset_id":424460,"created_at":"2021-10-06T01:36:07.568+08:00","updated_at":"2021-10-06T01:36:07.568+08:00"}]
Orange Apple Learning Platform
My Projects
View Project Page
Export
Remix
Import
Delete
Download Android APP (APK)
Screenshot
繁中
简中
English
日本語
1:1:1
1:1
Full Width
Scan the QRCode below with your phone to install
Or you can
download APK
to this computer
Scan the QRCode below with your phone to install
Or you can
download APK
to this computer