HTML5实现一笔画游戏

HTML5实现一笔画游戏

一笔画问题

一笔画是图论科普中一个著名的问题,它起源于柯尼斯堡七桥问题科普。当时的东普鲁士哥尼斯堡城中有一条河,在这条河上有七座桥:

蓝色的代表河,这条河将城市分开成为四个区域,而七个橙色的矩形为座桥。

欧拉把实际的问题抽象为平面上的点与线,每一座桥视为一条线,桥所连接的地区视为点。

 “一笔画”问题涉及的核心概念包括连通图、奇点、偶点等。连通图指的是图中任意两个顶点之间都存在一条路径相连且没有重复。奇点则是与奇数个边相连的顶点,偶点则是与偶数个边相连的顶点。

欧拉发现,一个连通图能够一笔画出的条件是:要么图中所有顶点都是偶点,要么图中只有两个奇点。这个规律被称为欧拉定理,它为解决一笔画问题提供了理论基础。

由于哥尼斯堡七桥问题的抽象图中的四个顶点全部是奇顶点,所以它无法实现符合要求的走法,也就是不可能一笔画成。

数学家欧拉在他1736年发表的论文《柯尼斯堡的七桥》中不仅解决了七桥问题,也提出了一笔画定理,顺带解决了一笔画问题。他的这篇论文也成为图论史上第一篇重要文献。

HTML5实现一笔画游戏

HTML5和Canvas API提供了强大的图形处理能力,足以支持一笔画这样的游戏开发。

先给出效果图示:

游戏由两个文件构成:html文件(我这里命名为:一笔画游戏.html)和JavaScript脚本文件 (我这里命名为:game.js),我这里将这两个文件放在同一文件夹中。

html文件“一笔画游戏.html”源码如下

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>一笔画游戏</title><style>canvas {border: 1px solid black;}</style>
</head>
<body><canvas id="gameCanvas" width="300" height="300"></canvas><div><button onclick="startGame('easy')">简单</button><button onclick="startGame('medium')">中等</button><button onclick="startGame('hard')">困难</button><br> 连接线段时,必须按照一定的顺序来连接点。<br> 两点间连线方法:从一个点按下鼠标左键拖动到释放。</div><script src="game.js"></script>
</body>
</html>

JavaScript脚本文件 game.js源码如下

