简单的小游戏制作,代码量只有两三百行。游戏可自行扩展延申。

源码已发布至github,喜欢的点个小星星,源码入口:game-snake

游戏已发布,游戏入口:http://snake.game.yanjd.top

第一步 - 制作想法

游戏如何实现是首要想的,这里我的想法如下:

  1. 利用canvas进行绘制地图(格子装)。
  2. 利用canvas绘制蛇,就是占用地图格子。让蛇移动,即:更新蛇坐标,重新绘制。
  3. 创建四个方向按钮,控制蛇接下来的方向。
  4. 随机在地图上绘制出果子,蛇移动时“吃”到果子,增加长度和“移速”。
  5. 开始键和结束键配置,分数显示、历史记录

第二步 - 框架选型

从第一步可知,我想实现这个游戏,只需要用到canvas绘制就可以了,没有物理引擎啥的,也没有高级的UI特效。可以选个简单点的,用来方便操作canvas绘制。精挑细选后选的是EaselJS,比较轻量,用于绘制canvas,以及canvas的动态效果。

第三步 - 开发

准备

目录和文件准备:

| - index.html

| - js

| - | - main.js

| - css

| - | - stylesheet.css

index.html 导入相关的依赖,以及样式文件和脚本文件。设计是屏幕80%高度为canvas绘制区域,20%高度是操作栏以及展示分数区域.

<!DOCTYPE html>
<html lang="zh"> <head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible"
content="ie=edge">
<title>贪吃蛇</title>
<link rel="stylesheet" href="css/stylesheet.css">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
</head> <body>
<div id="app">
<div class="content-canvas">
<canvas></canvas>
</div>
<div class="control">
</div>
</div>
<script src="https://cdn.bootcss.com/EaselJS/1.0.2/easeljs.min.js"></script>
<!-- 载入jquery 方便dom操作 -->
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<!-- sweetalert 美化alert用的 -->
<script src="https://cdn.bootcss.com/sweetalert/2.1.2/sweetalert.min.js"></script>
<script src="js/main.js"></script>
</body> </html>

stylesheet.css

* {
padding: 0;
margin: 0;
}
body {
position: fixed;
width: 100%;
height: 100%;
}
#app {
max-width: 768px;
margin-left: auto;
margin-right: auto;
}
/* canvas绘制区域 */
.content-canvas {
width: 100%;
max-width: 768px;
height: 80%;
position: fixed;
overflow: hidden;
}
.content-canvas canvas {
position: absolute;
width: 100%;
height: 100%;
}
/* 操作区域 */
.control {
position: fixed;
width: 100%;
max-width: 768px;
height: 20%;
bottom: 0;
background-color: #aeff5d;
}

main.js

$(function() {
// 主代码编写区域
})

1.绘制格子

注意的点(遇到的问题以及解决方案):

  1. canvas绘制的路线是无宽度的,但线条是有宽度的。比如:从(0, 0)到(0, 100)绘制一条宽度为10px的线,则线条一半是在区域外看不见的。处理方案是起点偏移,比如:从(0, 0)到(0, 100)绘制一条宽度为10px的线,改为从(5,0)到(5,100),偏移量为线条宽度的一半。
  2. 用样式定义canvas的宽高坐标会被拉伸,处理方案是给canvas元素设置宽高属性,值为它当前的实际宽高。

代码

main.js

