document.write('
Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1.     public void GenerateCrossWords()
  2.     {
  3.         List<CrossedWord> fixedwordsList = new List<CrossedWord>();
  4.        
  5.         string[] words = System.IO.File.ReadAllLines("crossword.txt");
  6.        
  7.         foreach(string line in words)
  8.         {
  9.             string[] wordAndClue = line.Split(\'/\');
  10.             fixedwordsList.Add(new CrossedWord(wordAndClue[0].Trim() , wordAndClue[1]));
  11.         }
  12.        
  13.        
  14.         // The very final crosswords
  15.        
  16.         List<CrossedWord> CrossWordsToKeep = new List<CrossedWord>();
  17.            
  18.         float crosswordLength = float.MaxValue;
  19.         int WordsPlaced = 0;
  20.         int crosswordMinX = 0, crosswordMinY = 0;
  21.        
  22.         // Looping to choose the best grid (looping arbitrary "the number of words" time)
  23.        
  24.         for(int gen = 0 ;  gen < fixedwordsList.Count ; gen++)
  25.         {
  26.             // Not Touching the initial List
  27.             List <CrossedWord> allWords = new List<CrossedWord>(fixedwordsList);
  28.            
  29.             if(gen % 2 == 1)
  30.             {
  31.                 // Shuffling the words half the tries because sometimes not starting with the longer word can be a good option too
  32.                 for(int j = allWords.Count - 1 ; j > 0; j--)
  33.                 {
  34.                     int r = UnityEngine.Random.Range(0, j+1);
  35.                     CrossedWord tmp = allWords[r];
  36.                     allWords[r] = allWords[j];
  37.                     allWords[j] = tmp;
  38.                 }
  39.             }
  40.             else
  41.             {
  42.                 allWords.Sort();
  43.                 allWords.Reverse();
  44.             }
  45.            
  46.             // The final crosswords for this loop only
  47.             List<CrossedWord> finalWords = new List<CrossedWord>();
  48.            
  49.             // Adding the first word we found
  50.             finalWords.Add(new CrossedWord(allWords[0]));
  51.             // Removing this word from the list
  52.             allWords.RemoveAt(0);
  53.            
  54.             // Initial size knowing the fact that the first word is Horizontal
  55.             int minX = 0, maxX = finalWords[0].Size - 1, minY = 0, maxY = 0;
  56.            
  57.             // Loop on all the words we want in the crossword
  58.             int maxLoop = Mathf.FloorToInt(allWords.Count*allWords.Count );
  59.            
  60.             int z = 0;
  61.             int i = 0;
  62.             for(; 0 != allWords.Count && z < maxLoop ;z++)
  63.             {
  64.                
  65.                 // The current word we want to place
  66.                 CrossedWord currentWordToPlace = new CrossedWord(allWords[i]);
  67.                
  68.                
  69.                 // Will tell us if we succeed placing it
  70.                 bool bIsPlaced = false;
  71.                
  72.                 // Will always be the best position we find, initialise here with arbitrary values
  73.                 Tile BestStartingPosition = new Tile(0,0);
  74.                 CrossedWord.Direction BestDirection = CrossedWord.Direction.Horizontal;
  75.                
  76.                 // Will be a score to tell us which position is "conceptually" the best
  77.                 float score = float.MaxValue;
  78.                
  79.                 // Loop on all the existing words in the crossword
  80.                 for(int j = 0; j< finalWords.Count; j++)
  81.                 {
  82.                     // The current already placed word that we will used to try to place the new word
  83.                     CrossedWord currentWordPlaced = finalWords[j];
  84.                    
  85.                     // If we must placed the new one according to the existing one, the new one will be the other direction
  86.                     currentWordToPlace.WordDirection = currentWordPlaced.WordDirection == CrossedWord.Direction.Horizontal ? CrossedWord.Direction.Vertical : CrossedWord.Direction.Horizontal;
  87.                    
  88.                     // An array wich gave us for each letter (e.g. array[0] for the first letter) the tiles on which the current placed word has the same letter
  89.                     List<Tile>[] intersectionForEachLetter = currentWordPlaced.SimilarLetterTiles(currentWordToPlace);
  90.                    
  91.                     // Loop on all the letters
  92.                     for(int k = 0; k < intersectionForEachLetter.Length;k++)
  93.                     {
  94.                         // Looking for each given tile for one letter
  95.                         for(int l = 0; l < intersectionForEachLetter[k].Count; l++)
  96.                         {
  97.                             // Getting the tile
  98.                             Tile currentCommonTile = intersectionForEachLetter[k][l];
  99.                            
  100.                             // Given the direction of the placed word and the intersection tile we calculate the new word potential starting position
  101.                             if( currentWordPlaced.WordDirection == CrossedWord.Direction.Horizontal )
  102.                             {
  103.                                 currentWordToPlace.StartingPosition = new Tile(currentCommonTile.X, currentCommonTile.Y - k);
  104.                             }
  105.                             else
  106.                             {
  107.                                 currentWordToPlace.StartingPosition = new Tile(currentCommonTile.X -k , currentCommonTile.Y);
  108.                             }
  109.                            
  110.                             // Loop on all the words in the crossword to check if the place we want the new word isn\'t in conflict with the existings words
  111.                             // the int to tell us how many correct intersection we have
  112.                             int iCanBePlaced = 0;
  113.                             // the boolean to tell us a conflict
  114.                             bool bCanBePlaced = true;
  115.                             for(int m = 0; m < finalWords.Count && bCanBePlaced; m++)
  116.                             {
  117.                                 // ca = 0 means no conflict, -1 means a conflict, 1 means a good intersection
  118.                                 int ca = finalWords[m].CanAccept(currentWordToPlace);
  119.                                 if(ca > 0)
  120.                                     iCanBePlaced += ca;
  121.                                 if(ca == -1)
  122.                                     bCanBePlaced = false;
  123.                             }
  124.                            
  125.                             // The place is OK and have minimum one good intersection
  126.                             if(bCanBePlaced && iCanBePlaced > 0)
  127.                             {
  128.                                 // Calculate a score to find the best place
  129.                                
  130.                                 // how much intersection but the opposite value
  131.                                 int crossedNumber = (0 - iCanBePlaced);
  132.                                
  133.                                 // a conceptual score that should be the less the better
  134.                                 float tmpScore =  UnityEngine.Random.Range(0,10) + crossedNumber *100;
  135.                                
  136.                                 // if this score si better than a previous one we keep this position and tell that we succeed placing at least one time this word
  137.                                 if( tmpScore < score)
  138.                                 {
  139.                                     bIsPlaced = true;
  140.                                    
  141.                                     // Updating the new best score
  142.                                     score = tmpScore;
  143.                                     BestStartingPosition = currentWordToPlace.StartingPosition;
  144.                                     BestDirection = currentWordToPlace.WordDirection;
  145.                                 }
  146.                             }
  147.                         }
  148.                     }
  149.                 }
  150.                
  151.                 // We have at least one position to place this new word
  152.                 if(bIsPlaced)
  153.                 {
  154.                     // getting this saved position
  155.                     currentWordToPlace.StartingPosition = BestStartingPosition;
  156.                     currentWordToPlace.WordDirection = BestDirection;
  157.                     // adding this word to the crossword
  158.                     finalWords.Add(currentWordToPlace);
  159.                    
  160.                     // Shuffling the crossword array to have more random factor on the grid creation (doesn\'t really matters but linear operation so it\'s ok)
  161.                     for(int j = finalWords.Count - 1 ; j > 0; j--)
  162.                     {
  163.                         int r = UnityEngine.Random.Range(0, j+1);
  164.                         CrossedWord tmp = finalWords[r];
  165.                         finalWords[r] = finalWords[j];
  166.                         finalWords[j] = tmp;
  167.                     }
  168.                    
  169.                     // Updating the grid Rectangle if necessary
  170.                     minX = Mathf.Min(minX, currentWordToPlace.StartingPosition.X);
  171.                     minY = Mathf.Min(minY, currentWordToPlace.StartingPosition.Y);
  172.                    
  173.                     maxX = Mathf.Max(maxX, currentWordToPlace.WordDirection == CrossedWord.Direction.Horizontal ? currentWordToPlace.StartingPosition.X + currentWordToPlace.Size - 1 : currentWordToPlace.StartingPosition.X);
  174.                     maxY = Mathf.Max(maxY, currentWordToPlace.WordDirection == CrossedWord.Direction.Vertical ? currentWordToPlace.StartingPosition.Y + currentWordToPlace.Size - 1 : currentWordToPlace.StartingPosition.Y);
  175.                
  176.                     allWords.RemoveAt(i);
  177.                     if(allWords.Count > 0)
  178.                         i = i % allWords.Count;
  179.                 }
  180.                 else
  181.                 {
  182.                     i = (i+1) % allWords.Count;
  183.                 }
  184.             }
  185.            
  186.             // Final new length of the grid
  187.             float newLength = Mathf.Sqrt((maxX - minX)*(maxX - minX) + (maxY - minY)*(maxY - minY));
  188.             // Final new number of word we succeed to put on the grid
  189.             int currentWordsPlaced = finalWords.Count;
  190.            
  191.             // if it\'s a better grid (smaller and more words). Indeed, we allow a bigger crossword proportionally to how much more words it contains
  192.             if(newLength - (currentWordsPlaced - WordsPlaced)*4 < crosswordLength  && WordsPlaced < currentWordsPlaced)
  193.             {
  194.                 // Keeping this grid in memory
  195.                 CrossWordsToKeep = finalWords;
  196.                 // Updating best grid values
  197.                 crosswordLength = newLength;
  198.                 WordsPlaced = currentWordsPlaced;
  199.                
  200.                 crosswordMinX = minX;
  201.                 crosswordMinY = minY;
  202.             }
  203.        
  204.         }
  205.        
  206.         Debug.Log(CrossWordsToKeep.Count+"/"+fixedwordsList.Count+" size: "+crosswordLength);
  207.        
  208.         for(int r = 0; r < CrossWordsToKeep.Count; r++)
  209.         {
  210.             CrossWordsToKeep[r].StartingPosition.X -= crosswordMinX;
  211.             CrossWordsToKeep[r].StartingPosition.Y = -CrossWordsToKeep[r].StartingPosition.Y + crosswordMinY;
  212.         }
  213.        
  214.         CrToShow = CrossWordsToKeep;
  215.        
  216.     }
');