// game.jslet canvas = document.getElementById("gameCanvas");
let ctx = canvas.getContext("2d");let isDrawing = false;
let startPoint = null;
let lastPointId = null;let presetPoints = [];
let presetLines = [];
let userLines = [];const levels = {easy: {points: [{id: 1, x: 50, y: 50}, {id: 2, x: 150, y: 50}, {id: 3, x: 150, y: 150},{id: 4, x: 50, y: 150}],lines: [{start: 1, end: 2}, {start: 2, end: 3}, {start: 3, end: 4},{start: 4, end: 1},{start: 2, end: 4}]},medium: {points: [{id: 1, x: 50, y: 100}, {id: 2, x: 150, y: 100}, {id: 3, x: 250, y: 100}, {id: 4, x: 100, y: 200}, {id: 5, x: 200, y: 200}],lines: [{start: 1, end: 2}, {start: 2, end: 3}, {start: 1, end: 4}, {start: 2, end: 5}, {start: 3, end: 5}, {start: 4, end: 5}]},hard: {points: [{id: 1, x: 50, y: 50}, {id: 2, x: 150, y: 50}, {id: 3, x: 250, y: 50}, {id: 4, x: 50, y: 150}, {id: 5, x: 150, y: 150}, {id: 6, x: 250, y: 150}, {id: 7, x: 50, y: 250}, {id: 8, x: 150, y: 250}, {id: 9, x: 250, y: 250}],lines: [{start: 1, end: 2}, {start: 2, end: 3}, {start: 1, end: 4}, //{start: 2, end: 5}, {start: 3, end: 6}, {start: 4, end: 5}, //{start: 5, end: 6}, {start: 4, end: 7}, {start: 5, end: 8}, {start: 6, end: 9}, {start: 7, end: 8}, {start: 8, end: 9}]}
};function startGame(difficulty) {const level = levels[difficulty];if (!level) {console.error('未知难度级别');return;}presetPoints = level.points;presetLines = level.lines;userLines = [];lastPointId = null;draw();
}canvas.addEventListener("mousedown", (e) => {isDrawing = true;startPoint = getPointFromMouseEvent(e);
});canvas.addEventListener("mouseup", (e) => {if (!isDrawing || !startPoint) return;let endPoint = getPointFromMouseEvent(e);if (endPoint && startPoint.id !== endPoint.id) {if (lastPointId === null || lastPointId === startPoint.id) {if (isPresetLine(startPoint.id, endPoint.id)) {userLines.push({start: startPoint, end: endPoint});lastPointId = endPoint.id;draw();} else {alert("不能绘制原图中不存在的线段。");}} else {alert("必须按顺序连接点。");}}isDrawing = false;
});function getPointFromMouseEvent(e) {const rect = canvas.getBoundingClientRect();const x = e.clientX - rect.left;const y = e.clientY - rect.top;return presetPoints.find(p => Math.sqrt((p.x - x) ** 2 + (p.y - y) ** 2) < 10);
}function isPresetLine(startId, endId) {return presetLines.some(line => (line.start === startId && line.end === endId) || (line.start === endId && line.end === startId));
}function draw() {ctx.clearRect(0, 0, canvas.width, canvas.height);// 绘制预设线段presetLines.forEach(line => {let start = presetPoints.find(p => p.id === line.start);let end = presetPoints.find(p => p.id === line.end);drawLine(start, end, 'black');});// 绘制用户线段userLines.forEach(line => {drawLine(line.start, line.end, 'red');});// 绘制点presetPoints.forEach(point => {drawPoint(point);});// 检查胜利条件if (checkWin()) {alert("恭喜,你完成了这个难度级别的游戏!");}
}function checkWin() {if (userLines.length !== presetLines.length) {return false;}// 检查每个用户线段是否匹配预设线段for (let userLine of userLines) {const startId = userLine.start.id;const endId = userLine.end.id;const match = presetLines.some(line => (line.start === startId && line.end === endId) || (line.start === endId && line.end === startId));if (!match) {return false;}}return true;
}function drawLine(start, end, color) {ctx.beginPath();ctx.moveTo(start.x, start.y);ctx.lineTo(end.x, end.y);ctx.strokeStyle = color;ctx.stroke();
}function drawPoint(point) {ctx.beginPath();ctx.arc(point.x, point.y, 5, 0, 2 * Math.PI);ctx.fillStyle = 'blue';ctx.fill();
}// 初始化游戏
startGame('easy');

说明,定义不同难度的关卡数据:

const levels = {
    easy: {
        // 定义简单难度的点和线段
    },
    medium: {
        // 定义中等难度的点和线段
    },
    hard: {
        // 定义高难度的点和线段
    }
};

这些点的 x 和 y 坐标是基于画布的尺寸和布局预设的。你可能需要根据你的具体实现调整这些坐标值,以确保点和线在你的游戏界面中正确显示。此外,这些关卡设计仅作为示例,你可以根据需要调整点和线的数量及布局,创造出更多不同难度的关卡。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/752492.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习 精选笔记(13.2)深度卷积神经网络-AlexNet模型

学习参考&#xff1a; 动手学深度学习2.0Deep-Learning-with-TensorFlow-bookpytorchlightning ①如有冒犯、请联系侵删。 ②已写完的笔记文章会不定时一直修订修改(删、改、增)&#xff0c;以达到集多方教程的精华于一文的目的。 ③非常推荐上面&#xff08;学习参考&#x…

深入浅出Hive性能优化策略

我们将从基础的HiveQL优化讲起&#xff0c;涵盖数据存储格式选择、数据模型设计、查询执行计划优化等多个方面。会的直接滑到最后看代码和语法。 目录 引言 Hive架构概览 示例1&#xff1a;创建表并加载数据 示例2&#xff1a;优化查询 Hive查询优化 1. 选择适当的文件格…

unity学习(61)——hierarchy和scene的全新认识+模型+皮肤+动画controller

刚刚开始&#xff0c;但又结束的感觉&#xff1f; 1.对hierarchy和scene中的内容有了全新的认识 一定要清楚自己写过几个scene&#xff1b;每个scene之间如何跳转&#xff1b;build setting是add当前的scene。 2.此时的相机需要与模型同级&#xff0c;不能在把模型放在相机下…

odoo中传递上下文

在Odoo中&#xff0c;上下文&#xff08;context&#xff09;是一个非常重要的概念&#xff0c;它允许开发人员在不同的动作、视图或模型间传递信息。上下文通常用于传递特定的标志或变量&#xff0c;这些变量可以影响方法的行为或视图的展示方式。 向表单和动作传递参数 1. …

vue的一些个人理解

个人的一些理解吧 可能不是很全面有的地方可能也不准确 MVVM 的理解 MVVM 是 Model-View-ViewModel 的缩写。MVVM 是一种设计思想。 Model 层代表数据模型&#xff0c;也可以在 Model 中定义数据修改和操作的业务逻辑; View 代表 UI 组件&#xff0c;它负责将数据模型转化成 U…

STM32的USART能否支持9位数据格式话题

1、问题描述 STM32L051 这款单片机。平常的 USART 串口传输是 8 位数据&#xff0c;但是他的项目需要用串口传输 9 位数据。当设置为 8 位数据时&#xff0c;串口响应中断正常。但是&#xff0c;当设置为 9 位数据时&#xff0c;串口就不产生中断了。USART2 的 ISR 寄存器 RXN…

ssh命令——安全远程连接Linux服务器

ssh命令是Secure Shell的简写&#xff0c;其功能是安全地远程连接服务器&#xff0c;ssh是OpenSSH套件中的客户端连接工具&#xff0c;通过SSH加密协议进行远程主机访问&#xff0c;并对远程服务器进行管理。 ssh命令的基本语法格式如下&#xff1a; ssh [选项] 主机名或IP地…

STM32G4高精度定时器的同步功能

1、引言 STM32G474 所含的高精度定时器(HRTIMER)其实包含了多个定时器&#xff0c;多个定时器之间可以单独工作&#xff0c;也可以进行同步&#xff0c;且高精度定时器还能与片上的其他定时器以及其他芯片进行同步&#xff0c;本文将对高精度定时器的同步功能进行介绍。 2、定…

linux安装wxWidgets

概要 在Linux系统中安装erlang时&#xff0c;需要提前安装wxWidgets&#xff01; 官方地址: https://docs.wxwidgets.org gitCode地址&#xff1a;https://gitcode.com/wxWidgets/wxWidgets 下载 下载地址&#xff1a; wget https://github.com/wxWidgets/wxWidgets/releas…

I2S 协议简介

I2S(Inter-IC Sound)是飞利浦公司提出的一种用于数字音频设备之间进行音频数据传输的总线。和 I2C、SPI 这些常见的通信协议一样&#xff0c;I2S 总线用于主控制器和音频 CODEC 芯片之间传输音频数据。 I2S 接口需要 3 根信号线(如果需要实现收和发&#xff0c;那么就要 4 根信…

【Text-to-CAD】基于生成式AI的CAD文件生成工具

Text-to-CAD作为一种机械设计工具,通过简单的文本提示实现CAD文件的智能生成。其开源接口、机器学习支持和Fine Tuning选项为用户提供了高度可定制化的体验。未来的Fine Tuning功能和可能的商业合作有望进一步拓展其在机械设计领域的影响力。 产品概述: 名称: Text-to-CAD类…

Django项目创建和settings设置

2021版本的pycharm有bug,需要将settings.py中 把BASE_DIR后面的/换成, url:统一资源定位符 互联网上每个文件都有一个唯一的url,它包含的信息指出文件的位置以及浏览器应该怎么处理它 语法: protocol://hostname[:port]/path[?query][#fragment] protocol:协议 hostname:主…

【excel】常用的50个函数与基础操作(统计函数)

统计函数 &#xff08;1&#xff09;数组函数操作 1.【SUM】求和 SUM&#xff08;数字1&#xff0c;数字2&#xff0c;数字3…&#xff09; 2.【SUMIF】单条件求和 SUMIF &#xff08;条件区域&#xff0c;条件&#xff0c;求和区域&#xff09; 3.【SUMIFS】(单)多条件求和…

程序员应该如何选择职业赛道?

程序员选择职业赛道是一个涉及个人兴趣、技能匹配、市场需求和长远发展规划的综合决策过程。以下是一些关键步骤和考虑因素&#xff1a; 自我评估&#xff1a; 技能与专长&#xff1a;分析自己在编程语言、算法、数据结构等方面的现有技能&#xff0c;并思考这些技能更适合前端…

适用于系统版本:CentOS 6/7/8的基线安全检测脚本

#!/bin/bash #适用于系统版本&#xff1a;CentOS 6/7/8 echo "----------------检测是否符合密码复杂度要求----------------" #把minlen&#xff08;密码最小长度&#xff09;设置为8-32位&#xff0c;把minclass&#xff08;至少包含小写字母、大写字母、数字、特殊…

51单片机—DS18B20温度传感器

目录 一.元件介绍及原理 二&#xff0c;应用&#xff1a;DS18B20读取温度 一.元件介绍及原理 1.元件 2.内部介绍 本次元件使用的是单总线 以下为单总线的介绍 时序结构 操作流程 本次需要使用的是SKIP ROM 跳过&#xff0c; CONVERT T温度变化&#xff0c;READ SCRATCHPAD…

AI美图设计室试用,可以生成PPT,以及模特试衣

文章目录 美图设计室试用 美图设计室试用 美图设计室是美图秀秀的公司推出的AI图像处理工具&#xff0c;其功能涵盖图片编辑、抠图、海报设计、文生图等常用的AI功能。尽管很多功能需要开通会员使用&#xff0c;但一些免费功能的表现也还不错&#xff0c;值得一用。 美图设计…

Spring Boot(六十九):利用Alibaba Druid对数据库密码进行加密

1 Alibaba Druid简介 之前介绍过Alibaba Druid的,章节如下,这里就不介绍了: Spring Boot(六十六):集成Alibaba Druid 连接池 这章使用Alibaba Druid进行数据库密码加密,在上面的代码上进行修改,这章只介绍密码加密的步骤。 目前越来越严的安全等级要求,我们在做产品…

JS原型和原型链的理解

原型链图&#xff0c;图中Parent是构造函数&#xff0c;p1是通过Parent实例化出来的一个对象 前置知识 js中对象和函数的关系&#xff0c;函数其实是对象的一种 函数、构造函数的区别&#xff0c;任何函数都可以作为构造函数&#xff0c;但是并不能将任意函数叫做构造函数&…

简单的Charles抓包教程

安装Charles 安装地址&#xff1a;https://www.charlesproxy.com/download/ 开关本机抓包 一般我们在抓取手机端内容时需要将Proxy菜单栏下的Windows Proxy取消勾选&#xff0c;禁止charles抓取本机上的请求信息。 注&#xff1a;开启电脑端抓包后&#xff0c;会为电脑添加局…