2010-06-13 3 views
1

Je m'exerce à écrire des applications MVC. J'ai un jeu Mastermind, que je voudrais réécrire en tant qu'application MVC. J'ai divisé mon code en parties, mais au lieu de travailler le jeu, je reçois un cadre vide et une erreur dans "public void paint (Graphics g)". L'erreur provient de l'appel de cette méthode dans ma vue avec un argument nul. Mais comment surmonter cela? MVC était assez simple avec swing mais awt et ses méthodes de peinture sont beaucoup plus compliquées.Conversion d'une application en architecture MVC

Code de l'application de travail:
http://paste.pocoo.org/show/224982/

App divisée MVC:
principal:

public class Main { 

    public static void main(String[] args){ 

     Model model = new Model(); 
     View view = new View("Mastermind", 400, 590, model); 
     Controller controller = new Controller(model, view); 

     view.setVisible(true); 
    } 
} 

Controller:

import java.awt.*; 
import java.awt.event.*; 

public class Controller implements MouseListener, ActionListener { 

    private Model model; 
    private View view; 

    public Controller(Model m, View v){ 

     model = m; 
     view = v; 

     view.addWindowListener(new WindowAdapter(){ 
      public void windowClosing(WindowEvent e){ 
      System.exit(0); 
     } }); 

     view.addMouseListener(this); 

    } 

    public void actionPerformed(ActionEvent e) { 
     if(e.getSource() == view.checkAnswer){ 
      if(model.isRowFull){ 
       model.check(); 
      } 
     } 
    } 

    public void mousePressed(MouseEvent e) { 
     Point mouse = new Point(); 

     mouse = e.getPoint(); 
     if (model.isPlaying){ 
      if (mouse.x > 350) { 
       int button = 1 + (int)((mouse.y - 32)/50); 
       if ((button >= 1) && (button <= 5)){ 
        model.fillHole(button); 
       } 
      } 
     } 
    } 

    public void mouseClicked(MouseEvent e) {} 
    public void mouseReleased(MouseEvent e){} 
    public void mouseEntered(MouseEvent e) {} 
    public void mouseExited(MouseEvent e) {} 
} 

Vue:

import java.awt.*; 
import javax.swing.*; 
import java.awt.event.*; 

public class View extends Frame implements ActionListener { 

    Model model; 
    JButton checkAnswer; 
    private JPanel button; 
    static final int HIT_X[] = {270,290,310,290,310}, HIT_Y[] = {506,496,496,516,516}; 

    public View(String name, int w, int h, Model m){ 

     model = m; 

     setTitle(name); 
     setSize(w,h); 
     setResizable(false); 
     this.setLayout(new BorderLayout()); 

     button = new JPanel(); 
     button.setSize(new Dimension(400, 100)); 
     button.setVisible(true); 
     checkAnswer = new JButton("Check"); 
     checkAnswer.addActionListener(this); 
     checkAnswer.setSize(new Dimension(200, 30)); 
     button.add(checkAnswer); 
     this.add(button, BorderLayout.SOUTH); 
     button.setVisible(true); 

     for (int i=0; i < model.SCORE; i++){ 
      for (int j = 0; j < model.LINE; j++){ 
       model.pins[i][j] = new Pin(20,0); 
       model.pins[i][j].setPosition(j*50+30,510-i*50); 
       model.pins[i+model.SCORE][j] = new Pin(8,0); 
       model.pins[i+model.SCORE][j].setPosition(HIT_X[j],HIT_Y[j]-i*50); 
      } 
     } 
     for (int i=0; i < model.LINE; i++){ 
      model.pins[model.OPTIONS][i] = new Pin(20, i+2); 
      model.pins[model.OPTIONS][i].setPosition(370,i * 50 + 56); 
     } 
     model.combination(); 

     model.paint(null); 
    } 

    public void actionPerformed(ActionEvent e) { 
    } 
} 

Modèle:

import java.awt.*; 

public class Model extends Frame{ 
    static final int 
    LINE = 5, 
    SCORE = 10, OPTIONS = 20; 
    Pin pins[][] = new Pin[21][LINE]; 
    int combination[] = new int[LINE]; 
    int curPin = 0; 
    int turn = 1; 
    int repaintPin; 
    boolean isUpdate = true, isPlaying = true, isRowFull = false; 

    public Model(){ 
    } 

    void fillHole(int color) { 
     pins[turn-1][curPin].setColor(color+1); 
     repaintPins(turn); 
     curPin = (curPin+1) % LINE; 
     if (curPin == 0){ 
      isRowFull = true; 
     } 
    } 

    public void paint(Graphics g) { 
     g.setColor(new Color(238, 238, 238)); 
     g.fillRect(0,0,400,590); 

     for (int i=0; i < pins.length; i++) { 
      pins[i][0].paint(g); 
      pins[i][1].paint(g); 
      pins[i][2].paint(g); 
      pins[i][3].paint(g); 
      pins[i][4].paint(g); 
     } 
    } 

