我们让交java程序。同学大都写的是记事本这样的东西。我觉得没有什么意思,完全不能训练自己对面向对象编程的思想,所以想到了做一个扫雷游戏。基于swing GUI开发。但是由于第一次用面向对象的方法写程序所以不知道怎样划分和封装类(类怎样划分以及把那些功能封装到类中)我分了3个类
1. class Mine     格子 继承JButton2. MineTable      雷表 继承JPanel
主要是一个逻辑上的2维数组(用于在计算机中表示)
和一1维的Mine数组(用于显示) 
3. 程序主窗口本来在Mine 类中实现了MouseListener接口,实现了格子的 点开、标雷等方法。但是后来(今天下午)发现好像这样做完全错了。
因为格子的点开(左单击)方法应该是一个递归的函数,需要感知以该(被点击的格子)为中心的周围8个(不考虑边界问题)的状态,以及是否继续展开。如果被封装到Mine类中就只能感知到它自己,所以好像应该写到MineTable类中实现。但是又感觉好像这个方法应该是雷(格子)的,而不是雷区表的方法。所以很乱。不知道怎样封装类。请高手指点一下,如何封装类。怎样用面向对象的方法思考。谢谢!

解决方案 »

  1.   

    楼主的方法可行,你可以在构造雷表格的时候,把每个格子要显示的数算出来.而不是在点击时计算.这个数封装在你那个Button里.
    class Mine extends JButton{
    int aroundBombNum=0; //这个是周围的雷数,例如-1表示雷什么的,你说了算
    //封装所有icon,作为static型的字段不错的.
    public void setAroundBombNum(int n){...}
    public int getAroundBombNum(){..}
    }
    class MineTable extends JPanel{
    boolean[][] table;//例如true为雷,false不是雷.
    Mine[][] block; //对应上面数组的按钮public void init(){//初始数组
    //初始雷(也就是table数组),随机就行了.
    //循环所有元素,如果table[i][j]==true,设置block[i][j]的aroundBombNum=-1,否则扫描周围八个方块,计下true的个数到它的aroundBombNum,也就是周围雷的个数.要显示的数值.
    }
      

  2.   

    试着重设计一下:
    1。格子中雷的信息存放在一个二维数组中,1为有雷,0为无雷。
    2。按下任一个button,并不需要什么感知自己,只是在事件处理中,调用一个函数,计算以他中心所在的对应的存放雷信息的二维数组中能点开的格子,这个与界面上的按钮没关系,然后重绘雷区。这就简单的MVC,把数据,界面,控制分开处理(控制与界面经常会放在一起),而不是全放在一起。
      

  3.   

    (刚才还没有敲完就按提交了:))各个类生成的组建之间如何相互联系工作?
    我现在已经基本上把雷表写好了。
    需要在public static void main(String args[]) 中不断的判断雷表的状态。也就是需要不断的检测游戏是否结束了。
    但是这样写好像不行。
    麻烦高手提供一个思路,我怎么样在主调函数main中判断雷表状态?while((win.minepanel.total - win.minepanel.ed != 0) && (win.minepanel.dead = false))
    {

    }
    if(win.minepanel.dead == true)
    {
     win.msgbar.setText("game over");
     win.validate();

    }
    else
    win.msgbar.setText("you win");
      

  4.   

    // the mine
    void flag(int row , int col)
    {
    status[row][col] = FLAG;
    this.ed++;
    humantable[row*grid+col].setBackground(Color.RED);
    }

    //un the mine
    void unflag(int row , int col)
    {
    status[row][col] = INITIAL;
    this.ed--;
    humantable[row*grid+col].setBackground(defaultcolor);
    }

    //expand the mine
    void expand(int row , int col)
    {
    if(isValid(row,col))
    {

    if(this.status[row][col] == INITIAL)
    {
    if(isBomb(row,col))
    {
    setGameStatus(EXPLODED);
    }
    else // it's not a bomb itself
    {

    if ( (computeBomb(row,col)-computeFlag(row,col)) != 0 ) // there are many bombs around this grid,如果发现它周围一共有3个雷,而且你都已经标了3个,那么不管你标的对不对都自动展开.
    {
    if(isBomb(row,col))// make a wrong judge
    setGameStatus(EXPLODED);
    else
    {
    this.status[row][col] = EXPANDED;
    this.humantable[row*grid+col].setBackground(new Color(217, 217, 217));
    this.showBomb(row,col);
    this.ed++;
    }

    }
    else // there is no bomb around this grid
    {
    this.status[row][col] = LOCK; //在递归调用前加锁add lock to the current grid

    this.expand(row-1,col-1); //up_left
    this.expand(row-1,col); //up_middle
    this.expand(row-1,col+1); //up_right
    this.expand(row,col-1); //left
    this.expand(row,col+1); //right
    this.expand(row+1,col-1); //down_left
    this.expand(row+1,col); //down_middle
    this.expand(row+1,col+1); //down_right

    this.status[row][col] = 
    this.humantable[row*gridEXPANDED; //unlock the grid
    this.ed++;+col].setBackground(new Color(217, 217, 217));

    }

    }

    }

    }

    }