JavaScript小游戏--2048(PC端)
1.初始化棋局
$(document).ready(function() {
prepare_for_mobile(); //适配移动端
new_game();
});
2.开始新游戏
function new_game() {
back = [];
//初始化棋盘
init();
//在随机两个格子生成数字
generate_one_number();
generate_one_number();
}
3.初始化
function init() {
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
var grid_cell = $('#grid_cell_' + i + '_' + j);
grid_cell.css('top', get_pos_top(i, j) + 'rem');//每个格子距离顶部和左边的距离;
grid_cell.css('left', get_pos_left(i, j) + 'rem');
}
}
for (var i = 0; i < 4; i++) {
board[i] = new Array();
has_conflicted[i] = new Array();
for (var j =0; j < 4; j++) {
board[i][j] = 0;//生成二维数组,每个格子的数字初始化为0;
has_conflicted[i][j] = false;
}
}
update_board_view();
score = 0;
update_score(score);
}
4.更新棋局(改数字大小、数字背景、设置数字宽度、高度、位置)
数字为0、 数字大于100、数字大于1024获取不同的数字大小及背景;
function update_board_view() {
$('.number_cell').remove();//??number_cell
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
$('#grid_container').append('<div class="number_cell" id="number_cell_' + i + '_' + j + '"></div>');
var number_cell = $('#number_cell_' + i + '_' + j);
if (board[i][j] == 0) {
number_cell.css({
'width': '0',//宽度、高度为0
'height': '0',
'top': get_pos_top(i, j) + 2.5 + 'rem',//这是每个数字的位置,其相对于每个格子的位置还要加2.5rem(每个格子高度、宽度为5rem)
'left': get_pos_left(i, j) + 2.5 +'rem',
'line-height': '5rem',
'font-size': '3rem'
});
}else if(board[i][j] >= 1024){
console.log(board[i][j]);
number_cell.css({
'width': '5rem',
'height': '5rem',
'top': get_pos_top(i, j) + 'rem',
'left': get_pos_left(i, j) + 'rem',
'background-color': get_number_background_color(board[i][j]),//改变背景颜色
'color': get_number_color(board[i][j]),//改变数字颜色
'line-height': '5rem',
'font-size': '2rem'//字体变小
});
number_cell.text(board[i][j]);
}else if(board[i][j] >= 100){
number_cell.css({
'width': '5rem',
'height': '5rem',
'top': get_pos_top(i, j) + 'rem',
'left': get_pos_left(i, j) + 'rem',
'background-color': get_number_background_color(board[i][j]),
'color': get_number_color(board[i][j]),
'line-height': '5rem',
'font-size': '2.5rem'
});
number_cell.text(board[i][j]);
}else {//小于100
number_cell.css({
'width': '5rem',
'height': '5rem',
'top': get_pos_top(i, j) + 'rem',
'left': get_pos_left(i, j) + 'rem',
'background-color': get_number_background_color(board[i][j]),
'color': get_number_color(board[i][j]),
'line-height': '5rem',
'font-size': '3rem'
});
number_cell.text(board[i][j]);//.text()方法设置或返回被选元素的文本内容
}
has_conflicted[i][j] = false;
}
}
}
5.随机在一个格子生成数字
function generate_one_number() {
if (nospace(board)) {//若nospace(board)返回true,说明没有空格子;
return false;
}
//随机一个位置
var randx = parseInt(Math.floor(Math.random() * 4));
var randy = parseInt(Math.floor(Math.random() * 4));//在124行调用
var time = 0;
while (time < 50) {//time??50??
if (board[randx][randy] == 0) {//看看随机选的位置上数字是否为0,为0则可用,跳出循环,不为0,则重新找位置。
break;
}
randx = parseInt(Math.floor(Math.random() * 4));//当board[randx][randy]不为0,则重新选位置。
randy = parseInt(Math.floor(Math.random() * 4));
time++;
}
if (time == 50) {//如果连续找了50次都没找到数字为0的位置,则按二维数组挨个去找,直到找到第一个数字为0的格子;
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
if (board[i][j] == 0) {
randx = i;
randy = j;
}
}
}
}
//随机一个数字
var rand_number = Math.random() < 0.5 ? 2 : 4;
//在随机位置显示随机数字
board[randx][randy] = rand_number;
show_number_with_animation(randx, randy, rand_number);//动画显示数字格子
save_status(board); //每生产一个数字,保存状态(以便撤回),模拟快照,每一步生成一个对象,调用support.js中函数
return true;
}
6.监听键盘的上下左右移动
keyCode(键码),指定与引发事件的键关联的Unicode的键码。此属性旨在与所述的onkeydown,的onkeyup和onkeypress事件的事件中使用。
键盘上下左右 方向键的键码(keyCode)是38、40、37和39
$(document).keydown(function(event) {
if ($('#score').text() == success_string) {//一按下键盘首先判断是否成功。324行判断数字是否到达2048,若等于2048则调用showanimation.js中的更新分数函数;
new_game();
return;
}
switch (event.keyCode) {//键盘上下左右 方向键的键码(keyCode)是38、40、37和39
case 37: //left
event.preventDefault();
if (move_left()) {
setTimeout('generate_one_number()', 200);//在指定的毫秒数后调用函数或计算表达式,setTimeout() 只执行 code 一次;
setTimeout('is_gameover()', 300);
}
break;
case 38: //up
event.preventDefault();
if(move_up()){
setTimeout('generate_one_number()',200);
setTimeout('is_gameover()', 300);
}
break;
case 39: //right
event.preventDefault();
if(move_right()){
setTimeout('generate_one_number()',200);
setTimeout('is_gameover()', 300);
}
break;
case 40: //down
event.preventDefault();
if (move_down()){
setTimeout('generate_one_number()',200);
setTimeout('is_gameover()', 300);
}
break;
default:
break;
}
});
7.向左移动 (向右移动、向上移动、向下移动类似)
function move_left() {//判断能否左移,调用support.js
if (!can_move_left(board)) {
return false;
}
//move left
for (var i = 0; i < 4; i++) {
for (var j = 1; j < 4; j++) { //j=1
if (board[i][j] != 0) {
for (var k = 0; k < j; k++) {
if (board[i][k] == 0 && no_block_horizontal(i, k, j, board)) {//(i,k)为0且(i,k)到(i,j)之间都是0
show_move_animation(i, j, i, k);//格子移动时有动画效果,从(i,j)到(i,k)
board[i][k] = board[i][j];
board[i][j] = 0;
break;//跳出的只是199行的for循环,外面还有两层循环
} else if (board[i][k] == board[i][j] && no_block_horizontal(i, k, j, board) && !has_conflicted[i][k]) {//可合并的情况,(i,k)和(i,j)数字相等且(i,k)到(i,j)之间都是0
show_move_animation(i, j, i, k);
board[i][k] += board[i][j];
board[i][j] = 0;
//add score
score += board[i][k];
update_score(score);
has_conflicted[i][k] = true;//??
break;
}
}
}
}
}
setTimeout('update_board_view()', 200);
return true;
}
8.判断游戏是否成功
function is_gameover() {
for(var i=0; i<4; i++){
for(var j=0; j<4; j++){
if (board[i][j] == 2048){
update_score(success_string);
return;
}
}
}
if (nospace(board) && nomove(board)) {//没有空格子,且各个方向不能移动合并;
gameover();
}
}
function gameover() {
alert("走投无路啦");
}
9.保存状态
function save_status(board) {
var o = new Object();
var n = 1;
for(var i=0; i<4; i++){
for(var j=0; j<4; j++){
o[n] = score+ ',' + board[i][j];//每个o长度为16
n ++;
}
}
back.push(o); //调用一次save_status(board),back长度加1.
}
10.撤销状态(回退)
function come_back() {
if (back.length<=2){//back数组长度小于2
return;
}
var o = back[back.length-2];//结合support.js中保存状态的函数理解,back数组长度减2,back[]取减2后的位置上的值,(每生成一个数字会保存一次状态,back数组长度加1)
var n = 1;
//o[n]遍历对象
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {//把存的score和board[i][j]取出
board[i][j] = parseInt(o[n].substr(o[n].lastIndexOf(',')+1));//lastIndexOf从右向左出现某个字符或字符串的首个字符索引值,该索引值加1,即可去到,的后半部分
score = parseInt(o[n]);//逗号前面的
n++;
}
}
update_score(score);
back.pop();
setTimeout('update_board_view()',200);
}
JavaScript小游戏--2048(PC端)的更多相关文章
- JavaScript小游戏--2048(移动端)
HTML5中新添加了很多事件,但是由于他们的兼容问题不是很理想,应用实战性不是太强,所以在这里基本省略,咱们只分享应用广泛兼容不错的事件,日后随着兼容情况提升以后再陆续添加分享.今天为大家介绍的事件主 ...
- JavaScript小游戏--2048(程序流程图)
- 制作一个 JavaScript 小游戏
简评: 作者学习了编程两个月,边学边做了一个 JavaScript 小游戏,在文中总结了自己在这个过程中的一些体会,希望能给其他初学者一些帮助. 对于很多想学编程但一直没下定决心的同学来说,最大的问题 ...
- javascript小实例,移动端页面中的拖拽
上文说到,想将移动端的拖拽说一说,那现在趁有时间,就将这个福利文带来了,哈哈! 在我还不知道怎么做移动端的手势操作的时候,我觉得这TM实在是太难了,这是多么高深的学问啊,手势操作耶,上滑下滑左滑右滑的 ...
- c语言----<项目>_小游戏<2048>
2048 小游戏 主要是针对逻辑思维的一个训练. 主要学习方面:1.随机数产生的概率.2.行与列在进行移动的时候几种情况.3.MessageBox的使用 #include <iostream&g ...
- 喜大普奔 | 微信小程序支持PC端打开了
微信小程序可以在PC端打开啦 微信PC版发布了v2.7.0测试版,其中一个重磅的功能就是:支持打开聊天中分享的小程序 咖啡君这么喜欢尝鲜的人自然是在第一时间下载进行了体验 安装成功,会有功能更新说明 ...
- C语言小游戏: 2048.c
概要:2048.c是一个C语言编写的2048游戏,本文将详细分析它的源码和实现.C语言是一种经典实用的编程语言,本身也不复杂,但是学会C语言和能够编写实用的程序还是有一道鸿沟的.本文试图通过一个例子展 ...
- JavaScript小游戏实例:统一着色
设计如下的简单小游戏. 在面板(画布)中放置10行10列共100个小方块,每个小方块随机在5种颜色中选一种颜色进行着色,在面板的下方,放置对应的5种颜色色块,如图1所示. 图1 “统一着色”游戏界面 ...
- JavaScript小游戏实例:简单的键盘练习
键盘是一种常用的输入设备,灵活熟练地使用键盘进行输入是计算机用户需掌握的一门基本功.下面我们编写一个简单的键盘练习游戏. 1.刺破气泡交互式小动画 在编写简单的键盘练习游戏之前,先设计一个简单地刺破气 ...
随机推荐
- css兼容小问题
1.RGBA在CSS3.0体现,不向下兼容: 2.非float元素和float元素在一起版本时,非float元素会排斥float元素,为避免换行,float元素应优先显示(放非float元素之前)
- 从MySQL到ORM(一):Centos7.x安装Mysql5.7
一.下载安装mysql 1.进入官网获取RPM包:https://dev.mysql.com/downloads/repo/yum/ 2.复制链接地址进行下载: wget https://dev.my ...
- Java 8 读取文件
以前的Java版本中读取文件非常繁琐,现在比较简单.使用Java8的Files以及Lambda,几句代码就可以搞定. public static String getXml() { StringBuf ...
- IO流之 commons-IO
commons-IO 导入classpath 加入classpath的第三方jar包内的class文件才能在项目中使用 创建lib文件夹 将commons-io.jar拷贝到lib文件夹 右键点击co ...
- 谈谈HTML5中的history.pushSate方法,弥补ajax导致浏览器前进后退无效的问题
移动端为了减少页面请求,有时候需要通过单页面做成多页面的效果,最近有这么个需求,表单填完后执行第一步,然后执行第二步,第二步执行完后再执行第三步,每一步都要保留之前的数据.这种情况用单页面实现再合适不 ...
- vue-router 的使用
vue-router 是 vue 的 一个特色. 下面介绍vue-router 的使用: 一.先将vue-router作为vue 的一个插件使用 import Vue from 'vue' imp ...
- Linux基础之命令练习Day1-init,who,date,cal,man,clear,passwd,su,whoami,mkdir,touch,rm,cp,mv,head,tail,more,less,echo
开启Linux操作系统,要求以root用户登录GNOME图形界面,语言支持选择为汉语 使用快捷键切换到虚拟终端2,使用普通用户身份登录,查看系统提示符 使用命令退出虚拟终端2上登录的用户 使用快捷键切 ...
- <Android 基础(十九)> CoordinatorLayout
介绍 CoordinatorLayout,中文翻译,协调布局,顾名思义,此布局中的子View之间,子View与父布局之间应该是可以协调工作的,如何协调,Behavior. 今天看下Android St ...
- 您需要售后返修管理软件的N个理由
一.减少人工成本. 二.提高工作效率. 三.其他管理成本降低. ▲传统采用人工登记或电子表格Excel管理 售后人员,他们日常的工作就是接件.维修.送修.记录.统计.跟件.寄送件.电话客户沟通.电话厂 ...
- iDempiere 使用指南 开发环境搭建
Created by 蓝色布鲁斯,QQ32876341,blog http://www.cnblogs.com/zzyan/ iDempiere官方中文wiki主页 http://wiki.idemp ...