    public void update(Graphics g) { 
     if (isUpdate) { 
      paint(g); 
     } 
     else { 
      isUpdate = true; 
      pins[repaintPin-1][0].paint(g); 
      pins[repaintPin-1][1].paint(g); 
      pins[repaintPin-1][2].paint(g); 
      pins[repaintPin-1][3].paint(g); 
      pins[repaintPin-1][4].paint(g); 
     } 
    } 

    void repaintPins(int pin) { 
     repaintPin = pin; 
     isUpdate = false; 
     repaint(); 
    } 

    void check() { 
     int junkPegs[] = new int[LINE], junkCode[] = new int[LINE]; 
     int pegCount = 0, pico = 0; 

     for (int i = 0; i < LINE; i++) { 
      junkPegs[i] = pins[turn-1][i].getColor(); 
      junkCode[i] = combination[i]; 
     } 
     for (int i = 0; i < LINE; i++){ 
      if (junkPegs[i]==junkCode[i]) { 
       pins[turn+SCORE][pegCount].setColor(1); 
       pegCount++; 
       pico++; 
       junkPegs[i] = 98; 
       junkCode[i] = 99; 
      } 
     } 
     for (int i = 0; i < LINE; i++){ 
      for (int j = 0; j < LINE; j++) 
       if (junkPegs[i]==junkCode[j]) { 
        pins[turn+SCORE][pegCount].setColor(2); 
        pegCount++; 
        junkPegs[i] = 98; 
        junkCode[j] = 99; 
        j = LINE; 
      } 
     } 
     repaintPins(turn+SCORE); 

     if (pico == LINE){ 
      isPlaying = false; 
     } 
     else if (turn >= 10){ 
       isPlaying = false; 
     } 
     else{ 
      curPin = 0; 
      isRowFull = false; 
      turn++; 
     } 
    } 

    void combination() { 
     for (int i = 0; i < LINE; i++){ 
      combination[i] = 1 + (int)(Math.random()*5); 
      System.out.print(i+","); 
     } 
    } 
} 

class Pin{ 
    private int color, X, Y, radius; 
    private static final Color COLORS[] = { 
     Color.black, 
     Color.white, 
     Color.red, 
     Color.yellow, 
     Color.green, 
     Color.blue, 
     new Color(7, 254, 250)}; 

    public Pin(){ 
     X = 0; Y = 0; radius = 0; color = 0; 
    } 

    public Pin(int r,int c){ 
     X = 0; Y = 0; radius = r; color = c; 
    } 

    public void paint(Graphics g){ 
     int x = X-radius; 
     int y = Y-radius; 

     if (color > 0){ 
      g.setColor(COLORS[color]); 
      g.fillOval(x,y,2*radius,2*radius); 
     } 
     else{ 
      g.setColor(new Color(238, 238, 238)); 
      g.drawOval(x,y,2*radius-1,2*radius-1); 
     } 
     g.setColor(Color.black); 
     g.drawOval(x,y,2*radius,2*radius); 
    } 

    public void setPosition(int x,int y){ 
     this.X = x ; 
     this.Y = y ; 
    } 
    public void setColor(int c){ 
     color = c; 
    } 
    public int getColor() { 
     return color; 
    } 
} 

Des indices sur la façon de surmonter ce serait formidable. Ai-je divisé mon code incorrectement?

Répondre

1

Cela ne me semble pas juste.

Le modèle ne doit pas étendre le cadre. Le cadre est une idée de vue. Le modèle ne devrait pas avoir de graphiques, ou de peinture, ou quoi que ce soit d'autre que le problème à l'intérieur.

je n'aurais pas Voir tout mettre en œuvre des interfaces Listener. C'est le travail du contrôleur. C'est l'écouteur qui gère tous les événements et met à jour le modèle pour répondre aux changements qu'il reçoit de l'événement View.

Voir devrait être juste swing ou les classes AWT; pas d'auditeurs. Les méthodes de peinture appartiennent à View. Tout ce qui est peint doit être exprimé dans View.

Aucun des deux modèles ne devraient avoir des références Voir à l'autre ou contrôleur; le contrôleur possède des références à la fois au modèle et à la vue. C'est l'omniscient qui connaît tout le problème.

modèle ne connaît que le problème que vous résolvez.

Voir devrait être complètement amovible. Un bon test consiste à pouvoir supprimer l'interface utilisateur Swing et écrire une vue purement textuelle pour la remplacer. Si vous pouvez le faire sans affecter les deux autres, vous avez superposé les choses correctement.

+0

Alors où dois-je placer les méthodes paint()? en vue ? Et si j'ai de la peinture() pour Model et Pin? – terence6

+0

"paint" est intrinsèquement View. Si vous avez des objets Model et Pin qui nécessitent une peinture, passez-les dans View et demandez-leur de faire le travail. – duffymo

Questions connexes