利用JS實現(xiàn)AI自動玩貪吃蛇_第1頁
利用JS實現(xiàn)AI自動玩貪吃蛇_第2頁
利用JS實現(xiàn)AI自動玩貪吃蛇_第3頁
利用JS實現(xiàn)AI自動玩貪吃蛇_第4頁
利用JS實現(xiàn)AI自動玩貪吃蛇_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第利用JS實現(xiàn)AI自動玩貪吃蛇目錄演示技術(shù)棧源碼樣式設置構(gòu)建食物對象構(gòu)建貪吃蛇對象構(gòu)建自動貪吃

演示

自動貪吃蛇

技術(shù)棧

bottom屬性規(guī)定元素的底部邊緣。該屬性定義了定位元素下外邊距邊界與其包含塊下邊界之間的偏移。

注釋:如果position屬性的值為static,那么設置bottom屬性不會產(chǎn)生任何效果。

對于static元素,為auto;對于長度值,則為相應的絕對長度;對于百分比數(shù)值,為指定值;否則為auto。

對于相對定義元素,如果bottom和top都是auto,其計算值則都是0;如果其中之一為auto,則取另一個值的相反數(shù);如果二者都不是auto,bottom將取top值的相反數(shù)。

默認值:auto繼承性:no版本:CSS2JavaScript語法:object.style.bottom=50px

user-select屬性規(guī)定是否能選取元素的文本。

在web瀏覽器中,如果您在文本上雙擊,文本會被選取或高亮顯示。此屬性用于阻止這種行為。

user-select:auto|none|text|all;

auto默認。如果瀏覽器允許,則可以選擇文本。none防止文本選取。text文本可被用戶選取。all單擊選取文本,而不是雙擊。

源碼

樣式設置

