设计如下的简单小游戏。

在面板(画布)中放置10行10列共100个小方块,每个小方块随机在5种颜色中选一种颜色进行着色,在面板的下方,放置对应的5种颜色色块,如图1所示。

图1  “统一着色”游戏界面

游戏要求通过每次对包含最左上角方块的相邻同色区域方块改变着色的方式,最终使得面板中的100个小方块着色统一。

例如,图1中包含最左上角方块的相邻同色区域方块只有1个,此时对其有效改变着色应该是选择“绿色”(下方相邻的方块颜色)或“棕色”(左边相邻的方块颜色),这样扩大了包含最左上角方块的相邻同色区域;否则,不扩大包含最左上角方块的相邻同色区域,应是无效的着色选择。

单击面板下方5个色块中的某个色块,就可以将包含最左上角方块的相邻同色区域的所有方块颜色改为所单击色块的颜色。一次游戏过程如图2所示。

图2  “统一着色”游戏过程示例

定义一个数组

var colors = ["Aquamarine","Blue","BlueViolet","Brown","Chartreuse","Chocolate","Cyan",

"DeepPink","Fuchsia","Green","Orange","Purple","Red","SkyBlue","Yellow"];

保存游戏可供选择的颜色。

每局游戏选择5个色块,定义数组 var options=[];保存在colors数组中选择的5种颜色所对应的下标。为了达到随机选择5种颜色,采用对颜色数组进行简单洗牌的方法来完成。

定义数组var blocks=[];保存面板中100个小方块的着色,第i行第j列小方块的着色保存在数组元素blocks[10*i+j]中。初始时,每个小方块的着色在选定的5种颜色中随机选择一种,一个简单的循环可完成。

for (var i=0;i<100;i++)

blocks[i]=options[Math.floor(Math.random()*5)];

单击面板下方5个小色块中某个色块后,调用函数setColor()完成改变着色的过程。

改变着色的区域是包含最左上角方块的相邻同色区域的所有方块,因此关键问题是怎么找到这个相邻同色区域中的所有方块。可采用广度优先搜索算法的思想来完成。算法描述为:

记下最左上角方块的初始着色srcColor;

队列初始化;

最左上角方块编号 0入队;

while (队列非空)

{

队头元素出队,赋给k;

改变方块k的着色(修改blocks[k]的值为所单击色块的颜色编号destColor);

if  (方块k右边的方块k+1存在且颜色为srcColor)

方块编号k+1入队;

if  (方块k下边的方块k+10存在且颜色为srcColor)

方块编号k+10入队;

}

实际上,一个方块相邻的方块有上下左右四个,但算法中只需考虑右边和下边,无需考虑左边和上边。这是因为本游戏的着色改变总是改变包含最左上角方块的相邻区域,即搜索总是从最左上角方块开始,而最左上角方块只能向右边和下边扩展,之后每个方块也只需向右边和下边扩展即可,无需向左边和上边扩展(因为左边和上边的方块已被扩展处理过)。

获胜判断就更简单了,因为获胜的条件是所有方块的着色统一,即数组blocks的元素值全部相同,因此用循环检查元素blocks[1]~blocks[99],若它们的值全部与blocks[0]相同,则获胜,否则只要有一个元素与blocks[0]不同,就没有达到着色统一的获胜要求。编写为一个简单的函数。

function checkWin()

{

for (var i=1;i<blocks.length;i++)

if (blocks[i]!=blocks[0])  return false;

return true;

}

另外,为避免游戏过程中的无效色块单击,记录游戏的步数(色块单击次数),若35步内不能完成统一着色,判定游戏失败。

完整的HTML代码如下。

