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

源码已发布至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. day03课堂练习

    简述变量的组成 变量由变量名,赋值符号,和变量值三个部分组成 简述变量名的命名规范 a.变量名必须有意义,要能反映变量值所描述的状态 b.变量名以字母.数字和下划线组成,不能用数字开头 c.不能以关键 ...

  2. PHP 输出XML字符串

    <?php echo htmlentities( $xml_string);?>

  3. Hibernate 查询方式、JPA查询方式

    hibernate 查询方式: OID 查询 对象导航查询 HQL 方式查询 QBC方式查询 原生SQL方式查询 JPA 查询方式: OID 查询 对象导航查询 JPQL 方式查询 CriteriaB ...

  4. 基于canvas的流程编辑器

    今年由于项目上需要给客户的流程管理系统进行升级,其中包含流程的可视化.于是在网上找一些可以用的轮子,考察了D3,js.GooFlow.js.G6-Editor等工具后,发现D3,js学习成本太高,G6 ...

  5. Scrapy进阶知识点总结(六)——中间件详解

    概述 查看scrapy官网的框架图,可以看出中间件处于几大主要组件之间,类似于生产流水线上的加工过程,将原料按照不同需求与功能加工成成品 其中4,5处于下载器与引擎之间的就是下载中间件,而spider ...

  6. jquery写$ document.getElementById效果

    jquery写$ document.getElementById效果<pre>document.getElementById('video-canvas')和$('#video-canva ...

  7. Resource Path Location Type Target runtime Apache Tomcat v6.0 is not defined(项目报错)已解决

    我换了开发工具后,导入的项目不是这里报错就是那里不错.不过,我喜欢.在tomcat里面部署项目后,定位到报错行时,总是提示我这句话:Description Resource Path Location ...

  8. mysql-大量数据的sql查询优化

    1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 2.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉 ...

  9. ios沙盒机制---基本数据类型的存取和文件的基本操作

    沙盒快速存储及读取 存储:  [[NSUserDefaults standardUserDefaults] setObject:@"abc" forKey:@"1&quo ...

  10. 分享使用PHP开发留言板

    首先我不是一名开发人员,只是一名小小的运维工程师,PHP是我自己喜欢的一门开发语言,所以我偶尔也会敲一些代码,写一些案例.今天我给大家分享的是使用PHP开发的留言板,留言板功能不全所以请大家见谅,也不 ...