$(function () {
var LINE_WIDTH = 1 // 线条宽度
var LINE_MAX_NUM = 32 // 一行格子数量
var canvasHeight = $('canvas').height() // 获取canvas的高度
var canvasWidth = $('canvas').width() // 获取canvas的宽度
var gridWidth = (canvasWidth - LINE_WIDTH) / LINE_MAX_NUM // 格子宽度,按一行32个格子计算
var num = { w: LINE_MAX_NUM, h: Math.floor((canvasHeight - LINE_WIDTH) / gridWidth) } // 计算横向和纵向多少个格子,即:横坐标的最大值和纵坐标的最大值 /**
* 绘制格子地图
* @param graphics
*/
function drawGrid(graphics) {
var wNum = num.w
var hNum = num.h
graphics.setStrokeStyle(LINE_WIDTH).beginStroke('#ffac52')
// 画横向的线条
for (var i = 0; i <= hNum; i++) {
if (i === hNum || i === 0) graphics.setStrokeStyle(LINE_WIDTH)
if (i === 1) graphics.setStrokeStyle(0.1)
graphics.moveTo(LINE_WIDTH / 2, i * gridWidth + LINE_WIDTH / 2)
.lineTo(gridWidth * wNum + LINE_WIDTH / 2, i * gridWidth + LINE_WIDTH / 2)
}
graphics.setStrokeStyle(LINE_WIDTH)
// 画纵向的线条
for (i = 0; i <= wNum; i++) {
if (i === wNum || i === 0) graphics.setStrokeStyle(LINE_WIDTH)
if (i === 1) graphics.setStrokeStyle(.1)
graphics.moveTo(i * gridWidth + LINE_WIDTH / 2, LINE_WIDTH / 2)
.lineTo(i * gridWidth + LINE_WIDTH / 2, gridWidth * hNum + LINE_WIDTH / 2)
}
} function init() {
$('canvas').attr('width', canvasWidth) // 给canvas设置宽高属性赋值上当前canvas的宽度和高度(单用样式配置宽高会被拉伸)
$('canvas').attr('height', canvasHeight)
var stage = new createjs.Stage($('canvas')[0])
var grid = new createjs.Shape()
drawGrid(grid.graphics)
stage.addChild(grid)
stage.update()
} init()
})

效果图

浏览器打开index.html,可以看到效果:

2.绘制蛇

蛇可以想象成一串坐标点(数组),“移动时”在数组头部添加新的坐标,去除尾部的坐标。类似队列,先进先出。

代码

main.js

