贪吃蛇面向对象c语言,面向对象案例——贪吃蛇游戏(示例代码)

本文介绍了一个使用JavaScript实现的经典贪吃蛇游戏案例。通过面向对象的设计思路,文章详细讲解了如何构建食物对象、蛇对象及游戏对象,并实现了游戏的基本逻辑,如蛇的移动和吃食物等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近项目上线,近一个星期没更博了,今天来写一个经典的游戏案例——贪吃蛇。在这个简单的案例里可以体会javaScript 面向对象开发相关模式,学习使用面向对象的方式分析问题。

1.功能实现

1.1 搭建页面:放一个容器盛放游戏场景 div#map,设置样式

1

3 background-color:#000;

4 width:1500px;

5 height:700px;

6 position:relative;

7 left:0;

8 top:0;

9 }

10

1.2 分析对象:食物对象、蛇对象、游戏对象

1.3 创建食物对象Food

⑴ 属性:位置(x,y)、大小(width、height)、颜色(color)

1 //创建Food的构造函数,并设置属性

2 functionFood(width,height,bgColor) {3 //食物的宽度和高度(像素)

4 this.width=width||10;5 this.height=height||10;6 //食物的颜色

7 this.bgColor=bgColor||"white";8 }

⑵ 方法:render() 随机创建一个食物对象,并输出到map上

1 //通过原型设置render方法,实现随机产生食物对象,并渲染到map上

2 Food.prototype.render=function(map) {3 remove(map);4 //随机食物的位置,map.宽度/food.宽度,总共有多少分food的宽度,随机一下。然后再乘以food的宽度

5 this.x=Math.floor(Math.random()*(map.offsetWidth/this.width))*this.width;

6 this.y=Math.floor(Math.random()*(map.offsetHeight/this.height))*this.height;

7 //动态创建食物对应的div

8 var newDiv=document.createElement("div");9 newDiv.style.position="absolute";10 newDiv.style.left=this.x+"px";11 newDiv.style.top=this.y+"px";12 newDiv.style.backgroundColor=this.bgColor;13 newDiv.style.width=this.width+"px";14 newDiv.style.height=this.height+"px";15 map.appendChild(newDiv);16 li.push(newDiv);17 }

1.4 创建蛇对象Snake

⑴ 属性:大小(width、height)、颜色(color)、方向(direction)、身体数组对象(body)

1 //Snake构造函数

2 functionSnake(width,height,bgColor,direction) {3 //设置每一个蛇节的宽度

4 this.width=width||10;5 this.height=height||10;6 this.bgColor=bgColor||"white";7 //蛇的运动方向

8 this.direction=direction||"right";9 //蛇的每一部分, 第一部分是蛇头

10 this.body=[11 {x:3,y:1},12 {x:2,y:1},13 {x:1,y:1}14 ];15 }

⑵ 方法:render() 把蛇渲染到map上

1 //render方法,原理与渲染食物相同

2 Snake.prototype.render=function(map) {3 remove(map);4 for (var i = 0; i < this.body.length; i++) {5 var newDiv=document.createElement("div");6 newDiv.style.position="absolute";7 newDiv.style.left=this.body[i].x*this.width+"px";8 newDiv.style.top=this.body[i].y*this.height+"px";9 newDiv.style.width=this.width+"px";10 newDiv.style.height=this.height+"px";11 newDiv.style.backgroundColor=this.bgColor;12 map.appendChild(newDiv);13 list.push(newDiv);14 }15 }

1.5 创建游戏对象Game(用来管理游戏中的所有对象和开始游戏)

⑴ 属性:food、snake、map

1 //Game构造函数

2 functionGame(map) {3 this.map=map;4 this.snake=newSnake();5 this.food=newFood();6 that=this;7 }

⑵ 方法:start() 开始游戏(绘制所有游戏对象)

1 //开始游戏,渲染食物对象和蛇对象

2 Game.prototype.startGame=function() {3 this.food.render(this.map);4 this.snake.render(this.map);5 autoMove();6 keyBind();7 }

//在自调用函数中暴露Game对象

window.Game=Game;

2.游戏逻辑

2.1 蛇的move方法

⑴ 在蛇对象(snake.js)中,在Snake的原型上新增move方法

⑵ 让蛇移动起来,把蛇身体的每一部分往前移动一下

⑶ 蛇头部分根据不同的方向决定 往哪里移动

1 Snake.prototype.move=function(food,map) {2 //让蛇身体的每一部分往前移动一下

3 for (var i = this.body.length-1; i >0; i--){4 this.body[i].x=this.body[i-1].x;5 this.body[i].y=this.body[i-1].y;6 }7 //根据移动的方向,决定蛇头如何处理

8 switch (this.direction) {9 case "left":10 this.body[0].x--;11 break;12 case "right":13 this.body[0].x++;14 break;15 case "up":16 this.body[0].y--;17 break;18 case "down":19 this.body[0].y++;20 break;21 default:22 break;23 }24 }

//在game中测试

this.snake.move(this.food, this.map);this.snake.render(this.map);

2.2 让蛇自己动起来

⑴ 在game.js中 添加autoMove的私有方法,开启定时器调用蛇的move和render方法,让蛇动起来(私有方法即不能被外部访问的方法,使用自调用函数包裹)

