Modelo Vista Controlador (MVC) es un patrón de arquitectura de software que separa los datos de una aplicación, la interfaz de usuario, y la lógica de negocio en tres componentes distintos. (Según Santa Wikpedia)
Arquitectura.
Basta de teoria y tratemos de implementar este en una aplicación GUI de Java con el IDE de netbeans, existen ejemplos sobre este patron y java en aplicación Web, pero encontre pocos y la mayoria en ingles sobre este modelo orientado a GUI, pero eso no quiere decir que no se pueda, Java cuenta con sus propias herramientas para implementar MVC, por ejemplo Observer y Observable, pero en esta ocasión nosotros no haremos uso de ellas.
El proyecto.
1. Creamos un nuevo proyecto en Netbeans siguiendo la estructura MVC, creamos un paquete para cada uno de ellos, una carpeta Controlador, otra Vista y una más para el Modelo.
2. Comenzando por la interfaz, creamos un JFrame con 9 botones, estos los ordenamos utilizando un GridLayout en una matriz 3×3, renombramos cada boton con el nombre «casilla1», «casilla2» y asi sucesivamente, ahora lo importante, Netbeans crea los objetos como PRIVATE, esto no nos sirve, entonces selecciona todos los botones y dirigete a sus propiedades, clic derecho PROPIEDADES, en la pestala CODIGO, busva la opción «Modificadores de Variable», entonces eliges la opcion PUBLIC y le das a aceptar. Si no sabes como hacer esto, fijate en el video que esta al final del post.
El nombre de la vista es «interfaz.java».
3. Crea una nueva clase en el paquete Modelo, llamalo «juego.java», es ahi donde colocamos la logica del juego 3 en Raya, el codigo es el siguiente:
package modelo; /** * @web www.jc-mouse.net/ * @author Mouse */ public class juego { private byte turno = 1;//1=>jugador 1 2=> jugador 2 private String marca_X = "X"; private String marca_O = "O"; private boolean error=false;//por si se produce algun mensaje private byte ganador_es=0;//1=>jugador 1 2=> jugador 2 3=>Empate //matriz para almacenar los movimientos del juego private String tablero[][] ={{"","",""}, {"","",""}, {"","",""} }; public juego(){} //reinicia los valores y limpia el tablero public void Jugar_otra_vez() { for ( int i = 0 ; i < tablero.length ; i++ ) for ( int j = 0 ; j < tablero.length ; j++) tablero[i][j]=""; this.error=false; this.ganador_es=0; this.turno=1; } //dado una posicion y segun el turno que corresponda //coloca la marca "X" o "O" en el tablero //Salida: La marca que se coloco en la matriz public String set_movimiento(int posicion) { String out=""; if(turno==1) { out = marcar(posicion , this.marca_X); //si no se pudo marcar => continua con su turno turno = 2; if ( gano(this.tablero, this.marca_X) ) this.ganador_es=1; else if ( empate() ) this.ganador_es=3; } else { out = marcar(posicion , this.marca_O); turno = 1; if ( gano(this.tablero, this.marca_O) ) this.ganador_es=2; else if ( empate() ) this.ganador_es=3; } return out; } /* MARCA LA CASILLA CON EL MOVIMIENTO DEL JUGADOR, */ private String marcar(int Posicion, String value) { String marca=""; switch (Posicion) { case 1:marca = sub_marcar(0,0,value); break; case 2:marca = sub_marcar(0,1,value); break; case 3:marca = sub_marcar(0,2,value); break; case 4:marca = sub_marcar(1,0,value); break; case 5:marca = sub_marcar(1,1,value); break; case 6:marca = sub_marcar(1,2,value); break; case 7:marca = sub_marcar(2,0,value); break; case 8:marca = sub_marcar(2,1,value); break; case 9:marca = sub_marcar(2,2,value); break; } return marca; } //funcion privada que sigue a funcion marcar, esto para no repetir codigo //si al marcar en la matriz , existe algun error, coloca la bandera a TRUE private String sub_marcar(int x, int y, String value) { String marca=""; this.error=false; if( this.tablero[x][y].equals("") ) //se puede marcar { this.tablero[x][y] = value; marca = value; } else//ya esta marcado { marca = this.tablero[x][y]; this.error=true;//Error=>se trata de marcar casilla ya marcada } return marca; } public boolean get_error() { return this.error; } public String get_turno() { return (this.turno==1)? "Turno: X":"Turno: O"; } public byte ganador() { return this.ganador_es; } //funcion que determina quien gano la partida public boolean gano( String matriz[][], String marca ) { //busqueda de ganador por filas for ( int i = 0 ; i < matriz.length ; i++ ) { byte count=0; for ( int j = 0 ; j < matriz.length ; j++) count+=( matriz[i][j].equals(marca) )?1:0; if( count == 3) return true; } //busqueda de ganador por columnas for ( int j = 0 ; j < matriz.length ; j++ ) { byte count=0; for ( int i = 0 ; i < matriz.length ; i++) count+=( matriz[i][j].equals(marca) )?1:0; if( count == 3) return true; } //diagonales if( matriz[0][0].equals(marca) && matriz[1][1].equals(marca) && matriz[2][2].equals(marca) ) return true; if( matriz[0][2].equals(marca) && matriz[1][1].equals(marca) && matriz[2][0].equals(marca) ) return true; return false; } //Funcion que determina si se puede continuar jugando private boolean empate() { for ( int i = 0 ; i < tablero.length ; i++ ) for ( int j = 0 ; j < tablero.length ; j++) if( tablero[i][j].equals("")) return false; return true; } }
Como ves, es un juego sencillo y no necesitamos de otras clases ni de base de datos, aunque si asi fuera, las demas clases y la persistena se colocan en esta carpeta.
4. Toca el turno del Controlador, crea una clase en este paquete y llamalo «controlador.java» (que original no), esta clase nos permite la interacción entre la Vista y el Modelo, aunque en ocasiones la vista puede recuperar datos del modelo directamente o viceversa, eso ya depende del programador. El codigo es el siguiente:
package controlador; import modelo.juego; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JOptionPane; import vista.interfaz; /** * @web www.jc-mouse.net/ * @author Mouse */ public class controlador implements ActionListener { private interfaz vista; private juego juego; private String titulo = "3 en Raya MVC * jc-mouse.net "; //En el constructor inicializamos nuestros objetos public controlador( interfaz vista , juego modelo){ this.vista = vista; this.juego = modelo; } //Inicia los valores del jFrame VISTA con los datos del MODELO // tambien añadimos el ActionListener a los botones de la VISTA public void iniciar_vista(){ vista.setTitle( this.titulo ); vista.setLocationRelativeTo(null); this.vista.casilla1.addActionListener(this); this.vista.casilla2.addActionListener(this); this.vista.casilla3.addActionListener(this); this.vista.casilla4.addActionListener(this); this.vista.casilla5.addActionListener(this); this.vista.casilla6.addActionListener(this); this.vista.casilla7.addActionListener(this); this.vista.casilla8.addActionListener(this); this.vista.casilla9.addActionListener(this); } //La accion de los botones de la VISTA es capturado, asi como los valores //dependiendo del boton pulsado, se envia la informacion al modelo //y se espera la respuesta public void actionPerformed(ActionEvent e) { Object boton = e.getSource(); if( this.juego.ganador()== 0 ) { if( boton == this.vista.casilla1 ) this.vista.casilla1.setText( this.juego.set_movimiento(1) ); else if(boton == this.vista.casilla2) this.vista.casilla2.setText( this.juego.set_movimiento(2) ); else if(boton == this.vista.casilla3) this.vista.casilla3.setText( this.juego.set_movimiento(3) ); else if(boton == this.vista.casilla4) this.vista.casilla4.setText( this.juego.set_movimiento(4) ); else if(boton == this.vista.casilla5) this.vista.casilla5.setText( this.juego.set_movimiento(5) ); else if(boton == this.vista.casilla6) this.vista.casilla6.setText( this.juego.set_movimiento(6) ); else if(boton == this.vista.casilla7) this.vista.casilla7.setText( this.juego.set_movimiento(7) ); else if(boton == this.vista.casilla8) this.vista.casilla8.setText( this.juego.set_movimiento(8) ); else if(boton == this.vista.casilla9) this.vista.casilla9.setText( this.juego.set_movimiento(9) ); if( this.juego.get_error()) JOptionPane.showMessageDialog(null, "Error: la casilla ya esta marcada \n Perdiste tu turno"); this.vista.setTitle( this.titulo + this.juego.get_turno()); } if( this.juego.ganador()== 1 ) mensaje(" 'X' "); else if( this.juego.ganador()== 2 ) mensaje(" 'O' "); else if( this.juego.ganador()== 3 ) mensaje(" 'Es un empate' "); } //dependiendo de la respuesta del modelo, se muestra un mensaje al usuario private void mensaje(String s) { int seleccion = JOptionPane.showOptionDialog(null,"Gano el jugador " + s + "\n ¿Que desea hacer?", "Fin del juego", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, // null para icono por defecto. new Object[] { " Jugar otra vez ", " Salir de Programa " }, "Jugar otra vez"); if (seleccion != -1) if( (seleccion+1)==1 ) { this.juego.Jugar_otra_vez(); this.vista.setTitle(titulo); this.vista.casilla1.setText( "" ); this.vista.casilla2.setText( "" ); this.vista.casilla3.setText( "" ); this.vista.casilla4.setText( "" ); this.vista.casilla5.setText( "" ); this.vista.casilla6.setText( "" ); this.vista.casilla7.setText( "" ); this.vista.casilla8.setText( "" ); this.vista.casilla9.setText( "" ); } else System.exit(0); } }
5. muy bien, ya vamos terminando, fijate que no escribimos nada de codigo en la clase interfaz 😉
Para terminar debemos escribir un poco de codigo en la clase MAIN, el código es:
package mvc3nraya; import vista.interfaz; import controlador.controlador; import modelo.juego; /** * @web www.jc-mouse.net/ * @author Mouse */ public class Main { public static void main(String[] args) { //nuevas instancias de clase juego modelo = new juego(); interfaz vista = new interfaz(); controlador controlador = new controlador( vista , modelo ); controlador.iniciar_vista(); vista.setVisible(true); } }
En la clase Main, lo que hacemos es crear instancias de nuestros objetos pasando la Vista y el Modelo al Controlador, y despues lanzamos la interfaz al usuario y … eso es todo. Ejecuta el juego y revisa que todo este bien.
El código del proyecto esta AQUI
Yo soy yo :) JC Mouse, Soy orgullosamente boliviano soy fundador y CEO de la web jc-Mouse.net uno de las pocas web en emprendimiento y tecnología en Bolivia.
Toda la información que encuentres en este sitio es y sera completamente gratis siempre, puedes copiar, descargar y re-publicar si así lo deseas en otros blogs o sitios web, solo te pido a cambio que dejes una referencia a esta web. Esto nos ayuda a crecer y seguir aportando. Bye
Enjoy! :)
Un Fragment representa un comportamiento o una parte de la interfaz de usuario en una Activity. Puedes combinar múltiple...
En esta oportunidad aprovechando el interés que tienen ahora los superheroes de Marvel, crearemos un formulario de logue...
Yachaywasi versión 3.1 es una aplicación para android que te permite crear, editar y realizar exámenes tipo test cómodam...
Un ProgressDialog muestra una ventana con un texto y una barra de progreso que indica el tiempo que tarda una tarea en r...
Para poder conectar PHP con una base de datos de microsoft Access debemos seguir los siguientes pasos: 1. Crea una base...
Android hace uso de la base de datos SQLite para el manejo de registros en las aplicaciones. Según Santa Wikipedia defin...
Los comentarios estan cerrados
El gigante tecnologico Google a puesto un bonito Doodle en su buscador que esta fascinando a sus millones de usuarios qu...
WhatsApp anuncio a través de su blog que ya se encuentra disponible la función de envío de fotos y videos TEMPORALES, es...
Muchas de las innovaciones computacionales de la NASA se desarrollaron para ayudar a explorar el espacio, pero ahora la...
TikTok es una plataforma de microvideos muy popular entre los jóvenes el cual cuenta ya con millones de videos cortps de...
Muy buen tutorial justo lo que estaba buscando
Segi adelante amigo
ola! esta muy buena la explicacion pero se puede hacer con matriz?
pero si una matriz es la que estoy utilizando 🙁
Como se podría hacer usando un usuario vs. la máquina (por ejemplo con A*?)
Hola! Muy bueno el ejemplo.
Una pregunta: supongamos que quiero crear el jframe, el jpanle y los jbuttons en tiempo de diseño ¿Existe alguna manera de cambiar “Modificadores de Variable” de los botones para que sean PUBLIC en lugar de PRIVATE?
Gracias,
_
S
claro, pero seria escribiendo código para crear una matriz de controles 🙂 netbeans no te permite hacer eso
hola me puedes dar un analisis del juego por favor atte. manuel muchas gracias man un abrazo
específicamente con tus palabras por fa man te lo voy ha agradecer muchas gracias analisis del programa i analisis del juego analisis del codigo fuente graias
:/ análisis??? no te comprendo, seguramente alguna vez abras jugado tres en raya en tu cuaderno, entonces conoces las reglas del juego eso es todo lo que necesitas saber, el patrón MVC resumiendo M = modelo = logica del juego, reglas, metodos, IA (si asi fuera necesario) , V = vista = es todo lo que ve el usuario, el tablero de juego, C = controlador = el «controlador» agarra todos los eventos de la vista, (clic sobre en cuadrado del tablero, etc) y procesa esa información (X o O, gano el juego????, es un empate???? , le toca el turno al otro jugador, etc) en el modelo y retorna el resultado a la vista, ya sea marcando el tablero con la X o O, mostrando un mensaje de error, etc.
Muchas gracias, es justo lo que buscaba, un juego sencillo y que lo pudiese entender.
No sabia por donde empezar y fijándome un poco en tu código he resuelto las dudas, estoy empezando así que estas cosas me cuestan mucho todavía.
GRACIAS!!
holaaa mira es que queria pedirte un favor, podrias poner el codigo escrito del punto 2 en el que dices como haces el package modelo package porfavor, un saludo espero tu respuesta con la mayor brevedad posible. un saludo.
GRACIAS.
para crear un paquete, solo debes hacer clic en «Source Packages» -> new -> Java Packages
🙂
Hola Buenas noches Mouse excelente proyecto, te felicito por tus aportes queria preguntarte si este codigo es ORIENTADO A OBJETOS (POO) o es codigo Estructurado, Ademas queria preguntar si puedes enviarme este mismo codigo pero lo mas comentariado posible para entender mejor cada linea de codigo la verdad con tu pagina estoy repasando muchos conceptos de POO y pues este proyecto me parecio excelente ya que incorpora varios temas. Te agradezco si puedes comentariar cada linea de tu codigo ya que asi aprendo para que funciona cada cosa, La verdad de nuevo muchisimas gracias, Un saludo desde colombia! Mira mi correo es usuarionuevo9024@hotmail.com
Hola, como le haria para que cuando marque una casilla que ya esta marcada, en vez de perder el turno se reinicie el juego. Espero tu respuesta a la mayor brevedad posible, gracias!
muy buen tutorial.. sabes como se hace para guardar y cargar una partida en la consola?
puedes usar base de datos pero si no quieres nada complicado usa archivos texto para cada partida, nose digamos:
mijuego.txt
0,x,0,x,x,,,x,0 | 15-10-2014 | x
donde guardamos en una cadena separada por comas los movimientos de cada jugador, la fecha y el turno del jugador
Mouse
Gracias por tu aporte. Excelente ejemplo. Ha sido de gran utilidad para mi.
Holis amio gracias x el codigo es muy byeno y me va a ayudar bastanten tengo q exponerlo en clases para pasar una evaluacion, me puedes ayudar y darme una explicacion mas detallada del proceso del codigo , es q tengo q explicarle al ingeniero y si no se bien….me jalara 🙁