找回密码
 马上注册

QQ登录

只需一步,快速开始

查看: 13308|回复: 15

经典游戏再现——俄罗斯方块第一代( 第二版已发布)

[复制链接]
发表于 2016-8-8 22:14:19 | 显示全部楼层 |阅读模式
本帖最后由 hello怪 于 2016-9-24 14:23 编辑

之前看过大神用nxc写的俄罗斯方块,但相对而言比较简单

因此我想到,能不能用nxt的诸多传感器增强人机交互性呢?

嗯,现在开始试着用Java se来实现,预计很快就能实现用lejos nxj做俄罗斯方块了
站内视频似乎挂了,直接上优酷连接:
http://v.youku.com/v_show/id_XMTY4NjU2MzQyMA==.html?x=1

(妈妈说把视频放一楼就有更多人看了。。。(第二版视频:)
先放出java se的实验版:




捕获.PNG
捕获1.PNG
捕获2.PNG
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
 楼主| 发表于 2016-8-15 23:01:09 | 显示全部楼层
本帖最后由 hello怪 于 2016-8-16 10:48 编辑

(自己先占一楼)图片放出:
DSC08312.jpg
DSC08313.jpg
DSC08314.jpg
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复 1 0

使用道具 举报

 楼主| 发表于 2016-8-10 10:25:49 | 显示全部楼层
咦没人用lejos吗。。。。为啥这么冷清勒。。。。算了我直接把代码贴出来
首先是主类Russian.java
控制总的游戏进程
  1. package ro;

  2. import lejos.nxt.Button;
  3. import lejos.nxt.Button.*;

  4. public class Russian {
  5.        
  6.         static GameStatue gs = new GameStatue();
  7.        
  8.         MyPanel mp = new MyPanel(gs);
  9.        
  10.         public Russian(){
  11.                
  12.                 //Events
  13.                 Button.ENTER.addButtonListener(mp);
  14.                 Button.ESCAPE.addButtonListener(mp);
  15.                 Button.LEFT.addButtonListener(mp);
  16.                 Button.RIGHT.addButtonListener(mp);
  17.                
  18.         }

  19.         private void gameStart(){
  20.                
  21.         }
  22.        
  23.         private void gameRun(){
  24.                 while(true){
  25.                         try{                                        //avoid overHeat
  26.                                 Thread.sleep(1000);
  27.                         }catch(Exception e){
  28.                                 e.printStackTrace();
  29.                         }
  30.                         while(gs.isGameRunning){
  31.                                 try{                                        //wait the actions
  32.                                         Thread.sleep(1000);
  33.                                 }catch(Exception e){
  34.                                         e.printStackTrace();
  35.                                 }
  36.                                
  37.                                 if(!gs.tryBlockDown()){
  38.                                         gs.locateBlock();
  39.                                         gs.tryRemoveRow();
  40.                                         if(gs.isGameOver()){
  41.                                                 System.out.println("GAME OVER!!");
  42.                                                 gs.isGameRunning = false;
  43.                                                 return;
  44.                                         }
  45.                                         gs.refresh();
  46.                                 }mp.paint();
  47.                                
  48.                         }
  49.                 }
  50.         }
  51.        
  52.         private void gameEnd(){
  53.                 Button.waitForAnyPress(5000);
  54.         }
  55.        
  56.         public static void main(String[] args) {
  57.                 Russian r = new Russian();
  58.                 r.gameStart();
  59.                 r.gameRun();
  60.                 r.gameEnd();
  61.         }

  62. }
复制代码
然后是画图类MyPanel.java,实现在LCD上的动画效果
  1. package ro;

  2. import lejos.nxt.Button;
  3. import lejos.nxt.ButtonListener;
  4. import lejos.nxt.LCD;

  5. import javax.microedition.lcdui.*;

  6. public class MyPanel implements ButtonListener{
  7.        
  8.         GameStatue gs;
  9.         Graphics g = new Graphics();
  10.        
  11.         public MyPanel(GameStatue g){                        //set Game Statue
  12.                 gs = g;
  13.         }
  14.        
  15.         public void paint(){                        //Draw
  16.                
  17.                 LCD.clear();//refresh
  18.                
  19.                 g.setFont(Font.getFont(0,0,Font.SIZE_SMALL));
  20.                
  21.                 //Standard Line
  22.                 g.drawLine(64, 0, 64, 64);
  23.                
  24.                 //moving Blocks
  25.                 for(int iy=0; iy<4; iy++){
  26.                         for(int ix=0; ix<4; ix++){
  27.                                 if(gs.currentMap[ix][iy]){
  28.                                         g.fillRect((gs.blockX+ix)*8, (gs.blockY+iy-4)*8, 8,8);
  29.                                 }
  30.                         }
  31.                 }
  32.                 //next Blocks
  33.                 g.drawString("NEXT:", 64+2, 16, Graphics.LEFT|Graphics.TOP);
  34.                 for(int iy=0; iy<4; iy++){
  35.                         for(int ix=0; ix<4; ix++){
  36.                                 if(gs.nextMap[ix][iy]){
  37.                                         g.fillRect((ix)*6+gs.WIDTH*8+2, (iy)*6+24+2, 6,6);
  38.                                 }
  39.                         }
  40.                 }
  41.                
  42.                
  43.                 //stationary Blocks
  44.                 for(int iy=4; iy<gs.HEIGHT+4; iy++){
  45.                         for(int ix=0; ix<gs.WIDTH; ix++){
  46.                                 if(gs.isBlockExist[ix][iy]){
  47.                                         g.fillRect(ix*8,(iy-4)*8, 8,8);
  48.                                 }
  49.                         }
  50.                 }
  51.                
  52.                 //Display score & etc
  53.                 g.drawString("SCORE:", 64+2, 0, Graphics.LEFT|Graphics.TOP);
  54.                 g.drawString(String.valueOf(gs.score),64+2,8,Graphics.LEFT|Graphics.TOP);
  55.         }
  56.        
  57.         @Override
  58.         public void buttonPressed(Button b) {
  59.                
  60.                 if(Button.readButtons() == Button.ID_LEFT+Button.ID_RIGHT){
  61.                         gs.gameStartOrPause();
  62.                 }else{
  63.                         switch(b.getId()){
  64.                         case Button.ID_LEFT:
  65.                                 gs.tryBlockLeft();
  66.                                 break;
  67.                         case Button.ID_RIGHT:
  68.                                 gs.tryBlockRight();
  69.                                 break;
  70.                         case Button.ID_ENTER:
  71.                                 gs.tryBlockRotate();
  72.                                 break;
  73.                         case Button.ID_ESCAPE:
  74.                                 gs.tryBlockDown();
  75.                                 break;
  76.                         default:
  77.                         }
  78.                 }
  79.                 paint();
  80.                
  81.         }
  82.         @Override
  83.         public void buttonReleased(Button b) {
  84.                 // TODO Auto-generated method stub
  85.         }
  86. }
复制代码
再然后是控制类GameStatue, 存储游戏的大部分数据以及控制方块移动,旋转的方法
  1. package ro;

  2. public class GameStatue {
  3.        
  4.         static final int WIDTH = 8,HEIGHT = 8;
  5.        
  6.         boolean isGameRunning;
  7.         int score;
  8.        
  9.         int blockX=2, blockY = 0;
  10.        
  11.         int currentBlockType, currentBlockRotation;
  12.         int nextBlockType, nextBlockRotation;
  13.        
  14.         boolean currentMap[][] = new boolean[4][4];
  15.         boolean nextMap[][] = new boolean[4][4];
  16.        
  17.         boolean isBlockExist[][] = new boolean[WIDTH][HEIGHT+4];
  18.        
  19.         public GameStatue(){
  20.                
  21.                
  22.                 score = 0;
  23.                 isGameRunning = true;
  24.                
  25.                 currentBlockType = 5;
  26.                 currentBlockRotation = 0;                        //flash now and then
  27.                
  28.                 loadCurrentMap();
  29.                
  30.                 loadRandomNextMap();
  31.         }
  32.         private void loadCurrentMap(){
  33.                
  34.                 int array = 0x8000;
  35.                 for(int iy=0; iy<4; iy++){
  36.                         for(int ix=0; ix<4; ix++){
  37.                                 currentMap[ix][iy] =(Blocks.map[currentBlockType][currentBlockRotation] & array) !=0;
  38.                                 array = array >> 1;
  39.                         }
  40.                 }
  41.         }
  42.        
  43.         private void loadRandomNextMap(){
  44.                 nextBlockType = (int)(Math.random()*7);
  45.                 nextBlockRotation = (int)(Math.random()*4);
  46.                 int array = 0x8000;
  47.                 for(int iy=0; iy<4; iy++){
  48.                         for(int ix=0; ix<4; ix++){
  49.                                 nextMap[ix][iy] = (Blocks.map[nextBlockType][nextBlockRotation] & array) !=0;
  50.                                 array = array >> 1;
  51.                         }
  52.                 }
  53.         }
  54.        
  55.         public void refresh(){
  56.                
  57.                
  58.                 blockX = 2;
  59.                 blockY = 0;
  60.                 currentBlockType = nextBlockType;
  61.                 currentBlockRotation = nextBlockRotation;
  62.                 loadCurrentMap();
  63.                 loadRandomNextMap();
  64.         }
  65.        
  66.         public boolean tryBlockDown(){
  67.                 //&&&&&&&&&&&&&
  68.                
  69.                
  70.                 for(int ia=0; ia<4; ia++){//x
  71.                         for(int ib=3; ib>=0; ib--){//y
  72.                                 if(currentMap[ia][ib]){
  73.                                         if(blockY+ib-4+1>=HEIGHT){
  74.                                                 return false;
  75.                                         }
  76.                                         if(isBlockExist[blockX+ia][blockY+ib+1])return false;
  77.                                 }
  78.                         }
  79.                 }
  80.                
  81.                 blockY++;
  82.                
  83.                 return true;                        //return whether the block can be moved down
  84.         }
  85.        
  86.         public void tryBlockLeft(){
  87.                
  88.                 for(int ia=0; ia<4; ia++){//y
  89.                         for(int ib=0; ib<4; ib++){
  90.                                 if(currentMap[ib][ia]){
  91.                                         if(blockX+ib-1<0) return;
  92.                                         if(isBlockExist[blockX+ib-1][ia])return;
  93.                                 }
  94.                         }
  95.                 }
  96.                 blockX--;
  97.         }
  98.        
  99.         public void tryBlockRight(){
  100.                
  101.                 for(int ia=0; ia<4; ia++){//y
  102.                         for(int ib=3; ib>=0; ib--){
  103.                                 if(currentMap[ib][ia]){
  104.                                         if(blockX+ib+1>WIDTH-1) return;
  105.                                         if(isBlockExist[blockX+ib+1][ia])return;
  106.                                 }
  107.                         }
  108.                 }
  109.                 blockX++;
  110.         }
  111.        
  112.         public void tryBlockRotate(){
  113.                 int rotated;
  114.                 if(currentBlockRotation == 3)rotated = 0;
  115.                 else rotated = currentBlockRotation + 1;
  116.                
  117.                 boolean rotateMap[][] = new boolean[4][4];
  118.                 int array = 0x8000;
  119.                 for(int iy=0; iy<4; iy++){
  120.                         for(int ix=0; ix<4; ix++){
  121.                                 rotateMap[ix][iy] = (Blocks.map[currentBlockType][rotated] & array) !=0;
  122.                                 if(rotateMap[ix][iy]){
  123.                                         if(ix+blockX<0)return;
  124.                                         if(isBlockExist[ix+blockX][iy+blockY])return;
  125.                                 }
  126.                                 array = array >> 1;
  127.                         }
  128.                 }
  129.                 for(int ia=0; ia<4; ia++){
  130.                         for(int ib=0; ib<4; ib++){
  131.                                 currentMap[ia][ib] = (boolean)rotateMap[ia][ib];
  132.                         }
  133.                 }
  134.                 currentBlockRotation = rotated;
  135.                
  136.         }
  137.        
  138.         public void gameStartOrPause(){
  139.                 isGameRunning = !isGameRunning;
  140.                
  141.         }
  142.        
  143.         public void locateBlock(){
  144.                
  145.                 for(int iy=0; iy<4; iy++){
  146.                         for(int ix=0; ix<4; ix++){
  147.                                 if(currentMap[ix][iy]){
  148.                                         isBlockExist[blockX+ix][blockY+iy] = true;
  149.                                 }
  150.                         }
  151.                 }
  152.         }
  153.        
  154.         public int tryRemoveRow(){
  155.                 int removedRows = 0;
  156.                
  157.                 for(int iy=HEIGHT-1+4; iy>4; iy--){
  158.                         for(int ix=0; ix<WIDTH; ix++){
  159.                                 if(!isBlockExist[ix][iy]){
  160.                                         break;
  161.                                 }
  162.                                 if(ix==WIDTH-1){
  163.                                         removedRows++;
  164.                                         for(int ia=iy; ia>4;ia--){//y from down to up
  165.                                                 for(int ib=0; ib<WIDTH; ib++){
  166.                                                         isBlockExist[ib][ia] = isBlockExist[ib][ia-1];
  167.                                                 }
  168.                                         }
  169.                                         iy++;
  170.                                 }
  171.                         }
  172.                 }
  173.                
  174.                
  175.                 score+=10*removedRows;
  176.                
  177.                 //&&&&&&&&&&&&&&&&&&&&
  178.                 return removedRows;                        //return the number of removed Lines
  179.         }
  180.        
  181.         public boolean isGameOver(){
  182.                 for(int ix=0; ix<WIDTH; ix++){
  183.                         if(isBlockExist[ix][4])return true;
  184.                 }
  185.                 //&&&&&&&&&&&&&
  186.                 return false;                //check whether the game is over
  187.         }

  188. }
复制代码
最后是存储方块形状的类Blocks,用十六位的int来代表4*4棋盘上的方块数据
  1. package ro;

  2. public class Blocks {
  3.         //block version,rotation
  4.         public static final int map[][] = {
  5.                         {0x06c0,0x0462,0x06c0,0x0462},//反之字
  6.                         {0x0c60,0x04c8,0x0c60,0x04c8},//之字
  7.                         {0x0660,0x0660,0x0660,0x0660},//正方形
  8.                         {0x08e0,0x0644,0x00e2,0x044c},//左手拐
  9.                         {0x02e0,0x0446,0x00e8,0x0c44},//右手拐
  10.                         {0x4444,0x00f0,0x4444,0x00f0},//长条
  11.                         {0x04e0,0x0464,0x00e4,0x04c4}//三角
  12.         };
  13. }
复制代码
显而易见我在Java se上的代码没怎么改就直接搬过来了。嗯,所以说Java的可移植性比G语言强无限大倍(G语言的可移植性大概是零吧。。。)

想转行lejos Java 的快上车啊啊啊!!

如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复 1 0

使用道具 举报

 楼主| 发表于 2016-8-8 22:57:47 | 显示全部楼层
本帖最后由 hello怪 于 2016-8-15 22:59 编辑

附加jar文件以及java源代码:RussianBlocks
重要#########第一代第二版已发布,详情见9楼

RussianBlocks.rar

15.67 KB, 下载次数: 109

如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2016-8-9 16:29:25 | 显示全部楼层
本帖最后由 hello怪 于 2016-8-9 16:44 编辑

当当当当!历经一天时间,nxt版本写完了!

其实我大部分代码全是从Java SE版俄罗斯方块上直接搬过来的(笑)
上源码:

上图上视频
(视频是没有声音的,不用调大声音了:-):




DSC08306.jpg

降落前

降落前

消除,得分啦

消除,得分啦

LEGO_project.rar

38.44 KB, 下载次数: 65

如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2016-8-10 13:28:35 | 显示全部楼层
附带代码

RussianBlocks.rar

18.31 KB, 下载次数: 30

如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2016-8-10 13:29:01 | 显示全部楼层
牛B
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2016-8-10 16:33:33 | 显示全部楼层
请问现在 ev3 支持第三方的编程有哪些? 除了lejos.
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2016-8-11 09:18:26 | 显示全部楼层
lwl5633 发表于 2016-8-10 16:33
请问现在 ev3 支持第三方的编程有哪些? 除了lejos.

嗯,这个我还真不太清楚,不过似乎labview, matlab也支持ev3编程(如果把labview算在内的话)

可能在可移植性,功能和可扩展度方面只有matlab能和lejos比拼吧。。。(笑)
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2016-8-15 22:56:08 | 显示全部楼层
第一代第二版登场啦!

我进行了大规模的更新和bug修复:


横向的屏幕不够经典?我们也深有此感!于是,nxt从此横过来用!竖着屏幕玩才是王道!

#8*8的方格数怎么够?要玩就玩大个的!版面数已由8*8升级到8*10!更多可能与机会!

##全新的BGM功能火热登场啦!!”原汁原味“的背景音乐让你全身燃起来!

###最新的触控传感器控制了左右移动!向左为一号触摸传感器,向右为二号传感器,手感爆棚!!

####不想等待方块缓慢下落?用nxt左键即可让他们极速落下!原有的加速下落功能已移至灰色退出键!

#####总有激情一刻,总有短暂离开——nxt右键最懂你!全新的暂停/继续功能,让你短暂抽身也无妨!

######俄罗斯方块是智者的战场,同时消去多行更应赢得奖赏!分数机能全新改版,消去一行得十分,两行得40分,三行90分,四行160分!让分数像火箭一样飞升!

#######便捷的消息功能,让您实时获取分数奖励情况!


嘛,写了这么多,总而言之就一句话:更新太多啦!自己试去吧!


(打包的文件价值一乐币,以希望大家多多发言发干货,谢谢大家的支持啦!

Tetris.rar

37.07 KB, 下载次数: 39

如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2016-8-16 14:45:17 | 显示全部楼层
视频放出:
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2016-8-18 09:40:49 | 显示全部楼层
请允许我发一个 吊 字~
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2016-8-19 17:00:30 | 显示全部楼层
强顶
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2017-2-16 17:01:03 | 显示全部楼层
今天才看到,赞一个
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2017-2-17 08:42:31 | 显示全部楼层
学习。。。。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

手机版|中文乐高 ( 桂ICP备13001575号-7 )

GMT+8, 2024-11-16 01:37 , Processed in 0.300266 second(s), 25 queries .

Powered by Discuz! X3.5

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表