展开目录
nodejs俄罗斯方块
nodejs
X
陈尼玛的博客
记录开发生涯的踩坑经历,用时间来验证成长
加载中

在控制台打开。

ESC:退出程序 上:直接到底 下:加速下落 左右:移动 空格:顺时针旋转

let draw=(o)=>{
  let s=process.stdout
  s.cursorTo(0, 0)
  s.clearScreenDown()
  o.map(a=>s.write(a.join('')+'\n'))
}
let rotate90=(a, r=-1)=>{
  let n=a.length, b=[]
  for(let i=0; i<n; i++) {
    for(let j=0; j<n; j++) {
      let [_i, _j]=r===-1? [n-j-1, i]: [j, n-i-1]
      b[_i]=b[_i]||[]
      b[_i][_j]=a[i][j]
    }
  }
  return b
}
let fill=(y, x)=>[...new Array(y)].map(_=>[...new Array(x||y)].map(_=>0))
let rnd=n=>Math.random()*n|0
let fill_map=(map, shape)=>{
  let q=[]
  for(let i=0; i<4; i++) {
    for(let j=0; j<4; j++) {
      if(!shape[i][j]) continue
      if(j+px<0 || j+px>=X) return 0
      if(i+py<0 || i+py>=Y || map[i+py][j+px]) return -1
      if(shape[i][j]) q.push([i, j])
    }
  }
  q.map(([i, j])=>map[i+py][j+px]=shape[i][j])
  return map
}

let clean_map=_=>{
  let n=0
  for(let i=map.length; i--; ) {
    if(map[i].indexOf(0)!==-1) continue
    map.splice(i, 1)
    n++
  }
  map=fill(n, X).concat(map)
  if(map[2].indexOf(1)>-1) gameover=true
  if(!n) return
  c+=n
  score+=Math.ceil(Math.pow(5, n-1))
}
let test_map=_=>{
  let r_map=copy(map)
  r_map=fill_map(r_map, p)
  return r_map
}
let draw_map=(r_map)=>{
  if(r_map===0) ;else if(r_map===-1) {
    px=undefined
    map=map_t
    fn()
  }else{
    map_t=copy(r_map)
    draw([
      '='.repeat(X).split(''),
      ...map_t.slice(2, map_t.length).map(t=>t.map(o=>o?' ':'#')),
      '='.repeat(X).split(''),
      ['score: ', score],
      ['clear: ', c],
      gameover? ['-- gameover --']: [],
    ])
  }
}

let copy=m=>[...new Array(m.length)].map((_, i)=>m[i].slice(0, m[i].length))

const X=10, Y=16
/**
 1 2 3 4
 5 6 7 8
 9 a b c
 d e f g
 */
const SHAPES=[
  '1234',
  '7abc',
  '9ab7',
  '6abc',
  '376a',
  '267b',
  '67ab',
].map((o)=>{
  let n=4, r=fill(n)
  o.split('').map(a=>{
    let g=parseInt(a, 16)-1
    r[Math.floor(g/n)][g%n]=1
  })
  return r
})

const stdin=process.stdin
stdin.setRawMode(true)
stdin.resume()
stdin.on('data', c=>{
  let o=c[c.length-1], b, r_map
  if(o===27) process.exit()
  if(o===32) {
    let n=px<X/2?1:-1, h=0
    for(let i=0; i<4; i++) {
      p=rotate90(p, 1)
      let r=test_map()
      if(r!==-1 && r!==0) {
        h=0
        break
      }
      p=rotate90(p, -1)
      px+=n
      h++
    }
    px-=h*n
  }
  if(o===68) px--, b=_=>px++
  if(o===67) px++, b=_=>px--
  if(o===66) py++, b=_=>py--
  if(o===65) {
    for(;++py;) {
      r_map=test_map()
      if(r_map===0 || r_map===-1) break
    }
    py--
  }
  r_map=test_map()
  if(r_map===0 || r_map===-1) b && b()
  else draw_map(r_map)
})
let px, py, p, map=fill(Y, X), map_t, score=0, c=0, gameover, fn=_=>{
  if(gameover) {
    clearInterval(tt)
    process.exit()
  }else if(px===undefined) {
    px=X/2-2
    py=0
    p=SHAPES[rnd(SHAPES.length)]
    for(let i=rnd(4); i--; ) p=rotate90(p)
    clean_map()
  }else{
    py++
  }
  draw_map(test_map())
}
fn()
let tt=setInterval(fn, 5e2)

相关文档

  1. 记一次nodejs内存泄漏的排查经历

  2. nodejs 长连接

  3. npm包命令行调用

  4. nodejs本地双向代理 端口转发

  5. nodejs socks5

  6. webrtc服务搭建

  7. ssl 证书生成方式

  8. nodejs建立多级目录

  9. linux 上配置node路径

  10. nodejs处理gb2312编码

  11. nodejs遍历文件夹

  12. 读取Blob的内容实体

  13. nodejs那恶心的stream.Readable

  14. Promise复习,nodejs异步建立多级目录

  15. 异步并发也要保证原子性

  16. 简易命令行解析器

  17. Promise才是javascript的正统队列

  18. callback => Promise.then

  19. 简易转义字符转实体字符方法

随便看看

  1. sqlite 查看table的构建语句

  2. windows电脑防止自动休眠

  3. 定长消息队列读写优化

  4. css3自定义滚动条样式

  5. 华为等国产手机rem宽度超过实际宽度

  6. mac 终端运行后台程序如何在终端关闭时继续运行

  7. npm远程服务器某些配置不兼容代理的解决办法

  8. nodejs socks5

  9. 树莓派实现用pi用户自动登录

  10. git删除远程分支

  11. python 用摄像头拍照并写入文件

  12. 判断变量是否 0 或者 '0'

  13. webrtc服务搭建

  14. dd备份/还原

  15. git 设置代理服务器

  16. ie8上Image.onload不触发问题

  17. 随机取某个概率区间的代码

  18. 配置mysql ssl连接

畅言模块加载中