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

源码已发布至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. 启动elasticsearch报错的几种原因及解决方法

    ERROR: [1] bootstrap checks failed [1]: max virtual memory areas vm.max_map_count [65530] is too low ...

  2. ArangoDB简单实例介绍

    数据介绍: 2008美国国内航班数据 airports.csv flights.csv 数据下载地址:https://www.arangodb.com/graphcourse_demodata_ara ...

  3. 在jupyter中调用R

    目录 安装R 关联jupyter notebook 安装R 系统:Ubuntu:16.04 步骤1.添加镜像源 $ sudo echo "deb http://cran.rstudio.co ...

  4. ansible模块之yum、pip、service、corn、user、group

    ansible相关模块 yum rpm 和yum 的区别 rpm:全称redhat package manager (红帽包管理器) 不能解决包之间的依赖关系 yum:可以解决依赖关系 yum 源配置 ...

  5. python中的列表list练习

    列表: 1.增 1.1 append,在列表的末尾追加元素,使用方法:list.append('元素') li = ['alex', 'wusir', 'eric', 'rain', 'alex'] ...

  6. 网页开发利用jq自定义鼠标右击事件

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

  7. springboot(3)——配置文件和自动配置原理详细讲解

    原文地址 目录 概述 1. 配置文件作用 2.配置文件位置 3.配置文件的定义 3.1如果是定义普通变量(数字 字符串 布尔) 3.2如果是定义对象.Map 3.3如果是定义数组 4.配置文件的使用 ...

  8. Java8系列 (七) CompletableFuture异步编程

    概述 Java8之前用 Future 处理异步请求, 当你需要获取任务结果时, 通常的做法是调用  get(long timeout, TimeUnit unit) 此方法会阻塞当前的线程, 如果任务 ...

  9. Kong07-自定义 Kong 插件

    在进一步讨论之前,有必要简要说明 Kong 是如何构建的,特别是它是如何与 Nginx 集成的,以及 Lua 与它有什么关系. 在 Nginx 中,lua-nginx-module 模块支持 Lua ...

  10. 让NOI Linux变得可用

    开始用NOI Linux-- 上古加阉割,还是32位,完全不可用的亚子-- 怎么办,我真的好想念16.04 于是就走上魔改之旅-- 一些神奇的操作 git 听说直接装的话会是上古版本 sudo add ...