1 functionautoMove() {2 var timeId=setInterval(function() {3 this.snake.move(this.food,this.map);4 this.snake.render(this.map);5 //判断蛇是否撞墙

6 var snakeHeadX=this.snake.body[0].x*this.snake.width;7 var snakeHeadY=this.snake.body[0].y*this.snake.width;8 if(snakeHeadX<0 || snakeHeadY<0 || snakeHeadX>=this.map.offsetWidth || snakeHeadY>=this.map.offsetHeight){9 clearInterval(timeId);10 alert("Game over!");11 }12 }.bind(that),50);13 }

⑵ 在snake中添加删除蛇的私有方法,在render中调用

1 functionremove(map) {2 for (var i = 0; i < list.length; i++) {3 map.removeChild(list[i]);4 }5 list.length=0;6 }

⑶ 在game中通过键盘控制蛇的移动方向

1 functionkeyBind() {2 window.onkeydown=function(e) {3 e=e||window.event;4 e.keyCode= e.keyCode|| e.charCode||e.which;5 //console.log(e.keyCode);

6 switch(e.keyCode) {7 case 37:8 if(this.snake.direction!="right"){9 this.snake.direction="left";10 }11 break;12 case 38:13 if (this.snake.direction != "down") {14 this.snake.direction = "up";15 }16 break;17 case 39:18 if (this.snake.direction != "left") {19 this.snake.direction = "right";20 }21 break;22 case 40:23 if (this.snake.direction != "up") {24 this.snake.direction = "down";25 }26 break;27 default:28 break;29 }30 }.bind(that);31 }

⑷ 在start方法中调用keyBind()

2.3 判断蛇是否吃到食物

在Snake的move方法中添加判断

1 //在移动的过程中判断蛇是否吃到食物

2 var snakeHeadX=this.body[0].x*this.width;3 var snakeHeadY=this.body[0].y*this.height;4 var snakeTile=this.body[this.body.length-1];5 //如果蛇头和食物的位置重合代表吃到食物

6 if(snakeHeadX==food.x && snakeHeadY==food.y){7 //吃到食物,往蛇节的最后加一节

8 this.body.push({9 //食物的坐标是像素,蛇的坐标是几个宽度,进行转换

10 x:snakeTile.x,11 y:snakeTile.y12 });13 //把现在的食物对象删除,并重新随机渲染一个食物对象

14 food.render(map);15 }

★ ★ 自调用函数的参数

1 (function(window, undefined) {2 var document =window.document;3 }(window, undefined))

⑴ 传入window对象:代码压缩的时候,可以把function (window) 压缩成 function (w)

⑵ 传入undefined:把undefined作为函数的参数(当前案例没有使用) ,防止undefined 被重新赋值,因为在有的老版本的浏览器中 undefined可以被重新赋值

★ ★ 关于自调用函数的问题

⑴ 如果存在多个自调用函数要用分号分割,否则语法错误

1 //下面代码会报错

2 (function() {3 }())4

5 (function() {6 }())7 //所以代码规范中会建议在自调用函数之前加上分号

8 //下面代码没有问题

9 ;(function() {10 }())11

12 ;(function() {13 }())

⑵ 当自调用函数前面有函数声明时,会把自调用函数作为参数

1 //所以建议自调用函数前,加上;

2 var a = function() {3 alert(‘11‘);4 }5

6 (function() {7 alert(‘22‘);8 }())

利用面向对象的方法,实现贪吃蛇。 1. 利用面向对象的思想实现——一个食物对象、一个蛇对象、一个游戏总控对象。 2. 在使用××.prototype= {}重写原型对象的时候,一定要加上一句constructor:该对象。不然会造成实例化出来的实例的constructor为object。 3. 在underscore中,使用_.random(a,b)即可获得a-b中的一个随机数。 4. 在求食物的随机位置的时候,用到了panel.clientHeight/this.height - 1) * this.height。 原理是使用盒子的高度/小球的高度,可以算得最多放多少个小球。因为要控制小球不能超过边界,所以总数量要减去1,数量×高度即为随机位置的最大值。 5. 在蛇对象中,用body数组存放蛇身体每一个部分对象。蛇的绘制过程就是遍历body,在面板上绘制。 6. 蛇的移动分为两部分。 ① 蛇节移动到前一个蛇节的位置。直到蛇头后一个蛇节移动到蛇头的位置。 ② 根据direction判断蛇头如何移动。 注意:在游戏绘制的过程中,界面的每一次绘制都要**删除**之前的绘制,不然会叠加到一起。 7. 在蛇的闭包中建一个局部数组,存储蛇对象,可以更加方便的删除操作。 8. 只有在原型对象中的方法和属性,外界是可以调用的。 9. 蛇的移动(动画)必然需要定时器协助。定时器的时间,即象征着刷新速度,也就是难度。 10. this所在的函数在哪一个对象中,this就指向谁。单独写一个函数的时候,如果调用之前对象的this,需要备份指针(将对象的this赋值给另一个变量)。 11. JavaScript原生的键盘按下事件(keydown) 中,事件有一个keyCode属性,其值代表按下的键。其中:37—left、38—top、39—right、40—bottom。 12. 边界控制。通过判断蛇头与最大X和Y的关系,判断是否碰到边界。 13. confirm()方法用于显示一个带有指定消息和确认及取消按钮的对话框。 14. window.location.reload(); 重新加载当前文档 15. window.close() 方法用于关闭浏览器窗口。 16. 与食物的碰撞检测:如果蛇头和食物坐标重叠,将蛇尾添加到body中。并重新绘制一个食物点,将之前的食物删掉。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值