{"id":75496,"student_id":119,"content":"var SIZE = 70; // 每個世代的個數\nvar DNA_LENGTH = 24; // DNA 的長度\nvar generation = 0; // 紀錄目前是第幾代\nvar count = 0;\n//initalMaps([[{\"x\":35,\"y\":48},{\"x\":265,\"y\":47},{\"x\":341,\"y\":122},{\"x\":402,\"y\":50},{\"x\":440,\"y\":117},{\"x\":485,\"y\":51}],[{\"x\":84,\"y\":117},{\"x\":247,\"y\":117},{\"x\":336,\"y\":208},{\"x\":393,\"y\":152},{\"x\":438,\"y\":209},{\"x\":492,\"y\":141}],[{\"x\":489,\"y\":51},{\"x\":485,\"y\":52},{\"x\":494,\"y\":51},{\"x\":503,\"y\":52},{\"x\":520,\"y\":56},{\"x\":531,\"y\":58},{\"x\":541,\"y\":59},{\"x\":545,\"y\":66},{\"x\":561,\"y\":71},{\"x\":567,\"y\":74},{\"x\":574,\"y\":78},{\"x\":588,\"y\":88},{\"x\":592,\"y\":91},{\"x\":593,\"y\":104},{\"x\":594,\"y\":109},{\"x\":602,\"y\":122},{\"x\":607,\"y\":130},{\"x\":607,\"y\":142},{\"x\":607,\"y\":148},{\"x\":607,\"y\":157},{\"x\":607,\"y\":162},{\"x\":601,\"y\":171},{\"x\":584,\"y\":184},{\"x\":564,\"y\":192},{\"x\":565,\"y\":206},{\"x\":587,\"y\":225},{\"x\":602,\"y\":245},{\"x\":575,\"y\":255},{\"x\":550,\"y\":255},{\"x\":537,\"y\":269},{\"x\":592,\"y\":310}],[{\"x\":496,\"y\":142},{\"x\":490,\"y\":142},{\"x\":507,\"y\":154},{\"x\":512,\"y\":162},{\"x\":502,\"y\":175},{\"x\":487,\"y\":187},{\"x\":493,\"y\":217},{\"x\":478,\"y\":258},{\"x\":476,\"y\":285},{\"x\":482,\"y\":302},{\"x\":494,\"y\":315},{\"x\":522,\"y\":328},{\"x\":534,\"y\":334}],[{\"x\":518,\"y\":360},{\"x\":508,\"y\":367},{\"x\":534,\"y\":335}],[{\"x\":594,\"y\":315},{\"x\":592,\"y\":312},{\"x\":602,\"y\":330},{\"x\":575,\"y\":358},{\"x\":601,\"y\":383},{\"x\":590,\"y\":400},{\"x\":608,\"y\":431},{\"x\":576,\"y\":461},{\"x\":567,\"y\":475},{\"x\":454,\"y\":475}],[{\"x\":447,\"y\":419},{\"x\":451,\"y\":426},{\"x\":442,\"y\":413},{\"x\":442,\"y\":410},{\"x\":448,\"y\":402},{\"x\":458,\"y\":397},{\"x\":469,\"y\":392},{\"x\":476,\"y\":386},{\"x\":478,\"y\":377},{\"x\":476,\"y\":369},{\"x\":468,\"y\":348},{\"x\":463,\"y\":339},{\"x\":461,\"y\":337},{\"x\":451,\"y\":323},{\"x\":447,\"y\":316},{\"x\":439,\"y\":303},{\"x\":433,\"y\":298},{\"x\":424,\"y\":290},{\"x\":421,\"y\":288},{\"x\":413,\"y\":292},{\"x\":401,\"y\":308},{\"x\":404,\"y\":327},{\"x\":392,\"y\":340},{\"x\":353,\"y\":329},{\"x\":344,\"y\":300},{\"x\":335,\"y\":280},{\"x\":313,\"y\":281},{\"x\":300,\"y\":301},{\"x\":308,\"y\":320},{\"x\":301,\"y\":337}],[{\"x\":441,\"y\":476},{\"x\":454,\"y\":477},{\"x\":406,\"y\":472},{\"x\":401,\"y\":469},{\"x\":401,\"y\":466},{\"x\":404,\"y\":457},{\"x\":391,\"y\":440},{\"x\":384,\"y\":435},{\"x\":383,\"y\":430},{\"x\":384,\"y\":424},{\"x\":392,\"y\":412},{\"x\":392,\"y\":408},{\"x\":387,\"y\":386},{\"x\":372,\"y\":375},{\"x\":360,\"y\":380},{\"x\":349,\"y\":395},{\"x\":341,\"y\":407},{\"x\":335,\"y\":408},{\"x\":324,\"y\":403},{\"x\":311,\"y\":416},{\"x\":305,\"y\":439},{\"x\":287,\"y\":446},{\"x\":276,\"y\":447},{\"x\":252,\"y\":463},{\"x\":183,\"y\":469},{\"x\":198,\"y\":446},{\"x\":154,\"y\":445},{\"x\":179,\"y\":412},{\"x\":131,\"y\":411},{\"x\":164,\"y\":383},{\"x\":105,\"y\":374},{\"x\":158,\"y\":336},{\"x\":69,\"y\":329},{\"x\":100,\"y\":281},{\"x\":45,\"y\":273}],[{\"x\":295,\"y\":342},{\"x\":300,\"y\":336},{\"x\":250,\"y\":402},{\"x\":251,\"y\":376},{\"x\":222,\"y\":383},{\"x\":240,\"y\":351},{\"x\":208,\"y\":344},{\"x\":227,\"y\":321},{\"x\":202,\"y\":302},{\"x\":197,\"y\":274},{\"x\":154,\"y\":260}],[{\"x\":142,\"y\":256},{\"x\":153,\"y\":262},{\"x\":137,\"y\":225},{\"x\":107,\"y\":212},{\"x\":107,\"y\":193},{\"x\":68,\"y\":193},{\"x\":87,\"y\":156},{\"x\":76,\"y\":141},{\"x\":84,\"y\":117}],[{\"x\":43,\"y\":265},{\"x\":44,\"y\":275},{\"x\":46,\"y\":274},{\"x\":21,\"y\":256},{\"x\":15,\"y\":223},{\"x\":10,\"y\":197},{\"x\":25,\"y\":185},{\"x\":14,\"y\":151},{\"x\":21,\"y\":132},{\"x\":12,\"y\":101},{\"x\":22,\"y\":75},{\"x\":33,\"y\":51}]])\nfor (var i = 0; i \u003c SIZE; i++) {\n let car = new Car();\n for (var j = -45; j \u003c= 45; j += 45) {\n car.addSensor(j);\n }\n car.reset(50, 80, 90);\n car.speed = 4;\n car.gens = randomDNA(DNA_LENGTH);\n car.score = 0;\n car.xx=car.x;\n car.yy=car.y;\n forever(function() {\n if (car.status != 'running') {\n return;\n }\n var output = NN(car.sensorsData.concat(car.speed), car.gens);\n car.turn(output[0]*4);\n car.speedUp(output[1]/10);\n car.score+=car.speed;\n if(count % 30 == 0){\n var diff = (car.xx-car.x)**2 + (car.yy-car.y)**2;\n if(car.speed == 0){car.status=\"broken\"}\n car.score += diff;\n car.xx=car.x;\n car.yy=car.y;\n }\n });\n}\nforever(function() {\n count++;\n for (var i = 0; i \u003c cars.length; i++) {\n if (cars[i].status == 'running') {\n return;\n }\n }\n print('結束');\n nextGeneration();\n});\n//===========示範程式開始實作後可移除===========//\n/*var car = new Car();\ncar.speed = 3; // 設定車速\ncar.reset(50, 50, 90);\n\nforever(function () {\n if (key.right) car.turn(18);\n if (key.left) car.turn(-18);\n if (key.up) car.speedUp(0.1);\n if (key.down) car.speedUp(-0.1);\n});*/\n//============================================//\n\n// 手動進入下一個世代來加速學習\n\n\nwhen('keydown', 'space', nextGeneration);\n\n// 不斷檢查所有車子的狀態是否都毀損\n// 如果是則進入下一個世代\n\n\n// 當所有車子都壞掉時,會觸發這個函式\nfunction nextGeneration () {\n console.log('產生下一代車子...');\n cars.sort(function(a, b) {\n return b.score-a.score;\n });\n var p1 = cars[0].gens;\n var p2 = cars[1].gens;\n for (var i = 0; i \u003c cars.length; i++) {\n cars[i].gens = crossover(p1, p2);\n cars[i].reset(50, 80, 90);\n cars[i].speed = 4;\n cars[i].score = 0;\n }\n}\n\n// 產生 dna1 dna2 的下一代基因\nfunction crossover (a, b) {\n var newgens = [];\n for (var i = 0; i \u003c DNA_LENGTH; i++) {\n if (Math.random() \u003c 0.02) {\n newgens.push(Math.floor(Math.random()*4));\n } else if (Math.random() \u003e 0.5) {\n newgens.push(a[i]);\n } else {\n newgens.push(b[i]);\n }\n }\n return newgens;\n}\n\n// length 要產生的 dna 長度\nfunction randomDNA (length) {\n var DNA = [];\n for (var i = 0; i \u003c length; i++) {\n DNA.push(Math.random()*2-1);\n }\n return DNA;\n}\n\n// S型函數\nfunction sigmoid(x) {\n return (Math.exp(x)-Math.exp(-x))/(Math.exp(x)+Math.exp(-x));\n}\n\n// input*5 hidden*4 output*1\nfunction NN (i, w) {\n var a = i[0]*w[0]+i[1]*w[1]+i[2]*w[2]+i[3]*w[3];\n a = sigmoid(a);\n var b = i[0]*w[4]+i[1]*w[5]+i[2]*w[6]+i[3]*w[7];\n b = sigmoid(b);\n var c = i[0]*w[8]+i[1]*w[9]+i[2]*w[10]+i[3]*w[11];\n c = sigmoid(c);\n var d = i[0]*w[12]+i[1]*w[13]+i[2]*w[14]+i[3]*w[15];\n d = sigmoid(d);\n var e = i[0]*w[16]+i[1]*w[17]+i[2]*w[18]+i[3]*w[19];\n e = sigmoid(d);\n var f = a*w[20]+b*w[21]+c*w[22]+d*w[23]+e*w[24];\n var g = a*w[25]+b*w[26]+c*w[27]+d*w[28]+e*w[29];\n console.log(output);\n return [f,g];\n}","created_at":"2019-06-29T09:10:25.287+08:00","updated_at":"2019-10-04T04:28:22.122+08:00","name":"自動駕駛(賽車版) 副本","language":"javascript","screenshot":{"url":null},"parent_id":61709,"plugin":"function Point (x, y) {\n this.x = x || 0;\n this.y = y || 0;\n}\n\nfunction Line (p1, p2, size, color) {\n\n this.p1 = p1;\n this.p2 = p2;\n this.size = size || 1;\n this.color = color || 'black';\n this.a = 0;\n this.b = 0;\n \n // 使用在繪圖用對應的 forever\n this.instance = createSprite('dot.jpg');\n this.instance.hidden = true;\n \n // y = ax + b\n // a:斜率 b:常數\n this.update = function () {\n // 計算斜率\n this.a = (this.p1.y - this.p2.y) / (this.p1.x - this.p2.x);\n \n // 這招真的很無恥,斜率 1000 畫面上分辨不出是否垂直線\n // 在計算交會點的時候就很方便,不用再判斷是否為垂直線\n if (Math.abs(this.a) \u003e 1000) this.a = 1000;\n \n // 計算常數項\n this.b = this.p1.y - this.p1.x*this.a;\n }\n this.update(); // 初始化更新\n \n \n // 取得兩線斷相交的座標,如果沒有相交就回傳 undefined\n this.touched = function (line) {\n\n if (!this.isCrossWith(line)) return; // undefined\n \n let x = (line.b - this.b)/(this.a - line.a);\n let y = this.a*x + this.b;\n return {x: x, y: y};\n }\n \n // 兩線斷是否相交\n this.isCrossWith = function (line) {\n return line._calc(this.p1.x, this.p1.y) * line._calc(this.p2.x, this.p2.y) \u003c 0 \u0026\u0026\n this._calc(line.p1.x, line.p1.y) * this._calc(line.p2.x, line.p2.y) \u003c 0\n }\n\n this._calc = function (x, y) {\n if (Math.abs(this.a) == Infinity) return x - this.b;\n return this.a*x + this.b - y;\n }\n \n // 渲染線條\n this.render = function () {\n pen.size = this.size;\n pen.color = this.color;\n pen.drawLine(this.p1.x, this.p1.y, this.p2.x, this.p2.y);\n }\n \n // 刪除線條\n this.destroy = this.instance.destroy.bind(this.instance);\n \n var self = this;\n this.instance.forever(function(){\n self.update();\n self.render();\n });\n}\n\n\nvar walls = []; // 存放賽道線條\nvar cars = []; // 存放所有製造出來的車子\n\n\nfunction Car (x, y) {\n \n let width = 17; // 車體中心到四個角的距離\n let sensorLength = 1000; // 感測器的長度距離\n\n let center = createSprite('dot.jpg');\n center.x = x || 320;\n center.y = y || 240;\n center.speed = 1; // 預設車速\n center.status = 'running'; // running, broken\n \n // 車體的四個點\n let p1 = new Point();\n let p2 = new Point();\n let p3 = new Point();\n let p4 = new Point();\n center.corner = [p1, p2, p3, p4];\n \n // 車體邊框\n center.border = [\n new Line(p1, p2, 2),\n new Line(p2, p3, 2),\n new Line(p3, p4, 2),\n new Line(p4, p1, 2),\n ];\n \n // 感測器的線段終點\n center.censorPoints = [];\n // 感測器的線段\n center.sensors = []\n // sensors 角度\n center.offset = [];\n // 感測器讀取的資料\n center.sensorsData = [];\n \n\n center.updateLines = function () {\n for (var i=0; i\u003c4; i++) {\n this.border[i].update();\n }\n for (var i=0; i\u003cthis.offset.length; i++) {\n this.sensors[i].update();\n }\n }\n \n center.update = function () {\n var self = this;\n this.border.forEach((line) =\u003e {\n if (self.status == 'broken') line.color = 'gray';\n else line.color = 'black';\n });\n \n // 更新車體的四個點座標\n var offset = [30, 150, -150, -30];\n for (var i=0; i\u003c4; i++) {\n this.direction += offset[i];\n this.stepForward(width);\n this.corner[i].x = this.x;\n this.corner[i].y = this.y;\n this.stepForward(-width);\n this.direction -= offset[i];\n }\n \n // 更新感測器的線\n var offset = [-45, -22.5, 0, 22.5, 45];\n var offset = [-60, 0, 60];\n for (var i=0; i\u003cthis.offset.length; i++) {\n center.direction += this.offset[i];\n center.stepForward(sensorLength);\n center.censorPoints[i].x = center.x;\n center.censorPoints[i].y = center.y;\n center.stepForward(-sensorLength);\n center.direction -= this.offset[i];\n }\n \n this.updateLines();\n };\n \n center.turn = function (direction) {\n if (isNaN(direction) || this.status == 'broken') return;\n if (direction \u003e this.speed) direction = this.speed;\n if (direction \u003c -this.speed) direction = -this.speed;\n this.direction += direction;\n }\n \n center.speedUp = function (speed) {\n if (isNaN(speed) || this.status == 'broken') return;\n this.speed += speed;\n if (this.speed \u003c 0) this.speed = 0;\n }\n \n center.reset = function (x, y, direction) {\n this.x = x;\n this.y = y;\n this.direction = direction;\n this.update();\n this.status = 'running';\n }\n \n center.addSensor = function (direction) {\n let point = new Point();\n let line = new Line(this, point, 0, '#00000000');\n this.censorPoints.push(point);\n this.sensors.push(line);\n this.offset.push(direction);\n }\n \n forever(function () {\n if (center.status == 'running') {\n center.stepForward(center.speed);\n }\n center.update();\n });\n \n center.update(); // 初始化更新\n \n cars.push(center);\n return center;\n}\n\n\nforever(function(){\n \n // 檢查車子是否碰到賽道邊界,碰到則將車子狀態改成 broken\n cars.forEach(function (car) {\n for (var x=0; x\u003ccar.border.length; x++) {\n for (var y=0; y\u003cwalls.length; y++) {\n if (car.border[x].touched(walls[y])) {\n car.status = 'broken';\n return;\n }\n }\n }\n });\n \n // 更新車子感測器的數值\n cars.forEach(function (car) {\n if (car.status == 'broken') return;\n for (var x=0; x\u003ccar.sensors.length; x++) {\n \n var shortest = Infinity;\n var target = {};\n \n for (var y=0; y\u003cwalls.length; y++) {\n let pos = car.sensors[x].touched(walls[y]);\n if (pos) {\n let length = Math.sqrt((pos.x - car.x)**2 + (pos.y - car.y)**2);\n if (length \u003c shortest) {\n shortest = Math.round(length);\n target = pos;\n }\n }\n }\n \n car.sensorsData[x] = shortest;\n pen.color = '#aaa';\n pen.size = 1;\n pen.drawLine(car.x, car.y, target.x, target.y);\n pen.fillColor = 'red';\n pen.drawCircle(target.x, target.y, 3);\n }\n });\n});\n\n// 初始化賽道牆壁\nfunction initalMaps (map) {\n walls.forEach(function (line) { line.destroy() });\n walls = [];\n map.forEach(function (points) {\n for (var i=1; i\u003cpoints.length; i++) {\n let p1 = new Point(points[i - 1].x, points[i - 1].y);\n let p2 = new Point(points[i].x, points[i].y);\n let l =new Line(p1, p2, 3);\n walls.push(l)\n }\n });\n}\n\nlet maps = [[{\"x\":4,\"y\":92},{\"x\":6,\"y\":67},{\"x\":14,\"y\":46},{\"x\":31,\"y\":28},{\"x\":52,\"y\":14},{\"x\":79,\"y\":9},{\"x\":542,\"y\":8},{\"x\":571,\"y\":11},{\"x\":594,\"y\":21},{\"x\":611,\"y\":38},{\"x\":623,\"y\":63},{\"x\":629,\"y\":90},{\"x\":631,\"y\":394},{\"x\":623,\"y\":419},{\"x\":611,\"y\":438},{\"x\":594,\"y\":454},{\"x\":567,\"y\":464},{\"x\":536,\"y\":467},{\"x\":120,\"y\":469},{\"x\":90,\"y\":467},{\"x\":62,\"y\":461},{\"x\":38,\"y\":446},{\"x\":22,\"y\":427},{\"x\":12,\"y\":399},{\"x\":9,\"y\":364},{\"x\":5,\"y\":93}],[{\"x\":103,\"y\":143},{\"x\":104,\"y\":121},{\"x\":116,\"y\":104},{\"x\":135,\"y\":92},{\"x\":161,\"y\":84},{\"x\":481,\"y\":84},{\"x\":508,\"y\":90},{\"x\":525,\"y\":107},{\"x\":533,\"y\":130},{\"x\":533,\"y\":169},{\"x\":532,\"y\":340},{\"x\":527,\"y\":360},{\"x\":514,\"y\":372},{\"x\":496,\"y\":381},{\"x\":471,\"y\":384},{\"x\":166,\"y\":384},{\"x\":146,\"y\":381},{\"x\":126,\"y\":371},{\"x\":112,\"y\":351},{\"x\":106,\"y\":325},{\"x\":103,\"y\":144}]]\ninitalMaps(maps);\n","description":null,"note":null,"status":"public","like_student_ids":[],"is_featured":false,"views":56,"hashid":"4y3spk3g","is_content_changed":false,"review_status":"unsubmitted","submitted_at":null,"reviewed_at":null,"advise":null,"is_deleted":false}
[{"id":1308442,"file_name":"dot.jpg","project_id":75496,"asset_id":113889,"created_at":"2019-06-29T09:10:25.293+08:00","updated_at":"2019-06-29T09:10:25.293+08:00"}]
橘蘋學習平台
橘蘋學習平台
我的作品
檢視專案頁
匯出
複製
匯入
刪除
下載 Android APP (APK)
截圖
1:1:1
1:1
full
幫助
用手機掃描下方 QRCode 進行安裝
或您也可以
下載 APK
到這台電腦
用手機掃描下方 QRCode 進行安裝
或您也可以
下載 APK
到這台電腦