canvas{

position:absolute;

width:100vh;

height:100vh;

margin:auto;

top:0;

bottom:0;

left:0;

right:0;

user-select:none;

background:#000;

cursor:pointer;

構(gòu)建食物對象

varfood={

x:0,

y:0,

//addrandomfood

add:functionadd(){

varemptyNodes=[];

for(varx=0;xmap.width;++x){

for(vary=0;ymap.height;++y){

if(!map.collision(x,y))emptyNodes.push({

x:x,

y:y

if(emptyNodes.length){

varp=emptyNodes[Math.floor(Math.random()*emptyNodes.length)];

this.x=p.x;

this.y=p.y;

構(gòu)建貪吃蛇對象

varsnake={

body:[],

head:{

x:0,

y:0

removeTail:functionremoveTail(){

varp=this.body.shift();

map.setSnake(p.x,p.y,0);

addHead:functionaddHead(x,y){

this.head.x=x;

this.head.y=y;

this.body.push({

x:x,

y:y

map.setSnake(x,y,1);

move:functionmove(dir){

varnext=map.getNext(this.head.x,this.head.y,dir);

this.addHead(next.x,next.y);

if(next.x===food.xnext.y===food.y){

food.add();

}elsethis.removeTail();

//snakeIA

nextDirection:functionnextDirection(){

varx=this.head.x;

vary=this.head.y;

varpathNumber=map.tour(x,y);

vardistanceToFood=map.distance(pathNumber,map.tour(food.x,food.y));

vardistanceToTail=map.distance(pathNumber,map.tour(snake.body[0].x,snake.body[0].y));

varcuttingAmountAvailable=distanceToTail-4;

varnumEmptySquaresOnBoard=map.size-snake.body.length-1;

if(distanceToFooddistanceToTail)cuttingAmountAvailable-=1;

varcuttingAmountDesired=distanceToFood;

if(cuttingAmountDesiredcuttingAmountAvailable)cuttingAmountAvailable=cuttingAmountDesired;

if(cuttingAmountAvailable0)cuttingAmountAvailable=0;

varcanGoRight=!map.collision(x+1,y);

varcanGoLeft=!map.collision(x-1,y);

varcanGoDown=!map.collision(x,y+1);

varcanGoUp=!map.collision(x,y-1);

varbestDir=-1;

varbestDist=-1;

vardist=0;

if(canGoRight){

dist=map.distance(pathNumber,map.tour(x+1,y));

if(dist=cuttingAmountAvailabledistbestDist){

bestDir=map.Right;

bestDist=dist;

if(canGoLeft){

dist=map.distance(pathNumber,map.tour(x-1,y));

if(dist=cuttingAmountAvailabledistbestDist){

bestDir=map.Left;

bestDist=dist;

if(canGoDown){

dist=map.distance(pathNumber,map.tour(x,y+1));

if(dist=cuttingAmountAvailabledistbestDist){

bestDir=map.Down;

bestDist=dist;

if(canGoUp){

dist=map.distance(pathNumber,map.tour(x,y-1));

if(dist=cuttingAmountAvailabledistbestDist){

bestDir=map.Up;

bestDist=dist;

if(bestDist=0)returnbestDir;

if(canGoUp)returnmap.Up;

if(canGoLeft)returnmap.Left;

if(canGoDown)returnmap.Down;

if(canGoRight)returnmap.Right;

returnmap.Right;

構(gòu)建自動貪吃

varmap={

//initmap

init:functioninit(width,height){

var_this=this;

this.width=width;

this.height=height;

this.size=width*height;

this.scale=Math.min(canvasWidth,canvasHeight)/Math.max(this.width,this.height);

//HamiltonianCycle

//flags

var_array2D=this.array2D(width,height,true);

var_array2D2=_slicedToArray(_array2D,2);

this.tour=_array2D2[0];

this.setTour=_array2D2[1];

var_array2D3=this.array2D(width/2,height/2);

var_array2D4=_slicedToArray(_array2D3,2);

this.isVisited=_array2D4[0];

this.setVisited=_array2D4[1];

var_array2D5=this.array2D(width/2,height/2);

var_array2D6=_slicedToArray(_array2D5,2);

this.canGoRight=_array2D6[0];

this.setGoRight=_array2D6[1];

var_array2D7=this.array2D(width/2,height/2);

var_array2D8=_slicedToArray(_array2D7,2);

this.canGoDown=_array2D8[0];

this.setGoDown=_array2D8[1];

var_array2D9=this.array2D(width,height);

var_array2D10=_slicedToArray(_array2D9,2);

this.isSnake=_array2D10[0];

this.setSnake=_array2D10[1];

this.canGoLeft=function(x,y){

if(x===0)returnfalse;

return_this.canGoRight(x-1,y);

this.canGoUp=function(x,y){

if(y===0)returnfalse;

return_this.canGoDown(x,y-1);

//directions

Left:1,

Up:2,

Right:3,

Down:4,

//flat2Darray

array2D:functionarray2D(width,height,protect){

vardata=newUint16Array(width*height);

return[function(x,y){

returndata[x+width*y];

},protectfunction(x,y,value){

vari=x+width*y;

if(!data[i])data[i]=value;

}:function(x,y,value){

data[x+width*y]=value;

//testsnakecollision

collision:functioncollision(x,y){

if(x0||x=this.width)returntrue;

if(y0||y=this.height)returntrue;

returnthis.isSnake(x,y)!==0;

//pathdistance

distance:functiondistance(a,b){

if(ab)returnb-a-1;elsereturnb-a-1+this.size;

//HamiltonianCycle

generate_r:functiongenerate_r(fromx,fromy,x,y){

if(x0||y0||x=this.width/2||y=this.height/2)return;

if(this.isVisited(x,y))return;

this.setVisited(x,y,1);

if(fromx!==-1){

if(fromxx)this.setGoRight(fromx,fromy,1);elseif(fromxx)this.setGoRight(x,y,1);elseif(fromyy)this.setGoDown(fromx,fromy,1);elseif(fromyy)this.setGoDown(x,y,1);

for(vari=0;ii++){

varr=Math.floor(Math.random()*4);

switch(r){

case0:

this.generate_r(x,y,x-1,y);

break;

case1:

this.generate_r(x,y,x+1,y);

break;

case2:

this.generate_r(x,y,x,y-1);

break;

case3:

this.generate_r(x,y,x,y+1);

break;

this.generate_r(x,y,x-1,y);

this.generate_r(x,y,x+1,y);

this.generate_r(x,y,x,y+1);

this.generate_r(x,y,x,y-1);

//findnextdirectionincycle

findNextDir:functionfindNextDir(x,y,dir){

if(dir===this.Right){

if(this.canGoUp(x,y))returnthis.Up;

if(this.canGoRight(x,y))returnthis.Right;

if(this.canGoDown(x,y))returnthis.Down;

returnthis.Left;

}elseif(dir===this.Down){

if(this.canGoRight(x,y))returnthis.Right;

if(this.canGoDown(x,y))returnthis.Down;

if(this.canGoLeft(x,y))returnthis.Left;

returnthis.Up;

}elseif(dir===this.Left){

if(this.canGoDown(x,y))returnthis.Down;

if(this.canGoLeft(x,y))returnthis.Left;

if(this.canGoUp(x,y))returnthis.Up;

returnthis.Right;

}elseif(dir===this.Up){

if(this.canGoLeft(x,y))returnthis.Left;

if(this.canGoUp(x,y))returnthis.Up;

if(this.canGoRight(x,y))returnthis.Right;

returnthis.Down;

return-1;//Unreachable

//generateHamiltonianCycle

generateTourNumber:functiongenerateTourNumber(){

varx=0;

vary=0;

vardir=this.canGoDown(x,y)this.Up:this.Left;

varnumber=0;

do{

varnextDir=this.findNextDir(x,y,dir);

switch(dir){

casethis.Right:

this.setTour(x*2,y*2,number++);

if(nextDir===dir||nextDir===this.Down||nextDir===this.Left)this.setTour(x*2+1,y*2,number++);

if(nextDir===this.Down||nextDir===this.Left)this.setTour(x*2+1,y*2+1,number++);

if(nextDir===this.Left)this.setTour(x*2,y*2+1,number++);

break;

casethis.Down:

this.setTour(x*2+1,y*2,number++);

if(nextDir===dir||nextDir===this.Left||nextDir===this.Up)this.setTour(x*2+1,y*2+1,number++);

if(nextDir===this.Left||nextDir===this.Up)this.setTour(x*2,y*2+1,number++);

if(nextDir===this.Up)this.setTour(x*2,y*2,number++);

break;

casethis.Left:

this.setTour(x*2+1,y*2+1,number++);

if(nextDir===dir||nextDir===this.Up||nextDir===this.Right)this.setTour(x*2,y*2+1,number++);

if(nextDir===this.Up||nextDir===this.Right)this.setTour(x*2,y*2,number++);

if(nextDir===this.Right)this.setTour(x*2+1,y*2,number++);

break;

casethis.Up:

this.setTour(x*2,y*2+1,number++);

if(nextDir===dir||nextDir===this.Right||nextDir===this.Down)this.setTour(x*2,y*2,number++);

if(nextDir===this.Right||nextDir===this.Down)this.setTour(x*2+1,y*2,number++);

if(nextDir===this.Down)this.setTour(x*2+1,y*2+1,number++);

break;

dir=nextDir;

switch(nextDir){

casethis.Right:

++x;

break;

casethis.Left:

--x;

break;

casethis.Down:

++y;

break;

casethis.Up:

--y;

break;

}while(number!==this.size);

//getnextnode

getNext:functiongetNext(x,y,dir){

switch(dir){

casethis.Left:

if(x)return{

x:x-1,

y:y

break;

casethis.Up:

if(y)return{

x:x,

y:y-1

break;

casethis.Right:

return{

x:x+1,

y:y

break;

casethis.Down:

return{

x:x,

y:y+1

break;

return{

x

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論