PRACTICA 2 SOPA DE LETRAS
OBJETIVO:
Desarrollar un programa donde se haga uso de cadenas en Java por medio de una sopa de letras a la que se le asignen 5 palabras las cuales acomodara aleatoriamente en la sopa de letras, tomando la palabra mas grande como punto de inicio colocada en diagonal y que los espacios que queden vacios sean llenadas con diferentes letras.
MARCO TEÓRICO:
Java posee gran capacidad para el manejo de cadenas dentro de sus clases String y StringBuffer . Un objeto String representa una cadena alfanumérica de un valor constante que no puede ser cambiada después de haber sido creada. Un objeto StringBuffer representa una cadena cuyo tamaño puede variar.
Los Strings son objetos constantes y por lo tanto muy baratos para el sistema. La mayoría de las funciones relacionadas con cadenas esperan valores String como argumentos y devuelven valores String.
Hay que tener en cuenta que las funciones estáticas no consumen memoria del objeto, con lo cual es más conveniente usar Character que char. No obstante, char se usa, por ejemplo, para leer ficheros que están escritos desde otro lenguaje.
Existen muchos constructores para crear nuevas cadenas:
String(); String( String str ); String( char val[] ); String( char val[],int offset,int count ); String( byte val[],int hibyte ); String( byte val[],int hibyte,int offset,int count );
Tal como uno puede imaginarse, las cadenas pueden ser muy complejas, existiendo muchas funciones muy útiles para trabajar con ellas y, afortunadamente, la mayoría están codificadas en la clase String .
Funciones Básicas
La primera devuelve la longitud de la cadena y la segunda devuelve el carácter que se encuentra en la posición que se indica en indice:
int length(); char charAt( int indice );
Funciones de Comparación de Strings
boolean equals( Object obj ); boolean equalsIgnoreCase( Object obj );
Lo mismo que equals() pero no tiene en cuenta mayúsculas o minúsculas.
int compareTo( String str2 );
Devuelve un entero menor que cero si la cadena es léxicamente menor que str2. Devuelve cero si las dos cadenas son léxicamente iguales y un entero mayor que cero si la cadena es léxicamente mayor que str2.
Funciones de Comparación de Subcadenas
boolean regionMatch( int thisoffset,String s2,int s2offset,int len ); boolean regionMatch( boolean ignoreCase,int thisoffset,String s2, int s2offset,int 1 );
Comprueba si una región de esta cadena es igual a una región de otra cadena.
boolean startsWith( String prefix ); boolean startsWith( String prefix,int offset ); boolean endsWith( String suffix );
Devuelve si esta cadena comienza o termina con un cierto prefijo o sufijo comenzando en un determinado desplazamiento.
int indexOf( int ch ); int indexOf( int ch,int fromindex ); int lastIndexOf( int ch ); int lastIndexOf( int ch,int fromindex ); int indexOf( String str ); int indexOf( String str,int fromindex ); int lastIndexOf( String str ); int lastIndexOf( String str,int fromindex );
Devuelve el primer/último índice de un carácter/cadena empezando la búsqueda a partir de un determinado desplazamiento.
String substring( int beginindex ); String substring( int beginindex,int endindex ); String concat( String str ); String replace( char oldchar,char newchar ); String toLowerCase(); String toUpperCase(); String trim();
Ajusta los espacios en blanco al comienzo y al final de la cadena.
void getChars( int srcBegin,int srcEnd,char dst[],int dstBegin ); void getBytes( int srcBegin,int srcEnd,byte dst[],int dstBegin ); String toString(); char toCharArray(); int hashCode();
Funciones ValueOf
La clase String posee numerosas funciones para transformar valores de otros tipos de datos a su representación como cadena. Todas estas funciones tienen el nombre de valueOf, estando el método sobrecargado para todos los tipos de datos básicos.
Veamos un ejemplo de su utilización:
String Uno = new String( "Hola Mundo" ); float f = 3.141592; String PI = Uno.valueOf( f ); String PI = String.valueOf( f ); // Mucho más correcto
La clase String proporciona cadenas de sólo lectura y soporta operaciones con ellas. Se pueden crear cadenas implícitamente usando una cadena intrecomillada o usando + ó += con dos objetos String.
También se pueden crear objetos String explícitamente con el mecanismo new. La clase String soporta los siguientes constructores.
• public String (): construye un nuevo String con el valor " ". • public String (String value): construye un String que es copia de value.
La forma de llamar a cualquier método de la clase String se realiza de la siguiente forma:
nombre_de_variable.nombre_del_método( ).
Los métodos básicos de los objetos String son:
• length () :
devuelve el número de caracteres de la cadena.
• charAt () :
devuelve el char de la posición especificada.
• for (int i = 0; i < str.length(); i++) • count[str.charAt(i)]++; • indexOf (char ch) :
devuelve el índice de la primera posición de ch.
• indexOf (char ch, int start) :
devuelve el índice de la primera posición de ch >=start.
• indexOf (String str) :
devuelve el índice de la primera posición de str.
• indexOf (String str, int start) :
devuelve el índice de la primera posición de str >= start.
• lastIndexOf (char ch):
devuelve el índice de la última posición de ch.
• lastIndexOf (char ch, int start) :
devuelve el índice de la última posición de ch <= start.
• lastIndexOf (String str) :
devuelve el índice de la última posición de str.
• lastIndexOf (String str, int start) :
devuelve el índice de la última posición de str <= start.
Los métodos indexOf (para métodos que buscan hacia delante) y lastIndexOf (para métodos que buscan hacia atrás) devuelven el índice que han encontrado o –1 si la búsqueda no ha sido satisfactoria.
DESARROLLO
El programa debera mostrar ua sopa de letras que permita ordenar las palabras aleatoriamente.Se creara una interfaz grafica atractiva para el usuario. Las palabras seran almacenadas previamente en un archivo .txt donde el programa las llamara. Primero se creara una clase principal donde se trate el manejo de la sopa de letras y una segunda clase que contenga los metodos para el "adorno" de la misma.
ANALISIS
Análisis de los requisitos:
• Plataforma java (jdk 6) • Editor de código (Text Pad, Blue J, Neat Beans, etc) • Conocimientos previos de programación O.O • Sistema operativo Windows (XP, Vista, Seven)
Analisis operativo:
1. El usuario visualiza una sopa de letras desordenada.
2. A la derecha se encuentran las palabras a buscar.
3.El usuario puede remarcar las palabras arrastrando el raton sobre ellas.
4. Para reiniciar otra serie de busqueda se oprime el boton Recargar.
Diseño
El programa debera mostrar una ventana similar a :
Par empezar a buscar las palabras se clikea cada una de las letras y se marcan automaticamente:
Para comenzar otra busqueda se oprime "Recargar" y se limpia la sopa de letras recargando con palabras nuevas:
CODIGO
Clase Worfind view source print? 001 import java.awt.*; 002 import java.applet.*;
003 import java.util.Vector; 004 import java.util.Hashtable;
005
006 public class Wordfind extends Applet implements java.awt.event.MouseListener,java.awt.event.ActionListener
007 { 008 private Label[] mines = null;
009 private final int square = 12; 010 private final int NUM_LABELS = square * square;
011 private final int NUM_WORDS_IN_PUZZLE = 4; 012 private Button button = null;
013 private Panel minepanel = null; 014 private Vector selectedLabels = new Vector();
015 private String[] solution = null; 016
017 private String wordlist = null; 018 private Hashtable words = null;
019 private Hashtable selectedWords = null; 020 //compass type constants
021 private final int NORTH = -square; // eg., if square= 12, then -12 022 private final int SOUTH = square;
023 private final int WEST = -1; 024 private final int EAST = 1;
025 private final int NE = -square + 1; 026 private final int NW = -square - 1;
027 private final int SE = square + 1; 028 private final int SW = square - 1;
029 private Label[] captions = null; 030 private Adorn a = null;
031
032
033 034
035 public void init() 036 {
037 038 setLayout(new BorderLayout());
039 this.setBackground(Color.pink); 040 //setSize(300,300);
041 minepanel = new Panel(new GridLayout(square,square)); 042
043 this.setForeground(Color.blue); 044 this.getLabels();
045 this.getWords(); 046 this.placeWords();
047 this.addFillers(); 048
049 Panel buttonpanel = new Panel(new BorderLayout()); 050
051 button = new Button("Recargar"); 052 button.addActionListener(this);
053 buttonpanel.add("South",button); 054
055 Panel labelpanel = new Panel(new GridLayout(0,1)); 056 for (int j = 0;j < getCaptions().length; j++){
057 labelpanel.add(getCaptions()[j]); 058
059 060 }
061 062
063 buttonpanel.add("North",labelpanel); 064
065 066
067 068 this.add("Center", minepanel);
069 this.add("South", buttonpanel); 070
071 072 setLayout(new FlowLayout());
073 setSize(792,396); 074 this.showStatus("Ready");
075 076
077 078
079 } 080
081 public void mouseClicked(java.awt.event.MouseEvent e){ 082 Component c = (Component)e.getSource();
083 if (c instanceof Label){ 084 Label l = (Label)c;
085 if (l.getBackground() == Color.lightGray){ 086 l.setBackground(Color.pink);
087 }else{ 088 l.setBackground(Color.lightGray);
089 } 090
091 this.addSelectedLabel(new Integer(l.getText())); 092 if (checkWin()){
093 showWin(); 094 }
095 096
097 } 098 }
099 public void mouseEntered(java.awt.event.MouseEvent e){} 100 public void mouseExited(java.awt.event.MouseEvent e){}
101 public void mousePressed(java.awt.event.MouseEvent e){} 102
103 public void mouseReleased(java.awt.event.MouseEvent e){}
104 public void actionPerformed(java.awt.event.ActionEvent e){
105 if (e.getSource()==button) { 106 //probably start button
107 restart(); 108 }
109 110
111 } 112
113 114 private boolean checkWin(){
115 //TO DO: 116 return false;
117 } 118 private void showWin(){
119 } 120
121 private Label[] getLabels(){ 122 if (mines == null){
123 124 mines = new Label[NUM_LABELS];
125 for (int i = 0;i < NUM_LABELS;i++){
126 mines[i] = new Label("",1);
127 mines[i].addMouseListener(this); 128 mines[i].setName("" + i);
129 minepanel.setBackground(Color.lightGray); 130 minepanel.add(mines[i]);
131 } 132 //set up adornment for these labels
133 134
135 a = new Adorn(); 136 a.setLabels(mines);
137 Thread aThread = new Thread(a); 138 aThread.start();
139 140
141 } 142
143 return mines; 144 }
145 146
147 private Label[] getCaptions(){ 148 if (captions==null){
149 captions = new Label[NUM_WORDS_IN_PUZZLE]; 150 for (int i = 0;i < captions.length;i++){
151 captions[i] = new Label(""); 152 captions[i].setAlignment(Label.RIGHT);
153 } 154 }
155 return captions; 156 }
157 158 //**************************
159 private void getWords(){ 160
161 int i = 0; 162
163 //words passed in ...or use default 164 wordlist = this.getParameter("WORDLIST");
165
if (wordlist ==null){
166
wordlist = "loco, tonto,inteligente,trabajado,rico,romantico,holgazan,memory,queue,rational,stereo,tranquil,weaver,zesty,blister,vanish,idiotic,range,scream,smile,spoof";
167 } 168
169 wordlist = wordlist.toUpperCase(); 170
171 172 java.util.StringTokenizer st = new java.util.StringTokenizer(wordlist,",");
173
174 words = new Hashtable(st.countTokens());
175 176 while (st.hasMoreElements()){
177 words.put(new String(String.valueOf(i)), st.nextToken()); 178 i++;
179 } 180 }
181 182
183 //*****************************
184 private void placeWords(){
185 186 //clear solution
187 solution = new String[NUM_LABELS];
188 String selectedWord = new String("");
189 190 //prepare selectedWords
191 selectedWords = new Hashtable(NUM_WORDS_IN_PUZZLE); 192
193 194
195 196 for (int i = 0; i< NUM_WORDS_IN_PUZZLE;i++){
197 198 boolean flag = false;
199 //don't add it to the selection if it's already there!! 200 while(flag==false){
201 //where to start 202 int pos = (int)(java.lang.Math.random()*words.size());
203 204 selectedWord = (String)words.get(String.valueOf(pos));
205 if (selectedWords.contains(selectedWord) == false){ 206 flag = true;
207 } 208 }
209 210 char[] thisword = selectedWord.toCharArray();
211 212 System.out.println(selectedWord + " ************************************");
213 214 int looped = 0;
215 //the direction should be randomly selected: 216 int[] directions = {NORTH,SOUTH,EAST,WEST,SW,SE,NE,NW};
217 218
219 while (looped < 50){ //presume unfittable word beyond this... 220 //try to position the word in the solution array
221 int startpos = (int)(java.lang.Math.random()* (square*square)); 222
223 int direction = (int)(java.lang.Math.random() * directions.length); 224
225 226 if (this.tryToFit(directions[direction], thisword, startpos)) {
227 //the word was placed!! So announce it 228 captionPuzzle(selectedWord);
229 break; //out of while loop 230 }
231 232 looped++;
233 } 234
235 } 236 }
237 //****************************** 238 private void addFillers(){
239 240 //add any old filler text to labels with no text
241 for (int i = 0;i < NUM_LABELS;i++){ 242
243 244 if (solution[i]==null){
245 mines[i].setText(this.getRandomLetter());
246 //mines[i].setText("-"); //TEST
247 248
249 }else{ 250 mines[i].setText(solution[i]);
251 252
253 } 254 }
255 256 }
257 // *********************** 258 private void clearLabels(){
259 //add any old filler text to labels with no text 260 for (int i = 0;i < NUM_LABELS;i++){
261 mines[i].setText(""); 262 mines[i].setBackground(Color.lightGray);
263 } 264
265 266 //now clear the captions
267 for (int j = 0;j< NUM_WORDS_IN_PUZZLE;j++){ 268 getCaptions()[j].setText("");
269 } 270
271 } 272
273 private void addSelectedLabel(Integer i){ 274 selectedLabels.addElement(i);
275 } 276
277 //***********************************
278 private String getRandomLetter(){
279 String pick = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 280
281 int spot = (int)(java.lang.Math.random() * 26);
282
283 String ret = pick.substring(spot,spot+1); 284
285 return ret; 286 }
287 288 //****************************
289 private synchronized void restart(){ 290 this.getWords();
291 this.clearLabels();
292 this.placeWords();
293 this.addFillers(); 294 }
295 296 //***************************
297 private boolean tryToFit(int increment, char[] what, int startPos){ 298 int charLength = what.length ;
299 int newPos = startPos; 300
301 for (int i = 0; i< charLength; i++){ 302 try{
303 // at this position
304 if ((solution[newPos]==null)||(solution[newPos].equals(String.valueOf(what[i])))){
305 //solution matrix must be null or same as the character 306
307 //dont worry about boundary on last char... 308 if ((!isBoundaryOK(newPos,increment)) || (i== charLength )){
309 return false; 310 }
311 312
313 //check another position in increment direction 314 newPos = newPos + increment ;
315 316
317 } 318
319 else{ 320 // oh oh, roadblock! try another direction...
321 return false; 322 }
323 }catch (Exception e){ 324 return false; //end of the road!
325 } 326 }
327 // if we got this far, we can position the char array in this direction 328
329 int charPos = startPos; 330 for (int q = 0; q< charLength; q++ ){
331 solution[charPos] = String.valueOf(what[q]); 332 charPos = charPos + increment ;
333 334 }
335 return true ; 336 }
337 338 //***************************************
339 private void captionPuzzle(String what){ 340
341 342 if (selectedWords !=null){
343 selectedWords.put(what,what); 344
345 } 346
347 348 //find an empty spot in the captions labels
349 for (int i = 0;i< getCaptions().length; i++){ 350 if (getCaptions()[i].getText().length()==0){
351 getCaptions()[i].setText(what); 352 return;
353 }
354 }
355 356
357 } 358
359 360 /* this routine checks to see that a char the boundary of the grid
361 doesn't try to write itself in the wrong place 362 ie, xxxh
363 tabx 364 xxxx
365 366
367 *note how the word bath is written if moving EAST 368
369 370 You can call this routine for all but the LAST char
371 372
373 */ 374
375 376 private boolean isBoundaryOK(int newPos,int direction){
377 378
379 380
381 switch (direction){ 382 case NORTH:
383 384
385 if (newPos < square){ 386 return false;
387 } 388 return true;
389 case SOUTH: 390 if (newPos + square >(square * square)){
391 return false; 392 }
393 return true; 394 case EAST:
395 //System.out.println("East" + newPos + " " + square); 396 if ( java.lang.Math.IEEEremainder(newPos+1,square)== 0){
397 return false; 398 }
399 case WEST: 400 //System.out.println("West" + newPos + " " + square);
401 if ( java.lang.Math.IEEEremainder(newPos,square)== 0){ 402 return false;
403 } 404 return true;
405 case NE: 406 if (newPos < square){//same as north
407 return false; 408 }
409 //System.out.println(" NE:" + newPos + " " + square);
410 if ( java.lang.Math.IEEEremainder(newPos+1,square)== 0){ //same rule as East
411 return false; 412 }
413 //System.out.println("true"); 414 return true;
415 case SE: 416
417 418 if (newPos + square >(square * square)){//same as south
419 return false; 420 }
421 //System.out.println("SE:" + newPos + " " + square);
422 if ( java.lang.Math.IEEEremainder(newPos+1,square)== 0){ //same rule as East
423 return false; 424 }
425 //System.out.println("true");
426 return true;
427 case SW: 428 if (newPos + square >(square * square)){ //Same as south
429 return false; 430 }
431 //System.out.println("SW " + newPos + " " + square); 432 if ( java.lang.Math.IEEEremainder(newPos,square)== 0){//like west
433 return false; 434 }
435 //System.out.println("true"); 436 return true;
437 case NW: 438 if (newPos < square){//same as north
439 return false; 440 }
441 442 //System.out.println("NW " + newPos + " " + square);
443 if ( java.lang.Math.IEEEremainder(newPos,square)== 0){ //like west rule
444 return false;
445 } 446 //System.out.println("true");
447 return true; 448
449 default: 450 break ;
451 } 452
453 454 return false;
455 } 456 }
Aqui la clase responsable del color de los adornos de las letras
Clase Adorn
view source
print? 01 import java.lang.*; 02 import java.awt.Color;
03 04
05 public class Adorn extends Object implements Runnable{ 06
07 08 private java.awt.Label[] labelArray = null;
09 private Color[] foreColors = {Color.magenta,Color.red,Color.cyan,Color.black};
10
11 12 public void setLabels(java.awt.Label[] l){
13 14
15 this.labelArray = l; 16 }
17 18
19 public void run(){ 20
21 22 while (true){
23 24
25 try{ 26 int myColor = (int)(java.lang.Math.random() * foreColors.length );
27 Color thisColor = foreColors[myColor]; 28 int currentLabel = (int)(java.lang.Math.random() * labelArray.length );
29 30
31 labelArray[currentLabel].setForeground(thisColor); 32
33 34 synchronized(this){ //lock it while doing this..
35 String text = labelArray[currentLabel].getText();
36 labelArray[currentLabel].setText(text);
37 } 38
39 40 Thread.currentThread().sleep(1000);
41 } catch (Exception e){} 42 }
43 } 44
45 46 }
PRUEBA Y DEPURACION
Resultado