$(function () {
var LINE_WIDTH = 1 // 线条宽度
var LINE_MAX_NUM = 32 // 一行格子数量
var SNAKE_START_POINT = [[0, 3], [1, 3], [2, 3], [3, 3]] // 初始蛇坐标
var DIR_ENUM = { UP: 1, DOWN: -1, LEFT: 2, RIGHT: -2 } // 移动的四个方向枚举值,两个对立方向相加等于0
var GAME_STATE_ENUM = { END: 1, READY: 2 } // 游戏状态枚举
var canvasHeight = $('canvas').height() // 获取canvas的高度
var canvasWidth = $('canvas').width() // 获取canvas的宽度
var gridWidth = (canvasWidth - LINE_WIDTH) / LINE_MAX_NUM // 格子宽度,按一行32个格子计算
var num = { w: LINE_MAX_NUM, h: Math.floor((canvasHeight - LINE_WIDTH) / gridWidth) } // 计算横向和纵向多少个格子,即:横坐标的最大值和纵坐标的最大值
var directionNow = null // 当前移动移动方向
var directionNext = null // 下一步移动方向
var gameState = null // 游戏状态 /**
* 绘制格子地图
* @param graphics
*/
function drawGrid(graphics) {
var wNum = num.w
var hNum = num.h
graphics.setStrokeStyle(LINE_WIDTH).beginStroke('#ffac52')
// 画横向的线条
for (var i = 0; i <= hNum; i++) {
if (i === hNum || i === 0) graphics.setStrokeStyle(LINE_WIDTH)
if (i === 1) graphics.setStrokeStyle(0.1)
graphics.moveTo(LINE_WIDTH / 2, i * gridWidth + LINE_WIDTH / 2)
.lineTo(gridWidth * wNum + LINE_WIDTH / 2, i * gridWidth + LINE_WIDTH / 2)
}
graphics.setStrokeStyle(LINE_WIDTH)
// 画纵向的线条
for (i = 0; i <= wNum; i++) {
if (i === wNum || i === 0) graphics.setStrokeStyle(LINE_WIDTH)
if (i === 1) graphics.setStrokeStyle(.1)
graphics.moveTo(i * gridWidth + LINE_WIDTH / 2, LINE_WIDTH / 2)
.lineTo(i * gridWidth + LINE_WIDTH / 2, gridWidth * hNum + LINE_WIDTH / 2)
}
} /**
* 坐标类
*/
function Point(x, y) {
this.x = x
this.y = y
} /**
* 根据移动的方向,获取当前坐标的下一个坐标
* @param direction 移动的方向
*/
Point.prototype.nextPoint = function nextPoint(direction) {
debugger
var point = new Point(this.x, this.y)
switch (direction) {
case DIR_ENUM.UP:
point.y -= 1
break
case DIR_ENUM.DOWN:
point.y += 1
break
case DIR_ENUM.LEFT:
point.x -= 1
break
case DIR_ENUM.RIGHT:
point.x += 1
break
}
return point
} /**
* 初始化蛇的坐标
* @returns {[Point,Point,Point,Point,Point ...]}
* @private
*/
function initSnake() {
return SNAKE_START_POINT.map(function (item) {
return new Point(item[0], item[1])
})
} /**
* 绘制蛇
* @param graphics
* @param snakes // 蛇坐标
*/
function drawSnake(graphics, snakes) {
graphics.clear()
graphics.beginFill("#a088ff")
var len = snakes.length
for (var i = 0; i < len; i++) {
if (i === len - 1) graphics.beginFill("#ff6ff9")
graphics.drawRect(
snakes[i].x * gridWidth + LINE_WIDTH / 2,
snakes[i].y * gridWidth + LINE_WIDTH / 2,
gridWidth, gridWidth)
}
} /**
* 改变蛇身坐标
* @param snakes 蛇坐标集
* @param direction 方向
*/
function updateSnake(snakes, direction) {
var oldHead = snakes[snakes.length - 1]
var newHead = oldHead.nextPoint(direction)
// 超出边界 游戏结束
if (newHead.x < 0 || newHead.x >= num.w || newHead.y < 0 || newHead.y >= num.h) {
gameState = GAME_STATE_ENUM.END
} else if (snakes.some(function (p) { // ‘吃’到自己 游戏结束
return newHead.x === p.x && newHead.y === p.y
})) {
gameState = GAME_STATE_ENUM.END
} else {
snakes.push(newHead)
snakes.shift()
}
} /**
* 引擎
* @param graphics
* @param snakes
*/
function move(graphics, snakes, stage) {
clearTimeout(window._engine) // 重启时关停之前的引擎
run()
function run() {
directionNow = directionNext
updateSnake(snakes, directionNow) // 更新蛇坐标
if (gameState === GAME_STATE_ENUM.END) {
end()
} else {
drawSnake(graphics, snakes)
stage.update()
window._engine = setTimeout(run, 500)
}
}
} /**
* 游戏结束回调
*/
function end() {
console.log('游戏结束')
} function init() {
$('canvas').attr('width', canvasWidth) // 给canvas设置宽高属性赋值上当前canvas的宽度和高度(单用样式配置宽高会被拉伸)
$('canvas').attr('height', canvasHeight)
directionNow = directionNext = DIR_ENUM.DOWN // 初始化蛇的移动方向
var snakes = initSnake()
var stage = new createjs.Stage($('canvas')[0])
var grid = new createjs.Shape()
var snake = new createjs.Shape()
drawGrid(grid.graphics) // 绘制格子
drawSnake(snake.graphics, snakes)
stage.addChild(grid)
stage.addChild(snake)
stage.update()
move(snake.graphics, snakes, stage)
} init()
})

效果图

效果图(gif):

3.移动蛇

制作4个按钮,控制移动方向

代码

index.html

...
<div class="control">
<div class="row">
<div class="btn">
<button id="UpBtn">上</button>
</div>
</div>
<div class="row clearfix">
<div class="btn half-width left">
<button id="LeftBtn">左</button>
</div>
<div class="btn half-width right">
<button id="RightBtn">右</button>
</div>
</div>
<div class="row">
<div class="btn">
<button id="DownBtn">下</button>
</div>
</div>
</div>
</div>
...

stylesheet.css

