level 1
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-16">
<style type="text/css">
.floor{height:15px;}
.Sand{width:15px; height:15px; float:left}
</style>
</head>
<body>
<script type="text/javascript" defer="defer">
var row1 = document.createElement("div");
var row2 = document.createElement("div");
var input = document.createElement("input");
input.addEventListener("keyup", drawImg);
document.body.appendChild(row1);
document.body.appendChild(row2);
row1.appendChild(input);
var rowsNum = null;//行数(沙漏的一半)
var rowWidth = null;//沙漏整体宽度
var lowerSandSum = 0;//下半部分的沙粒总数
/**沙粒落下*/
function drop(){
if(lowerSandSum === rowsNum * rowsNum){
lowerSandSum=-1;
}
lowerSandSum++;//下半部分的沙粒总数加1
var triangleNum = Math.floor(Math.sqrt(lowerSandSum));//上面少了的沙粒 或 下面多出来的沙粒,能组成的图形的层数
var triangleArr = new Array();//沙堆的层数数组
//初始化triangleArr,每一层都是0粒沙
for(var i=0; i<triangleNum; i++){
triangleArr[i] = 0;
}
var count = 0;
while(count<lowerSandSum){
count++;
var floorArr = getFloorArr(count, triangleNum);
for(var i=triangleArr.length-1; i>=0; i--){
//triangleArr[i]表示triangleArr的某层,其值代表当前层的沙粒数
//floorArr[i]表示当前层的沙粒数上限
if(triangleArr[i] < floorArr[i]){
triangleArr[i]++;
break;
}
}
}
//将triangleArr补充至rowsNum行
for(var i=triangleNum; i<rowsNum; i++){
triangleArr.unshift(0);
}
redraw(triangleArr);
}
/**根据代表沙堆的floorArr,重绘沙漏*/
function redraw(triangleArr){
var imgArr = new Array();
//"上半部分"缺失沙粒,镂空形成图形
for(var i=1; i<=rowsNum; i++){
var rowSandSum = i*2-1; //这一层最多能容纳的沙粒总数
var currRowSandSum = rowSandSum-triangleArr[i-1]; //这一行当前的沙粒总数
var res = drawUpperRow(rowSandSum, currRowSandSum);
imgArr.unshift(res);
}
//"下半部分"落下沙粒,堆成图形
for(var i=1; i<=rowsNum; i++){
var rowSandSum = i*2-1; //这一层最多能容纳的沙粒总数
var currRowSandSum = triangleArr[i-1]; //这一行当前的沙粒总数
var res = drawLowerRow(rowSandSum, currRowSandSum);
imgArr.push(res);
}
var floorArr = row2.childNodes;//沙漏的所有层
for(var i=0; i<floorArr.length; i++){
var floor = floorArr[i];
var img = imgArr[i];
for(var j=0; j<floor.childNodes.length; j++){
var div = floor.childNodes[j];
var ch = img.charAt(j);
div.innerText = ch;
}
}
}
/**获取这count粒沙粒,组成的arrNum层图形,每层的沙粒数量上限*/
function getFloorArr(count, arrNum){
var floorArr = new Array();
if(count == arrNum*arrNum){
for(var i=1; i<=arrNum; i++){
floorArr.push(2*i-1);
}
}else{
for(var i=1; i<=arrNum; i++){
floorArr.push(2*i+1);
}
var temp = Math.floor(Math.sqrt(count));
if(temp < arrNum){
floorArr.pop();
}
for(var i=floorArr.length; i<arrNum; i++){
floorArr.unshift(0);
}
}
return floorArr;
}
function drawImg(event){
if(event.keyCode == 13){
rowsNum = parseInt(input.value);
if(!rowsNum){
input.value = "";
return;
}
row2.innerHTML = "";
rowWidth = rowsNum*2-1;//沙漏宽度,即每一行的最大沙粒数量
init();
auto();
}
}
function auto(){
setTimeout(
function(){
drop();
setTimeout(arguments.callee, 500);
},500);
}
function init(){
//上半部分
for(var i=rowsNum; i>0; i--){//行数
var rowNo = document.createElement("div");
rowNo.className="floor";
row2.appendChild(rowNo);
generateRow(rowNo, i, "*");//在这一行后面画沙漏的第i行,填充物为*
}
//下半部分
for(var i=1; i<=rowsNum; i++){
var rowNo = document.createElement("div");
rowNo.className="floor";
row2.appendChild(rowNo);
generateRow(rowNo, i, "-");//在这一行后面画沙漏的第i行,填充物为-
}
}
function generateRow(rowNo, i, filler){
var rowSandSum = 2*i-1; //这一行的沙粒总数
var spaceSum = rowWidth-rowSandSum;//这一行的空格总数
var div = null;
var index1 = spaceSum/2;//一半的空格
var index2 = spaceSum/2 + rowSandSum;//一半的空格+全部的沙粒
for(var i=1; i<=rowWidth; i++){
if(i<=index1 || i>index2){//在两个index之外的是·
div = document.createElement("div");
div.innerText="·";
}else {
div = document.createElement("div");
div.innerText=filler;
}
div.className = "Sand";
rowNo.appendChild(div);
}
}
function drawUpperRow(rowSandSum, currRowSandSum){
//rowSandSum这一行最多能容纳的沙粒总数
//currRowSandSum这一行当前的沙粒总数
//rowWidth每一行的图形宽度
var str = "";
var space1 = (rowWidth-rowSandSum)/2; //一半的空格
var space2 = rowWidth - space1; //对称的另一半的空格起始位置
var miss1 = space1+Math.ceil(currRowSandSum/2); //漏掉的沙粒的起始位置
var miss2 = space2-Math.floor(currRowSandSum/2); //漏掉的沙粒的终止位置
for(var i=1; i<=rowWidth; i++){
if(i<=space1 || i>space2){//在两个index之外的是·
str+="·";
}else if(i>space1 && i<=miss1 || i>miss2 && i<=space2){
str+="*";
}else{
str+="-";
}
}
return str;
}
function drawLowerRow(rowSandSum, currRowSandSum){
currRowSandSum = rowSandSum-currRowSandSum;
//rowSandSum这一行最多能容纳的沙粒总数
//currRowSandSum这一行当前的沙粒总数
//rowWidth每一行的图形宽度
var str = "";
var space1 = (rowWidth-rowSandSum)/2; //一半的空格
var space2 = rowWidth - space1; //对称的另一半的空格起始位置
var miss1 = space1+Math.floor(currRowSandSum/2); //漏下的沙粒的起始位置
var miss2 = space2-Math.ceil(currRowSandSum/2); //漏掉的沙粒的终止位置
for(var i=1; i<=rowWidth; i++){
if(i<=space1 || i>space2){//在两个index之外的是·
str+="·";
}else if(i>space1 && i<=miss1 || i>miss2 && i<=space2){
str+="-";
}else{
str+="*";
}
}
return str;
}
</script>
</body>
</html>
2022年04月01日 04点04分


