实现最简单的贪吃蛇小游戏,主要需要以下三个步骤
- 绘制地图
- 实现贪吃蛇的移动
- 判断贪吃蛇当前的状态(例如:蛇头是否出界,是否吃到食物等)
其中,主要的难点是第二步,如何让蛇移动,这里大致讲解一些实现思路。首先需要把蛇和地图画出来。这里我设置地图大小为600px。然后取每一格子大小为15px。即地图总格子数为40×40。
<!DOCTYPE html>
<html>
<head>
<title>贪吃蛇</title>
<meta charset="utf-8">
<style type="text/css">
.container{
width: 600px;
height: 600px;
border: solid 1px black;
position: relative;
}
.snakeBody{
width: 13px;
height: 13px;
border: 1px solid white;
background-color: black;
position: absolute;
}
#snakeHead{
width: 13px;
height: 13px;
border: 1px solid white;
background-color: blue;
position: absolute;
}
</style>
</head>
<body>
<div align="center">
<div class="container">
<div class="snakeBody" style="left: 0;top: 0;" id="1"></div>
<div class="snakeBody" style="left: 15px;top: 0;" id="2"></div>
<div class="snakeBody" style="left: 30px;top: 0;" id="3"></div>
<div class="snakeBody" style="left: 45px;top: 0;" id="4"></div>
<div id="snakeHead" style="left: 60px;top: 0;"></div>
</div>
</div>
</body>
</html>
其次,需要编写js函数。实际上蛇的运动方式实现十分简单。操作起来只需要两步。第一步,将蛇头往运动方向前进一格。第二步,将蛇尾的div移动到蛇头移动前的位置。那么,要如何获得蛇尾的div呢?我采用的方法是使用队列存放蛇身div的id。经过排序之后,能够每一次从队列取出的id都是蛇尾的id。使用完之后将该id再次放入队列中
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
//队列用来储存snakeBody
var queue = new Array();
var front =0;
var rear =0;
//蛇头运动方向,0,1,2,3代表上下左右。初始默认向右走
var direction = 1;
$(document).ready(function () {
//将蛇身的id放入队列
queue[rear++]=4;
queue[rear++]=3;
queue[rear++]=2;
queue[rear++]=1;
setTimeout(move,300);
})
//蛇运动的函数
//每一次运动,将蛇头往运动方向移动一格。并将蛇尾的div移动到蛇头的位置
function move() {
//得到蛇头的位置
var snakeHeadtop = parseInt($('#snakeHead').css('top'));
var snakeHeadLeft = parseInt($('#snakeHead').css('left'));
//得到处在蛇尾div的id,并将该id重新加入队列
var id = queue[front++];
queue[rear++]=id;
//将蛇尾的div移动到蛇头位置
$('#'+id).css('top',snakeHeadtop+'px') ;
$('#'+id).css('left',snakeHeadLeft+'px') ;
//将蛇头往运动方向移动一格
if (direction == 0) {
$('#snakeHead').css('top',(snakeHeadtop-15)+"px");
}else if (direction == 1) {
$('#snakeHead').css('left',(snakeHeadLeft+15)+"px");
}else if (direction == 2) {
$('#snakeHead').css('top',(snakeHeadtop+15)+"px");
}else if (direction == 3) {
$('#snakeHead').css('left',(snakeHeadLeft-15)+"px");
}
setTimeout(move,300);
}
</script>
下面为完整的代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>贪吃蛇</title>
<style type="text/css">
.container{
width: 520px;
height: 520px;
border: 1px solid black;
margin: 20px 100px;
position: relative;
}
.snakeBody{
width: 11px;
height: 11px;
border: 1px solid white;
background-color: black;
position: absolute;
}
#snakeHead{
width: 11px;
height: 11px;
border: 1px solid white;
background-color: blue;
position: absolute;
}
#food{
width: 11px;
height: 11px;
border: 1px solid white;
background-color: red;
position: absolute;
}
</style>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
// 初始化地图,size为一行或一列的格数,520为container的大小,cell为每一个格子的大小
var size = 40;
var cell = 520/size;
var map = new Array();
var timeController ;
//初始化蛇
//snakeLength为蛇初始长度
//direction为蛇的运动方向0,1,2,3为上右下左
var direction;
var preDirection;
var snakeLength = 5;
//初始化队列
//队列用来储存snakeBody
var queue = new Array();
var front =0;
var rear =0;
//游戏状态
var game=false;
$(document).ready(function () {
// map 中 0为空地,1为蛇所占位置,2为食物
for (var i = 0; i<=size; i++) {
map[i] = new Array();
for(var j = 0; j<=size; j++){
map[i][j]=0;
}
}
//初始化蛇的位置
for(var i=0; i<snakeLength-1; i++){
map[0][i]=1;
var left = i * cell;
$('.container').append('<div class="snakeBody" style="left: '+left+'px;top: 0" id ='+i+'></div>')
}
map[0][i]=1;
left = i * cell;
$('.container').append('<div id="snakeHead" style="left: '+left+'px;top: 0"></div>')
for(var i=0;i<snakeLength-1;i++){
putQueue(i);
}
})
//移动函数
function move(){
//蛇头移动前的位置信息
var preSnakeHeadleft = parseInt($('#snakeHead').css("left"));
var preSnakeHeadtop = parseInt($('#snakeHead').css("top"));
//将蛇头朝着方向前进一格
if(direction == 0 ){
//如果运动方向和之前方向相反,则继续往之前方向运动
if (preDirection != 2) {
$('#snakeHead').css('top',(preSnakeHeadtop-cell)+"px");
}
else{
$('#snakeHead').css('top',(preSnakeHeadtop+cell)+"px");
direction = preDirection;
}
}else if(direction == 1 ){
if ( preDirection != 3) {
$('#snakeHead').css('left',(preSnakeHeadleft+cell)+"px");
}
else{
$('#snakeHead').css('left',(preSnakeHeadleft-cell)+"px");
direction = preDirection;
}
}else if(direction == 2 ){
if (preDirection != 0) {
$('#snakeHead').css('top',(preSnakeHeadtop+cell)+"px");
}else{
$('#snakeHead').css('top',(preSnakeHeadtop-cell)+"px");
direction = preDirection;
}
}else if(direction == 3 ){
if (preDirection != 1) {
$('#snakeHead').css('left',(preSnakeHeadleft-cell)+"px");
}else{
$('#snakeHead').css('left',(preSnakeHeadleft+cell)+"px");
direction = preDirection;
}
}
preDirection=direction;
//判断蛇头前进的格子状态
snakeHeadtop = parseInt($('#snakeHead').css('top'));
snakeHeadleft = parseInt($('#snakeHead').css('left'));
if(snakeHeadtop<0||snakeHeadtop>=520||snakeHeadleft<0||snakeHeadleft>=520){
game=false;
gameover('游戏结束:蛇撞到墙壁');
}
if (game) {
var mapStatus = map[snakeHeadtop/cell][snakeHeadleft/cell];
if (mapStatus == 0) {
//在map中将蛇头所在位置设为1
setMap('snakeHead',1);
//将队列的头出队列,然后再插入队尾
var i = outQueue();
putQueue(i);
//在map中,将蛇尾所在位置设为0
setMap(i,0);
//将蛇尾移动到移动前蛇头位置
$('#'+i).css('left',preSnakeHeadleft+"px");
$('#'+i).css('top',preSnakeHeadtop+"px");
timeController = setTimeout(move,120);
}else if (mapStatus == 1) {
//撞到了自己。游戏结束
gameover('游戏结束:蛇撞到自己');
}else if (mapStatus == 2) {
//吃到食物
//在map中将蛇头所在位置设为1
setMap('snakeHead',1);
//得到新增snakeBody的id
var id = snakeLength-1;
putQueue(id);
$('.container').append('<div class="snakeBody" style="left: '+preSnakeHeadleft+'px;top: '+preSnakeHeadtop+'px;" id ="'+id+'"></div>')
snakeLength++;
//生成食物
$('#food').remove();
createFood();
timeController = setTimeout(move,120);
}
}
}
//游戏开始
function start(){
//游戏为结束状态,才可以开始游戏
resetting();
if (!game) {
direction = 1;
preDirection = 1;
createFood();
game = true;
//初始化暂停功能
$("#pause").val(1);
//游戏状态
$('#msg').html("游戏中");
timeController = setTimeout(move,1000);
}
}
//监听按键事件
$(document).keydown(function(event){
//38上,39右,40下,37左
if(event.keyCode == 38){
direction = 0;
}
if(event.keyCode == 39){
direction = 1;
}
if(event.keyCode == 40){
direction = 2;
}
if(event.keyCode == 37){
direction = 3;
}
});
//创建食物
function createFood(){
while(true){
var x = random(0,size);
var y = random(0,size);
if (map[x][y]==0) {
$('.container').append('<div style="left: '+y*cell+'px;top: '+x*cell+'px;" id="food"></div>')
map[x][y] = 2;
break;
}
}
}
//得到随机数
function random(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
//通过id设置其在map中的值
function setMap(id,num){
var left = $('#'+id).css("left");
var top = $('#'+id).css("top");
map[parseInt(top)/cell][parseInt(left)/cell]=num;
}
//重置游戏
function resetting(){
//停掉move函数
clearTimeout(timeController);
$('.container').html("");
$('#msg').html("点击按钮开始游戏");
game = false;
front =0;
rear =0;
snakeLength = 5;
// map 中 0为空地,1为蛇所占位置,2为食物
for (var i = 0; i<=size; i++) {
map[i] = new Array();
for(var j = 0; j<=size; j++){
map[i][j]=0;
}
}
//初始化蛇的位置
for(var i=0; i<snakeLength-1; i++){
map[0][i]=1;
var left = i * cell;
$('.container').append('<div class="snakeBody" style="left: '+left+'px;top: 0" id ='+i+'></div>')
}
map[0][i]=1;
left = i * cell;
$('.container').append('<div id="snakeHead" style="left: '+left+'px;top: 0"></div>')
for(var i=0;i<snakeLength-1;i++){
putQueue(i);
}
}
function gameover(message){
message = message+"---------" +"蛇长度为"+snakeLength;
$('#msg').html(message);
}
//出队列
function outQueue(){
if (front >= size*size) {
front = 0;
}
var i = queue[front];
front++;
return i;
}
//进队列s
function putQueue(i){
if(rear >= size*size){
rear = 0;
}
queue[rear]=i;
rear++;
}
//暂停
function pause(obj){
//游戏进行才可以暂停
if(game){
var value = $(obj).val();
if(value == 1 ){
$(obj).val(0);
$('#msg').html("游戏暂停");
clearTimeout(timeController);
}else{
$(obj).val(1);
$('#msg').html("游戏中");
timeController = setTimeout(move,1000);
}
}
}
</script>
</head>
<body style="overflow: hidden;">
<div align="center">
<h1 style="margin-bottom: 10px;margin-top: 0;">贪吃蛇</h1>
<span id="msg" style="color: red;">点击按钮开始游戏</span>
<div class="container"></div>
<button onclick="start()">开始</button>
<button onclick="resetting()">重置</button>
<button onclick="pause(this)" id="pause">暂停/继续</button>
</div>
</body>
</html>