...
.control .row {
position: relative;
height: 33%;
text-align: center;
} .control .btn {
box-sizing: border-box;
height: 100%;
padding: 4px;
} .control button {
display: inline-block;
height: 100%;
background-color: white;
border: none;
padding: 3px 20px;
border-radius: 3px;
} .half-width {
width: 50%;
} .btn.left {
padding-right: 20px;
float: left;
text-align: right;
} .btn.right {
padding-left: 20px;
float: right;
text-align: left;
} .clearfix:after {
content: '';
display: block;
clear: both;
}

mian.js

...
/**
* 改变蛇行进方向
* @param dir
*/
function changeDirection(dir) {
/* 逆向及同向则不改变 */
if (directionNow + dir === 0 || directionNow === dir) return
directionNext = dir
} /**
* 绑定相关元素点击事件
*/
function bindEvent() {
$('#UpBtn').click(function () { changeDirection(DIR_ENUM.UP) })
$('#LeftBtn').click(function () { changeDirection(DIR_ENUM.LEFT) })
$('#RightBtn').click(function () { changeDirection(DIR_ENUM.RIGHT) })
$('#DownBtn').click(function () { changeDirection(DIR_ENUM.DOWN) })
} function init() {
bindEvent()
...
}

效果图

效果图(gif):

4. 绘制果子

随机取两个坐标点绘制果子,判定如果“吃到”,则不删除尾巴。缩短定时器的时间间隔增加难度。

注意的点(遇到的问题以及解决方案):新增一个果子不能占用蛇的坐标,一开始考虑的是随机生成一个坐标,如果坐标已被占用,那就继续生成随机坐标。然后发现这样做有个问题就是整个界面剩余两个坐标可用时(极端情况,蛇占了整个屏幕就差两个格子了),那这样的话,不停随机取坐标,要取到这最后两个坐标要耗不少时间。后面改了方法,先统计所有坐标,然后循环蛇身坐标,一一排除不可用坐标,然后再随机抽取可用坐标的其中一个。

代码

main.js

