java版 俄罗斯方块

一个java 版本的俄罗斯方块。先说小弟java水平尚属初级水平所有见笑了 有些bug,不想继续修改了,但是所有的基本功能都实现了。如果有需要的,可以参考一下

方块构造类

package com;

import java.util.Random;

public class Fangk {
private String[][] fklist = {
{"0000111100000000","0100010001000100","0000111100000000","0100010001000100"},
{"0000011001100000","0000011001100000","0000011001100000","0000011001100000"},
{"0000001001110000","0010001100100000","0000011100100000","0010011000100000"},
{"0010011001000000","0000011000110000","0010011001000000","0000011000110000"},
{"0100011000100000","0000001101100000","0100011000100000","0000001101100000"},
{"0000010001100010","0000011011000000","0000010001100010","0000011011000000"},
{"0000011101000000","0110001000100000","0000000101110000","0000010001000110"},
};
private int pcl;
private int scl;
private int lpcl;
private int lscl;

public int[] Fack(){
int[] a = new int [16];
Fangk ab = new Fangk();
Random rand = new Random();
lpcl = rand.nextInt(7);
lscl = rand.nextInt(3);
// System.out.println("fuck"+pcl+"ou"+scl);
for(int i=0;i<16;i++){
if((ab.fklist[lpcl][lscl].charAt(i)+"").equals("1"))a[i]=1;
else a[i]=0;
}
return a;
}
public int [] getNext(){
int[] a = new int [16];
Fangk ab = new Fangk();
int scl1;
//如果不是 該行的最後一個
if(scl!=3)scl1=scl+1;
else scl1=0;
for(int i=0;i<16;i++){
if((ab.fklist[pcl][scl1].charAt(i)+"").equals("1"))a[i]=1;
else a[i]=0;
}
return a;
}
public int getScl() {
return scl;
}
public void setScl() {
if(scl!=3)scl=scl+1;
else scl=0;
}
public void setScl1(int scl) {
this.scl =scl;
}

public int getLpcl() {
return lpcl;
}
public void setLpcl(int lpcl) {
this.lpcl = lpcl;
}
public int getLscl() {
return lscl;
}
public void setLscl(int lscl) {
this.lscl = lscl;
}
public int getPcl() {
return pcl;
}
public void setPcl(int pcl) {
this.pcl = pcl;
}

}


主类(其中 包括内部控制方块类 )


package com;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