<!DOCTYPE html>
<html>
<head>
<title>统一着色</title>
<style>
.num
{
padding: 28px 0;
border: 1px solid ;
cursor: pointer;
}
.new-game {
cursor: pointer;
text-decoration: underline;
color: #00bcd4;
font:bold 24px Georgia, serif;
}
#mess
{
width:480px;
padding:5px;
border:2px solid gray;
margin:0px;
font:bold 24px Georgia, serif;
color: #FF6600;
}
</style>
</head>
<body>
<div class="new-game" onclick="newGame();">New Game</div><br/>
<canvas id="myCanvas" width="500" height="500" style="border:3px double #996633;">
</canvas><br/>
<table cellpadding="0" cellspacing="20">
<tbody><tr>
<td width="60"><div id="c0" class="num" onclick="setColor(this);"></div></td>
<td width="60"><div id="c1" class="num" onclick="setColor(this);"></div></td>
<td width="60"><div id="c2" class="num" onclick="setColor(this);"></div></td>
<td width="60"><div id="c3" class="num" onclick="setColor(this);"></div></td>
<td width="60"><div id="c4" class="num" onclick="setColor(this);"></div></td>
</tr>
</tbody>
</table><br/>
<div id="mess">&nbsp;</div><br/>
<script type="text/javascript">
var canvas=document.getElementById('myCanvas');
ctx= canvas.getContext('2d');
var colors = ["Aquamarine","Blue","BlueViolet","Brown","Chartreuse","Chocolate","Cyan","DeepPink","Fuchsia ","Green","Orange","Purple","Red","SkyBlue","Yellow"];
var running = false;
var steps=0;
function shuffle(arr) // 数组arr洗牌
{
for (var i = arr.length-1; i>=0; i--)
{
var j = Math.floor(Math.random() * i);
var t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
var colorNum=[];
for (var i=0;i<colors.length;i++) colorNum[i]=i;
var options=[];
var blocks=[];
function newGame()
{
shuffle(colorNum);
options=colorNum.slice(0,5);
for (var i=0;i<100;i++)
blocks[i]=options[Math.floor(Math.random()*5)];
running=true;
steps=0;
draw();
document.getElementById("c0").style.backgroundColor =colors[options[0]];
document.getElementById("c1").style.backgroundColor =colors[options[1]];
document.getElementById("c2").style.backgroundColor =colors[options[2]];
document.getElementById("c3").style.backgroundColor =colors[options[3]];
document.getElementById("c4").style.backgroundColor =colors[options[4]];
document.getElementById("mess").innerHTML ="Steps:"+steps+"/35";
}
function draw()
{
for (var i=0;i<10;i++)
{
for (var j=0;j<10;j++)
{
ctx.fillStyle = colors[blocks[i*10+j]];
ctx.fillRect(j*50,i*50,50,50);
}
}
ctx.fillStyle ="rgba(255,255,255,0.85)";
ctx.fillRect(20,20,10,10);
}
function setColor(d)
{
if (!running)
{
document.getElementById("mess").innerHTML ="请单击 New Game 开始新游戏!";
return;
}
var index= parseInt(d.id.charAt(1));
var srcColor=blocks[0];
var destColor=options[index];
if (srcColor==destColor)
{
document.getElementById("mess").innerHTML ="Steps:"+steps+"/35 未进行颜色改变,无效单击!";
return;
}
var queue=[];
var front=0;
var rear=0;
queue[rear++]=0;
while (front<rear)
{
var k=queue[front++];
blocks[k]=destColor;
if (k%10!=9 && blocks[k+1]==srcColor) // 右边的方格
queue[rear++]=k+1;
if (k<90 && blocks[k+10]==srcColor) // 下边的方格
queue[rear++]=k+10;
}
draw();
steps++;
document.getElementById("mess").innerHTML ="Steps:"+steps+"/35";
if (checkWin())
{
running=false;
ctx.font = '50px PingFang SC';
ctx.fillStyle = "red";
ctx.textAlign = 'center';
ctx.baseline = 'middle';
ctx.fillText('You Win!',canvas.width/2, canvas.height/2);
}
else
{
if (steps==35)
{
running=false;
ctx.font = '50px PingFang SC';
ctx.fillStyle = "black";
ctx.textAlign = 'center';
ctx.baseline = 'middle';
ctx.fillText('You failed!',canvas.width/2, canvas.height/2);
}
}
}
function checkWin()
{
for (var i=1;i<blocks.length;i++)
if (blocks[i]!=blocks[0]) return false;
return true;
}
newGame();
</script>
</body>
</html>

JavaScript小游戏实例:统一着色的更多相关文章

  1. JavaScript小游戏实例:简单的键盘练习

    键盘是一种常用的输入设备,灵活熟练地使用键盘进行输入是计算机用户需掌握的一门基本功.下面我们编写一个简单的键盘练习游戏. 1.刺破气泡交互式小动画 在编写简单的键盘练习游戏之前,先设计一个简单地刺破气 ...

  2. 制作一个 JavaScript 小游戏

    简评: 作者学习了编程两个月,边学边做了一个 JavaScript 小游戏,在文中总结了自己在这个过程中的一些体会,希望能给其他初学者一些帮助. 对于很多想学编程但一直没下定决心的同学来说,最大的问题 ...

  3. javascript小游戏--生命游戏

    昨天参加Code Retreat的活动,"Code Retreat是一个一天的集中练习的活动,专注于软件开发和设计的基础". 要了解更多信息可前往 CodeRetreat官网 通过 ...

  4. JavaScript小游戏--2048(PC端)

    1.初始化棋局 $(document).ready(function() { prepare_for_mobile(); //适配移动端 new_game(); }); 2.开始新游戏 functio ...

  5. JavaScript小游戏--翻牌记忆游戏

    翻牌记忆游戏源码 1.有8张图片,每张图片要放两次,生成如下数组,长为16,[0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7] 其中两两相同的代表两张相同的图片,0对应文件夹image ...

  6. JavaScript 小游戏 贪吃蛇

    贪吃蛇 代码: <!DOCTYPE html><html><head> <meta charset="UTF-8"> <met ...

  7. CSS技术实例1-使用CSS计数器实现数值计算小游戏实例页面

    一 实例要达到的要求如图所示: 二 分析 1.7个圆角矩形标签(或按钮) 2. 点击触发并开始运算,最后一个标签显示结果 3.计算成功后弹出"万岁"字眼 三 代码实现 关键CSS代 ...

  8. Chrome内置的断网Javascript 小游戏脚本示范

    //示范面向对象 this 作用域 闭包 单例模式很好的示范 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. // ...

  9. JavaScript小游戏--2048(移动端)

    HTML5中新添加了很多事件,但是由于他们的兼容问题不是很理想,应用实战性不是太强,所以在这里基本省略,咱们只分享应用广泛兼容不错的事件,日后随着兼容情况提升以后再陆续添加分享.今天为大家介绍的事件主 ...

随机推荐

  1. shell专题(十一):企业真实面试题(重点)

    11.1 京东 问题1:使用Linux命令查询file1中空行所在的行号 答案: [atguigu@hadoop102 datas]$ awk '/^$/{print NR}' sed.txt 问题2 ...

  2. redis(十七):Redis 安装,部署(WINDOWS环境下)

    1.下载Redis安装文件, 我选择的是 3.0.504 版本,有zip或msi可供下载.   2.解压缩后,打开安装目录 双击redis-server.exe启动redis服务器,双击redis-c ...

  3. 机器学习实战基础(十八):sklearn中的数据预处理和特征工程(十一)特征选择 之 Wrapper包装法

    Wrapper包装法 包装法也是一个特征选择和算法训练同时进行的方法,与嵌入法十分相似,它也是依赖于算法自身的选择,比如coef_属性或feature_importances_属性来完成特征选择.但不 ...

  4. 集合-ConcurrentLinkedQueue 源码解析

    问题 (1)ConcurrentLinkedQueue是阻塞队列吗? (2)ConcurrentLinkedQueue如何保证并发安全? (3)ConcurrentLinkedQueue能用于线程池吗 ...

  5. 学会Python除了不能生孩子,其他的都能做。

    随着人工智能的迅猛发展,相信大家对于it行业最熟悉的词莫过于 Python.那么,Python究竟可以做些什么呢?一个资深程序员说:“学会Python除了不能生孩子,其他的都能做.”加入3137821 ...

  6. 题解 洛谷 P6142 【[USACO20FEB]Delegation P】

    和赛道修建类似,先对\(k\)进行二分,将最值问题转化为判定问题. 在判定一个\(k\)是否合法时,贪心去考虑,一个节点下面的若干条链在合并时,一条链肯定和另一条使它合并后恰好满足长度限制的链合并最优 ...

  7. Spring Cloud Alibaba教程:Nacos

    Nacos是什么 Nacos 致力于帮助您发现.配置和管理微服务,它 提供了一组简单易用的特性集,帮助您快速实现动态服务发现.服务配置.服务元数据及流量管理. 注册中心 nacos-server 可以 ...

  8. 数据页结构 .InnoDb行格式、以及索引底层原理分析

    局部性原理 局部性原理是指CPU访问存储器时,无论是存取指令还是存取数据,所访问的存储单元都趋于聚集在一个较小的连续区域中. 首先要明白局部性原理能解决的是什么问题,也就是主存容量远远比缓存大, CP ...

  9. JavaFX让UI更美观-CSS样式

    相对于Swing来说,JavaFX在UI上改善了很多,不仅可以通过FXML来排版布局界面,同时也可以通过CSS样式表来美化UI. 其实在开发JavaFX应用的时候,可以将FXML看做是HTML,这样跟 ...

  10. 史蒂夫-乔布斯(Steve Jobs)斯坦福大学演讲稿(中英对照)

    这是苹果公司和Pixar动画工作室的CEO Steve Jobs于2005年6月12号在斯坦福大学的毕业典礼上面的演讲稿. Thank you. I'm honored to be with you ...