$(function () {
var LINE_WIDTH = 1 // 线条宽度
var LINE_MAX_NUM = 32 // 一行格子数量
var SNAKE_START_POINT = [[0, 3], [1, 3], [2, 3], [3, 3]] // 初始蛇坐标
var DIR_ENUM = { UP: 1, DOWN: -1, LEFT: 2, RIGHT: -2 } // 移动的四个方向枚举值,两个对立方向相加等于0
var GAME_STATE_ENUM = { END: 1, READY: 2 } // 游戏状态枚举
var canvasHeight = $('canvas').height() // 获取canvas的高度
var canvasWidth = $('canvas').width() // 获取canvas的宽度
var gridWidth = (canvasWidth - LINE_WIDTH) / LINE_MAX_NUM // 格子宽度,按一行32个格子计算
var num = { w: LINE_MAX_NUM, h: Math.floor((canvasHeight - LINE_WIDTH) / gridWidth) } // 计算横向和纵向多少个格子,即:横坐标的最大值和纵坐标的最大值
var directionNow = null // 当前移动移动方向
var directionNext = null // 下一步移动方向
var gameState = null // 游戏状态
var scope = 0 // 分数 /**
* 绘制格子地图
* @param graphics
*/
function drawGrid(graphics) {
var wNum = num.w
var hNum = num.h
graphics.setStrokeStyle(LINE_WIDTH).beginStroke('#ffac52')
// 画横向的线条
for (var i = 0; i <= hNum; i++) {
if (i === hNum || i === 0) graphics.setStrokeStyle(LINE_WIDTH)
if (i === 1) graphics.setStrokeStyle(0.1)
graphics.moveTo(LINE_WIDTH / 2, i * gridWidth + LINE_WIDTH / 2)
.lineTo(gridWidth * wNum + LINE_WIDTH / 2, i * gridWidth + LINE_WIDTH / 2)
}
graphics.setStrokeStyle(LINE_WIDTH)
// 画纵向的线条
for (i = 0; i <= wNum; i++) {
if (i === wNum || i === 0) graphics.setStrokeStyle(LINE_WIDTH)
if (i === 1) graphics.setStrokeStyle(.1)
graphics.moveTo(i * gridWidth + LINE_WIDTH / 2, LINE_WIDTH / 2)
.lineTo(i * gridWidth + LINE_WIDTH / 2, gridWidth * hNum + LINE_WIDTH / 2)
}
} /**
* 坐标类
*/
function Point(x, y) {
this.x = x
this.y = y
} /**
* 根据移动的方向,获取当前坐标的下一个坐标
* @param direction 移动的方向
*/
Point.prototype.nextPoint = function nextPoint(direction) {
var point = new Point(this.x, this.y)
switch (direction) {
case DIR_ENUM.UP:
point.y -= 1
break
case DIR_ENUM.DOWN:
point.y += 1
break
case DIR_ENUM.LEFT:
point.x -= 1
break
case DIR_ENUM.RIGHT:
point.x += 1
break
}
return point
} /**
* 初始化蛇的坐标
* @returns {[Point,Point,Point,Point,Point ...]}
* @private
*/
function initSnake() {
return SNAKE_START_POINT.map(function (item) {
return new Point(item[0], item[1])
})
} /**
* 绘制蛇
* @param graphics
* @param snakes // 蛇坐标
*/
function drawSnake(graphics, snakes) {
graphics.clear()
graphics.beginFill("#a088ff")
var len = snakes.length
for (var i = 0; i < len; i++) {
if (i === len - 1) graphics.beginFill("#ff6ff9")
graphics.drawRect(
snakes[i].x * gridWidth + LINE_WIDTH / 2,
snakes[i].y * gridWidth + LINE_WIDTH / 2,
gridWidth, gridWidth)
}
} /**
* 改变蛇身坐标
* @param snakes 蛇坐标集
* @param direction 方向
*/
function updateSnake(snakes, fruits, direction, fruitGraphics) {
var oldHead = snakes[snakes.length - 1]
var newHead = oldHead.nextPoint(direction)
// 超出边界 游戏结束
if (newHead.x < 0 || newHead.x >= num.w || newHead.y < 0 || newHead.y >= num.h) {
gameState = GAME_STATE_ENUM.END
} else if (snakes.some(function (p) { // ‘吃’到自己 游戏结束
return newHead.x === p.x && newHead.y === p.y
})) {
gameState = GAME_STATE_ENUM.END
} else if (fruits.some(function (p) { // ‘吃’到水果
return newHead.x === p.x && newHead.y === p.y
})) {
scope++
snakes.push(newHead)
var temp = 0
fruits.forEach(function (p, i) {
if (newHead.x === p.x && newHead.y === p.y) {
temp = i
}
})
fruits.splice(temp, 1)
var newFruit = createFruit(snakes, fruits)
if (newFruit) {
fruits.push(newFruit)
drawFruit(fruitGraphics, fruits)
}
} else {
snakes.push(newHead)
snakes.shift()
}
} /**
* 引擎
* @param graphics
* @param snakes
*/
function move(snakeGraphics, fruitGraphics, snakes, fruits, stage) {
clearTimeout(window._engine) // 重启时关停之前的引擎
run()
function run() {
directionNow = directionNext
updateSnake(snakes, fruits, directionNow, fruitGraphics) // 更新蛇坐标
if (gameState === GAME_STATE_ENUM.END) {
end()
} else {
drawSnake(snakeGraphics, snakes)
stage.update()
window._engine = setTimeout(run, 500 * Math.pow(0.9, scope))
}
}
} /**
* 游戏结束回调
*/
function end() {
console.log('游戏结束')
} /**
* 改变蛇行进方向
* @param dir
*/
function changeDirection(dir) {
/* 逆向及同向则不改变 */
if (directionNow + dir === 0 || directionNow === dir) return
directionNext = dir
} /**
* 绑定相关元素点击事件
*/
function bindEvent() {
$('#UpBtn').click(function () { changeDirection(DIR_ENUM.UP) })
$('#LeftBtn').click(function () { changeDirection(DIR_ENUM.LEFT) })
$('#RightBtn').click(function () { changeDirection(DIR_ENUM.RIGHT) })
$('#DownBtn').click(function () { changeDirection(DIR_ENUM.DOWN) })
} /**
* 创建水果坐标
* @returns Point
* @param snakes
* @param fruits
*/
function createFruit(snakes, fruits) {
var totals = {}
for (var x = 0; x < num.w; x++) {
for (var y = 0; y < num.h; y++) {
totals[x + '-' + y] = true
}
}
snakes.forEach(function (item) {
delete totals[item.x + '-' + item.y]
})
fruits.forEach(function (item) {
delete totals[item.x + '-' + item.y]
})
var keys = Object.keys(totals)
if (keys.length) {
var temp = Math.floor(keys.length * Math.random())
var key = keys[temp].split('-')
return new Point(Number(key[0]), Number(key[1]))
} else {
return null
}
} /**
* 绘制水果
* @param graphics
* @param fruits 水果坐标集
*/
function drawFruit(graphics, fruits) {
graphics.clear()
graphics.beginFill("#16ff16")
for (var i = 0; i < fruits.length; i++) {
graphics.drawRect(
fruits[i].x * gridWidth + LINE_WIDTH / 2,
fruits[i].y * gridWidth + LINE_WIDTH / 2,
gridWidth, gridWidth)
}
} function init() {
bindEvent()
$('canvas').attr('width', canvasWidth) // 给canvas设置宽高属性赋值上当前canvas的宽度和高度(单用样式配置宽高会被拉伸)
$('canvas').attr('height', canvasHeight)
directionNow = directionNext = DIR_ENUM.DOWN // 初始化蛇的移动方向
var snakes = initSnake()
var fruits = []
fruits.push(createFruit(snakes, fruits))
fruits.push(createFruit(snakes, fruits))
var stage = new createjs.Stage($('canvas')[0])
var grid = new createjs.Shape()
var snake = new createjs.Shape()
var fruit = new createjs.Shape()
drawGrid(grid.graphics) // 绘制格子
drawSnake(snake.graphics, snakes)
drawFruit(fruit.graphics, fruits)
stage.addChild(grid)
stage.addChild(snake)
stage.addChild(fruit)
stage.update()
move(snake.graphics, fruit.graphics, snakes, fruits, stage)
} init()
})