@SuppressWarnings("serial")
public class Table extends JFrame {
MyJpanel[][] pan = new MyJpanel[23][15];
MyJpanel[][] next=new MyJpanel[4][4];
JButton button = new JButton("开始/暂停");
JButton button2 = new JButton("新游戏");
JButton button1 = new JButton("重来一回");
TextField curScore = new TextField();
Control tt1 = new Control();
int pause=0; /*用来判断继续或者暂停*/
int change =0;
int nowcur=5; //默认从 第5 列出来, (15+1-4)/2
int nowline =0; //默认当前在第一行
int lastline ; //用来记录当前下落方块的最下一个小方块的下标
int stotime =150; //方块下落时间间隔
int move =0; // 按下 左右移动时有停顿时间
int brg =0; //开始
JPanel panel1 = new JPanel();
int[] aa; //记录当前方块数据
int[] bb; //记录下一个方块数据
static int score = 0;
JPanel panel = new JPanel();
@SuppressWarnings("deprecation")
public Table() {
/**
* 以下完成页面布局
* */
JFrame mainFrame = new JFrame();

mainFrame.setLayout(null);
mainFrame.add(panel);
panel.setBounds(0, 0, 298, 720);
mainFrame.add(panel1);
panel1.setBounds(300, 0, 500, 720);
for (int i = 0; i < 23; i++) {
for (int j = 0; j < 15; j++) {
pan[i][j] = new MyJpanel();
panel1.add(pan[i][j]);
}
}
for(int i=0;i<4;i++){
for(int j =0;j<4;j++){
next[i][j]=new MyJpanel();
panel.add(next[i][j]);
next[i][j].setColor(Color.blue);
next[i][j].setBounds(50+(31*j),250+28*i, 30, 30);
// next[i][j].light_on();
}
}
panel.setBackground(Color.YELLOW);
Label levlab = new Label("当前分数");
Label curlev = new Label("当前等级");
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("文件");
JMenuItem saveItem = new JMenuItem("保存(C)",'C');
JMenuItem openItem = new JMenuItem("载入(I)",'I');
JMenuItem exitItem = new JMenuItem("退出(O)",'O');
saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,InputEvent.CTRL_MASK));
openItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, InputEvent.CTRL_MASK));
exitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));
saveItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
tt1.save();
}
});
openItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
try {
tt1.load();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
fileMenu.add(openItem);
fileMenu.add(saveItem);
fileMenu.add(exitItem);
menuBar.add(fileMenu);
mainFrame.setJMenuBar(menuBar);
final JComboBox scolist = new JComboBox();
scolist.addItem("初入江湖");
scolist.addItem("历经沧桑");
scolist.addItem("得道成仙");
curScore.setEditable(false);
curScore.setText("0");
panel.setLayout(null);
scolist.setBounds(30, 100, 60, 20);
levlab.setBounds(30, 100, 60, 20);
curlev.setBounds(30, 140, 60, 20);
scolist.setBounds(90, 140, 100, 20);
curScore.setBounds(90, 100, 100, 20);
button2.setBounds(30, 450, 80, 25);
button.setBounds(120, 450, 80, 25);
button1.setBounds(210, 450, 60, 25);
panel1.setLayout(new GridLayout(24, 15, 2, 2));
panel.add(button);
panel.add(button2);
panel.add(levlab);
panel.add(button1);
panel.add(scolist);
panel.add(curlev);
panel.add(curScore);
mainFrame.setSize(800, 720+25);
mainFrame.setResizable(false);
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// this.addKeyListener(new contro());
mainFrame.setTitle("失败的作品");
mainFrame.show();
// panel1.repaint();
/**
* 以下完成事件监听器
* */
scolist.addKeyListener(new contro()); //加上这一行 可以随时改变方块下落的速度
button.addKeyListener(new contro());
button1.addActionListener(new bot());
button.addActionListener(new bot());
button2.addActionListener(new bot());
scolist.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (scolist.getSelectedItem() == "历经沧桑") {
stotime =50;
}
if (scolist.getSelectedItem() == "得道成仙") {
stotime =1150;
synchronized(tt1){
tt1.notify();
}
}
}
});
}
// 按钮事件
public class bot implements ActionListener{
public void actionPerformed(ActionEvent e) {
if(e.getSource()==button){ //点击 开始/暂停 按钮
pause = 1-pause;
brg = 1;
synchronized(tt1){
tt1.notify();
}
}
if(e.getSource()==button1){ //重新开始

}
if(e.getSource()==button2){ //新游戏
synchronized(tt1){
pause = 1;
synchronized(tt1){
tt1.notify();
}
}
}
}

}
// 键盘事件
public class contro implements KeyListener{
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==38){ //按下上键
tt1.change();
}
if(e.getKeyCode()==40){ //按下下键;
stotime =20;
}
if(e.getKeyCode()==37){ //按下左键
tt1.left();
}
if(e.getKeyCode()==39){ //按下右键
tt1.right();
}

}
public void keyReleased(KeyEvent e) {
if(e.getKeyCode()==40){ //按下下键
System.out.println("下家");
stotime =150;
}
}

public void keyTyped(KeyEvent e) {
}

}


/**
* @param args
*/
public static void main(String[] args) {
Table table = new Table();
}