效果图

效果图(gif):

5. 分数显示、游戏结束提示、排行榜

这一部分就比较简单了,处理下数据的展示即可。这部分代码就不展示出来了。

效果图

结语

界面比较粗糙,主要是学习逻辑操作。中间出现一些小问题,但都一一的解决了。createjs这个游戏引擎还是比较简单易学的,整体只用了绘制图形的api。

手把手教学h5小游戏 - 贪吃蛇的更多相关文章

  1. 第一个windows 小游戏 贪吃蛇

    最近用dx尝试做了一个小的贪吃蛇游戏,代码放到github上面:https://github.com/nightwolf-chen/MyFreakout 说一下自己实现的过程: 首先,我把蛇这个抽象成 ...

  2. JavaScript面向对象编程小游戏---贪吃蛇

    1 面向对象编程思想在程序项目中有着非常明显的优势: 1- 1 代码可读性高.由于继承的存在,即使改变需求,那么维护也只是在局部模块 1- 2 维护非常方便并且成本较低. ​ 2 这个demo是采用了 ...

  3. 用Canvas制作小游戏——贪吃蛇

    今天呢,主要和小伙伴们分享一下一个贪吃蛇游戏从构思到实现的过程~因为我不是很喜欢直接PO代码,所以只copy代码的童鞋们请出门左转不谢. 按理说canvas与其应用是老生常谈了,可我在准备阶段却搜索不 ...

  4. 使用JavaScript实现简单的小游戏-贪吃蛇

    最近初学JavaScript,在这里分享贪吃蛇小游戏的实现过程, 希望能看到的前辈们能指出这个程序的不足之处. 大致思路 首先要解决的问题 随着蛇头的前进,尾巴也要前进. 用键盘控制蛇的运动方向. 初 ...

  5. python【控制台】小游戏--贪吃蛇

    传统贪吃蛇相信大家都玩过,也是一款很老很经典的游戏,今天我们用python控制台实现 项目有很多bug没有解决,因为本人一时兴起写的一个小游戏,所以只是实现可玩部分功能,并没有花较多的时间和精力去维护 ...

  6. Win32小游戏--贪吃蛇

    近日里学习了关于win32编程的相关知识,利用这些知识制作了一款贪吃蛇小游戏,具体细节还是分模块来叙述 前期准备:在网上找到一些贪吃蛇的游戏素材图片,以及具体的逻辑框图 在正式写功能之前,先把一系列环 ...

  7. Java_GUI小游戏--贪吃蛇

    贪吃蛇游戏:是一条蛇在封闭围墙里,围墙里随机出现一个食物,通过按键盘四个光标键控制蛇向上下左右四个方向移动,蛇头撞倒食物,则食物被吃掉,蛇身体长一节,接着又出现食物,等待蛇来吃,如果蛇在移动中撞到墙或 ...

  8. Java经典小游戏——贪吃蛇简单实现(附源码)

    一.使用知识 Jframe GUI 双向链表 线程 二.使用工具 IntelliJ IDEA jdk 1.8 三.开发过程 3.1素材准备 首先在开发之前应该准备一些素材,已备用,我主要找了一个图片以 ...

  9. 用Python实现童年小游戏贪吃蛇

    贪吃蛇作为一款经典小游戏,早在 1976 年就面世了,我最早接触它还是在家长的诺基亚手机中.