public class Control extends Thread {
boolean rel =true; //用以表示是否还可以移动
boolean rer =true; //用以表示是否还可以移动
Fangk fk = new Fangk();
int firsc,lastc;
int firsl,lastl;
Control() {
System.out.print("========================");
start();
}
/**
* 方块下落
* */
@SuppressWarnings("deprecation")
public void run() {
while(true){
if(brg ==0){
aa =fk.Fack();
}else
aa=bb;
fk.setScl1(fk.getLscl());
fk.setPcl(fk.getLpcl());
bb = fk.Fack();
firsc = this.getfirstc(aa);
lastc = this.getlastc(aa);
nowcur = 6;
rel =true;
rer =true;
firsl = this.getfirstl(aa);
lastline= 0;
for (int i =0;i< 23;i++) {
if(pause==0) //检查是否按下暂停键
synchronized( this ){ //必须放在同步里面,否则抛出异常
try {
this.wait();}catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int r=0;r<4;r++){
for(int j =0;j<4;j++){
next[r][j].light_off();
}
}
for(int r=0;r<4;r++){
for(int j =0;j<4;j++){
if(bb[4*r+j]==1)
next[r][j].light_on();
}
}
if(this.gettop()<=0){
System.out.println("游戏结束");
tt1.stop();
}
if(move==1) //检查是否左右移动
synchronized( this ){ //必须放在同步里面,否则抛出异常
try {
Thread.sleep(stotime);
move =0;}catch (InterruptedException e) {
e.printStackTrace();
}
}
if(change==1) //检查是否按下变形
synchronized( this ){ //必须放在同步里面,否则抛出异常
try {
Thread.sleep(stotime);
change =0;}catch (InterruptedException e) {
e.printStackTrace();
}
}
// 方块的下落的实现
for (int x = 0; x < 23; x++) {
for (int j = 0; j < 15; j++) {
pan[i][j].setIfmove(0);
}
}
rel =false;
rer=false;
int x = godown(i);
if(x==0)break;
lastline = i;
rel=true;
rer=true;
try {
Thread.sleep(stotime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lose();
}
}
//实现左移
public int left(){
if(nowcur>0&&rel){ //re用以作为边界,否则抛出异常
for(int i=nowcur;i<=nowcur+3-lastc-firsc;i++){
for(int j=lastline;j>=0;j--){
if(pan[j][i].getIfmove()==1&&pan[j][i-1].getIffill()==1&&pan[j][i-1].getIfmove()!=1){
return 0;
}
}
}
rer=false;
move =1;
for(int i=nowcur;i<=nowcur+3-lastc-firsc;i++){
for(int j=lastline;j>=0;j--){
if(pan[j][i].getIfmove()==1){
pan[j][i-1].light_on();
pan[j][i].light_off();
}
}
}
move =1;
nowcur = nowcur-1;
}
rer =true;
return 1;

}
//实现右移
public int right(){
if((nowcur<11+firsc+lastc)&&rer){
for(int i=3-firsc-lastc+nowcur;i>=nowcur;i--){
for(int j=lastline;j>=0;j--){
if(pan[j][i].getIfmove()==1&&pan[j][i+1].getIffill()==1&&pan[j][i+1].getIfmove()!=1){
return 0;
}
}
}
rel=false;
move =1;
for(int i=3-firsc-lastc+nowcur;i>=nowcur;i--){
for(int j=lastline;j>=0;j--){
if(pan[j][i].getIfmove()==1){
pan[j][i+1].light_on();
pan[j][i].light_off();
}
}
}
move =1;
nowcur = nowcur+1;
};
rel = true;
return 1;
}
/**此方法用以判断新产生的方块最下面一行的位置,以实现全部下落*/
public int getfirstl(int[] a){
int flag = 0;
int i;
for(i=3;i>=0;i--)
for(int j =0;j<4;j++){
if(a[i*4+j]==1)
return i;
}
return 1;
}

/**此方法用以判断新产生的方块最左边的位置,以实现左右移动*/
public int getfirstc(int[] a){
int i;
for(i=0;i<4;i++)
for(int j =0;j<4;j++){
if(a[j*4+i]==1)
return i;
}
return 1;
}
/**此方法用以判断新产生的方块最右边的位置,以实现左右移动*/
public int getlastc(int[] a){
int i;
for(i=3;i>=0;i--)
for(int j =0;j<4;j++){
if(a[j*4+i]==1)
return 3-i;
}
return 1;
}
/**此方法实现方块的直线下落*/
public int godown(int i){
if(i>0){
for (int m=i; m>0; m--) {
for (int k=nowcur; k <=3-firsc-lastc+nowcur; k++){//方块初始化大小为4*4
if (pan[m-1][k].getIfmove()==1
&&pan[m][k].getIffill()==1)
return 0;
}
for (int k=nowcur; k <=3-firsc-lastc+nowcur; k++) {//方块初始化大小为4*4
if (pan[m-1][k].getIffill() == 1&&pan[m-1][k].getIfmove()==1){
if(i>4){ //根据下面 k-r >=0 取得 k 的范围
//判断左边是否有限制
for(int r=1;r<=k-nowcur;r++){ //k -nowcur 判断该方块左边有几个
for(int t=1;t<4;t++){ // 判断左边的上方数据,t<=firsl
if(pan[m-t][k-r].getIfmove()!=1&&pan[m-t][k-r].getIffill()==1&&pan[m-t-1][k-r].getIfmove()==1)
return 0;}
}
//判断右边是否有限制
for(int r=1;r<4-k+nowcur-firsc-lastc;r++){
for(int t=1;t<4;t++){ // 判断左边的上方数据,t<=firsl -1
if(pan[m-t][k+r].getIfmove()!=1&&pan[m-t][k+r].getIffill()==1&&pan[m-t-1][k+r].getIfmove()==1)
return 0;}
}
}
pan[m-1][k].light_off();
pan[m][k].light_on();
}
}
}
}
if (i <firsl+1) { //方块当前尚未完全出来
for (int j = firsc; j <4; j++) {
if (aa[(firsl-i)*4+j]== 1) {//每个方块的状态定义为16个2进制数
pan[0][nowcur+j-firsc].light_on();
}
}
}
return 1;
}
/**此方法实现方块的变形*/
public int change(){
int[] bb = fk.getNext();
int cfirsc = this.getfirstc(bb);
int cfirsl =this.getfirstl(bb);
int clastc = this.getlastc(bb);
//此处循环 算法有待修改,此处把lastline>=4,是为了避免377行的数组越界,也可以通过此处实现 条子在出来的时候变形的数组越界
//当前方块右边的间隙 必须能容纳变形后的方块 由14-nowcur>=4-cfirsc-clastc-firsc-1 计算
if(lastline>=3&&nowcur>=firsc&&11-nowcur+firsc+cfirsc+clastc>=0&&firsc+14-nowcur>=3){
// 判断左边和右边的边界
for(int i =lastline;i>=lastline-3;i--){
for(int m =1;m<=firsc;m++){
if(pan[i][nowcur -m].getIffill()==1)
return 0;
}
for(int m=nowcur;m<=nowcur+3-cfirsc-clastc-firsc;m++){
if(pan[i][m].getIffill()==1&&pan[i][m].getIfmove()!=1)
return 0;
}
}
for(int i =lastline;i>=lastline-3;i--){
change =1;
for(int j=nowcur;j<=3-firsc-lastc+nowcur;j++){
if(pan[i][j].getIfmove()==1)pan[i][j].light_off();
}
if(cfirsl+i-lastline>=0){
for (int j = 0;j<4-clastc; j++) {
if (bb[(cfirsl+i-lastline)*4+j]== 1) {//每个方块的状态定义为16个2进制数
pan[i][nowcur+j-firsc].light_on();
}
}
}
}
//记录当前方块的坐标方块
fk.setScl();
//重定义 变形后方块的属性
nowcur = nowcur -firsc+cfirsc;//重新定义第一个小方块的位置
firsc= cfirsc;
firsl =cfirsl;
lastc =clastc;
}
return 1;
}
/**此方法实现方块的消行*/
public int lose(){
int num =0; //初始化消去的行数为0
int flag;
if(lastline>=3){
flag =1;
int los[] = new int[4]; //用于记录消去的行号
//实现 满格的行消去
for(int i=lastline;i>=lastline-3;i--){
flag =1;
for(int j =0;j<15;j++){
if(pan[i][j].getIffill()!=1){flag=0;break;} //如果该行有空格。直接跳出
}
if(flag==1){
for(int j =0;j<15;j++){
pan[i][j].light_off();
}
los[num]=i;
num++;
}
}
//实现消去行过后上面方块的下落
if(num!=0){
int top =this.gettop();
for(int i=num-1;i>=0;i--){ //总共需循环 num 次。因为消去了num行
for(int l =los[i];l>0;l--){
for(int k=0;k<15;k++){
if(pan[l][k].getIffill()==1){
pan[l][k].light_off();
pan[l+1][k].light_on();
}
}
}
score = score + 100*(i+1);
curScore.setText(""+score);

}
}
}
return 1;
}
/**此方法获取当前方块的最高坐标,实现消行的循环次数该井和 游戏结束功能*/
public int gettop(){
for(int m =0;m<23;m++){
for(int n=0;n<15;n++){
if(pan[m][n].getIffill()==1&&pan[m][n].getIfmove()!=1)return m;
}
}
return 10;
}
/**此方法b保存*/
@SuppressWarnings("static-access")
public int save(){
pause = 0;
JFileChooser fileChoose = new JFileChooser();
fileChoose.setFileSelectionMode(JFileChooser.FILES_ONLY);
int res = fileChoose.showSaveDialog(panel);
if(res==fileChoose.CANCEL_OPTION)return 0;
File fileName = fileChoose.getSelectedFile();
fileName.canWrite();
if(fileName ==null||"".equals(fileName.getName())){
JOptionPane.showMessageDialog(fileChoose, "文件错误","文件错误",JOptionPane.ERROR_MESSAGE);
synchronized(tt1){
tt1.notify();
}
return 0;
}else{
fileName.delete();
try {
FileOutputStream file = new FileOutputStream(fileName);
try {
byte[] by = new byte[23*15];
byte a='0' ;
for(int m=0;m<23;m++){
for(int n =0;n<15;n++){
if(pan[m][n].getIffill()==0)
a = '0';
else if(pan[m][n].getIfmove()==1)a ='2';
else a ='1';
by[m*15+n] =a;
}
}
file.write(by);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
pause = 1;
synchronized(tt1){
tt1.notify();
}
return 1;
}
@SuppressWarnings({ "static-access", "deprecation" })
public int load() throws IOException{
pause = 0;
JFileChooser fileChoose = new JFileChooser();
fileChoose.setFileSelectionMode(JFileChooser.FILES_ONLY);
int res = fileChoose.showOpenDialog(panel);
if(res==fileChoose.CANCEL_OPTION)return 0;
File fileName = fileChoose.getSelectedFile();
fileName.canRead();
if(fileName ==null||"".equals(fileName.getName())){
JOptionPane.showMessageDialog(fileChoose, "文件错误","文件错误",JOptionPane.ERROR_MESSAGE);
synchronized(tt1){
tt1.notify();
}
return 0;
}else{
tt1.stop();
for(int i = 0;i<23;i++){
for(int j = 0;j<15;j++){
pan[i][j].light_off();
}
}
FileReader fr = null;
try {
fr = new FileReader(fileName);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int ch = 0;
int i = 0;
int j = 0;
while((ch = fr.read())!=-1 )
{
j = i /15; //行号
int k = i - j*15;
if(ch=='1'){
pan[j][k].light_on();
pan[j][k].setIfmove(0);
}
if(ch=='2'){
pan[j][k].light_on();
}
i++;
}
// pause =1;
tt1 = new Control();
}
return 1;
}
}
}


大家根据把 文件名改成正确的就可以运行了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值