随机推荐

  1. WCF(一):初探WCF

    目录: 一.什么是WCF 二.WCF能做什么 三.WCF的模型 四.WCF的基本概念 五.WCF的快速创建 1.WCF是什么? A.WindowsCommunication Foundation(WC ...

  2. js重点

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  3. Okhttp 请求流程梳理

    最近在看 Okhttp 的源码.不得不说源码设计的很巧妙,从中能学到很多.其实网上关于 Okhttp 的文章已经很多了,自己也看了很多.但是俗话说得好,好记性不如烂笔头,当你动手的时候,你会发现你在看 ...

  4. ERP 到底是什么? 一则故事搞懂ERP

    你知道什么是ERP? ERP是什么? 你知道什么是ERP吗? (通俗易懂版) 一个故事搞懂“ERP” 一天中午,丈夫在外给家里打电话:“亲爱的老婆,晚上我想带几个同事回家吃饭可以吗?”(订货意向) 妻 ...

  5. ArcGIS Engine空间分析之拓扑分析的实现

    简单介绍: 拓扑学是一门研究几何图形位置关系的科学. GIS所关注的拓扑主要集中在拓扑关系——存在于地理实体间的拓扑关系. 拓扑关系在GIS中起着描述两个地理实体的相对空间位置的重要作用.它是GIS空 ...

  6. null与undefined的区别?

    古之立大事者,不惟有超世之才,亦必有坚忍不拔之志. ——北宋· 苏 轼<晁错论> 1.首先看一个判断题:null和undefined 是否相等     console.log(null== ...

  7. 如何做seo优化才能获取搜索引擎排名?

    现在网络上有很多网站,但是排名和流量都不理想,所以很多企业会很苦恼.所以我们经常思考如何使网站被搜索引擎喜欢,被用户喜欢,有一个良好的排名和流量? 在这个鱼龙混杂的网络中,seo优化实际上是seo网站 ...

  8. mysql设计规范一

    原文地址:http://www.jianshu.com/p/33b7b6e0a396 主键 表中每一行都应该有可以唯一标识自己的一列(或一组列). 一个顾客可以使用顾客编号列,而订单可以使用订单ID, ...

  9. [考试反思]1010csp-s模拟测试67:摸索

    嗯...所谓RP守恒? 仍然延续着好一场烂一场的规律. 虽说我也想打破这个规律,但是并不想在考烂之后打破这个规律.(因为下一场要考好???) 我也不知道我现在是什么状态,相较于前一阶段有所提升(第一鸡 ...

  10. 命运Ⅰ&命运Ⅱ

    upd:为啥下面的相关博文都是各种退役记(这TM怎么就相关了) 竟然被卡线了,16名,我这几次考试也是炸到了一定境界了... 前三次模拟总榜rk1,第一次分机房rk4,第二次分机房rk11,第三次分机 ...