Exemple #1
0
 public CrossedWord(CrossedWord previous)
 {
     this.Word             = previous.Word;
     this.Clue             = previous.Clue;
     this.WordDirection    = previous.WordDirection;
     this.StartingPosition = new Tile(previous.StartingPosition.X, previous.StartingPosition.Y);
 }
Exemple #2
0
 // An array wich gave us for each letter of c (e.g. array[0] for the first letter) the tiles on which the current instance has the same letter
 public List <Tile>[] SimilarLetterTiles(CrossedWord c)
 {
     List <Tile>[] tilesForEachLetter = new List <Tile> [c.Size];
     for (int i = 0; i < c.Size; i++)
     {
         List <Tile> TilesForCurrentLetter = new List <Tile>();
         for (int j = 0; j < this.Size; j++)
         {
             if (c.Word[i] == this.Word[j])
             {
                 TilesForCurrentLetter.Add(this.TileAtWordPosition(j));
             }
         }
         tilesForEachLetter[i] = TilesForCurrentLetter;
     }
     return(tilesForEachLetter);
 }
Exemple #3
0
    public int CompareTo(object obj)
    {
        if (obj == null)
        {
            return(1);
        }

        CrossedWord otherCrossWord = obj as CrossedWord;

        if (otherCrossWord != null)
        {
            return(this.Size.CompareTo(otherCrossWord.Size));
        }
        else
        {
            throw new ArgumentException("Object is not a CrossedWord");
        }
    }
Exemple #4
0
    // Tells if instance can accept the crossword (no superposition...)
    public int CanAccept(CrossedWord c)
    {
        // BOTH HORIZONTAL
        if (this.WordDirection == Direction.Horizontal && c.WordDirection == Direction.Horizontal)
        {
            // Having more than 1 line between them
            if (Math.Abs(c.StartingPosition.Y - this.StartingPosition.Y) > 1)
            {
                return(0);
            }
        }

        // Having less than 1 line between them but not touching nor supersposing
        if (Math.Abs(c.StartingPosition.Y - this.StartingPosition.Y) <= 1 && (this.StartingPosition.X > c.StartingPosition.X + c.Size || this.StartingPosition.X + this.Size < c.StartingPosition.X))
        {
            return(2);
        }

        // BOTH VERTICAL
        if (this.WordDirection == Direction.Vertical && c.WordDirection == Direction.Vertical)
        {
            // Having more than 1 row between them
            if (Math.Abs(c.StartingPosition.X - this.StartingPosition.X) > 1)
            {
                return(0);
            }
        }

        // Having less than 1 row between them but not touching nor supersposing
        if (Math.Abs(c.StartingPosition.X - this.StartingPosition.X) <= 1 && (this.StartingPosition.Y > c.StartingPosition.Y + c.Size || this.StartingPosition.Y + this.Size < c.StartingPosition.Y))
        {
            return(2);
        }

        // INSTANCE HORIZONTAL AND OTHER VERTICAL
        if (this.WordDirection == Direction.Horizontal && c.WordDirection == Direction.Vertical)
        {
            Tile potentialIntersection = new Tile(c.StartingPosition.X, this.StartingPosition.Y);

            char instanceChar = this.LetterOnTile(potentialIntersection);
            char otherChar    = c.LetterOnTile(potentialIntersection);
            // IF CROSSING ON THE SAME LETTER --> TRUE
            if (this.isWordOverTile(potentialIntersection) && c.isWordOverTile(potentialIntersection) && instanceChar == otherChar)
            {
                if (instanceChar != '0')
                {
                    return(1);
                }
                else
                {
                    return(0);
                }
            }
            else if (instanceChar == '0' && (potentialIntersection.X < this.StartingPosition.X - 1 || potentialIntersection.X > this.StartingPosition.X + this.Size))
            {
                return(0);
            }
        }

        // INSTANCE VERTICAL AND OTHER HORIZONTAL
        if (this.WordDirection == Direction.Vertical && c.WordDirection == Direction.Horizontal)
        {
            Tile potentialIntersection = new Tile(this.StartingPosition.X, c.StartingPosition.Y);

            char instanceChar = this.LetterOnTile(potentialIntersection);
            char otherChar    = c.LetterOnTile(potentialIntersection);
            // IF CROSSING ON THE SAME LETTER --> TRUE
            if (this.isWordOverTile(potentialIntersection) && c.isWordOverTile(potentialIntersection) && instanceChar == otherChar)
            {
                if (instanceChar != '0')
                {
                    return(1);
                }
                else
                {
                    return(0);
                }
            }
            else if (instanceChar == '0' && (potentialIntersection.Y < this.StartingPosition.Y - 1 || potentialIntersection.Y > this.StartingPosition.Y + this.Size))
            {
                return(0);
            }
        }


        return(-1);
    }
    public void GenerateCrossWords()
    {
        List <CrossedWord> fixedwordsList = new List <CrossedWord>();

        //string[] words = System.IO.File.ReadAllLines("crossword.txt");

        //foreach (string line in words)
        //{
        //    fixedwordsList.Add(new CrossedWord(line.Trim(), ""));
        //}

        //int lineno = New.instace.RemainingList[New.NumberOfPragrency];
        print("---->>" + New.instace.RemainingList[New.NumberOfPragrency]);
        string pragnencyword = New.instace.PrgencyList[New.instace.RemainingList[New.NumberOfPragrency]].Trim();


        char[] myChars = pragnencyword.ToCharArray();


        string char1 = myChars[UnityEngine.Random.Range(0, pragnencyword.Length - 1)].ToString();
        string char2 = myChars[UnityEngine.Random.Range(0, pragnencyword.Length - 1)].ToString();

        fixedwordsList.Add(new CrossedWord(pragnencyword, ""));
        New.NumberOfPragrency++;



        for (int i = 0; i < New.instace.CommonList.Count; i++)
        {
            if (New.instace.CommonList[i].Contains(char1))
            {
                string commonword1 = New.instace.CommonList[i].Trim();
                fixedwordsList.Add(new CrossedWord(commonword1, ""));
                New.NumberOfCommon++;
                New.instace.CommonList.Remove(New.instace.CommonList[i]);
                break;
            }
        }

        for (int i = 0; i < New.instace.CommonList.Count; i++)
        {
            if (New.instace.CommonList[i].Contains(char2))
            {
                string commonword2 = New.instace.CommonList[i].Trim();
                fixedwordsList.Add(new CrossedWord(commonword2, ""));
                New.NumberOfCommon++;
                New.instace.CommonList.Remove(New.instace.CommonList[i]);
                break;
            }
        }



        //string commonword2 = New.instace.CommonList[New.NumberOfCommon].Trim();
        //fixedwordsList.Add(new CrossedWord(commonword2, ""));
        //New.NumberOfCommon++;



        // The very final crosswords

        List <CrossedWord> CrossWordsToKeep = new List <CrossedWord>();

        float crosswordLength = float.MaxValue;
        int   WordsPlaced = 0;
        int   crosswordMinX = 0, crosswordMinY = 0;

        // Looping to choose the best grid (looping arbitrary "the number of words" time)

        for (int gen = 0; gen < fixedwordsList.Count; gen++)
        {
            // Not Touching the initial List
            List <CrossedWord> allWords = new List <CrossedWord>(fixedwordsList);

            if (gen % 2 == 1)
            {
                // Shuffling the words half the tries because sometimes not starting with the longer word can be a good option too
                for (int j = allWords.Count - 1; j > 0; j--)
                {
                    int         r   = UnityEngine.Random.Range(0, j + 1);
                    CrossedWord tmp = allWords[r];
                    allWords[r] = allWords[j];
                    allWords[j] = tmp;
                }
            }
            else
            {
                allWords.Sort();
                allWords.Reverse();
            }

            // The final crosswords for this loop only
            List <CrossedWord> finalWords = new List <CrossedWord>();

            // Adding the first word we found
            finalWords.Add(new CrossedWord(allWords[0]));
            // Removing this word from the list
            allWords.RemoveAt(0);

            // Initial size knowing the fact that the first word is Horizontal
            int minX = 0, maxX = finalWords[0].Size - 1, minY = 0, maxY = 0;

            // Loop on all the words we want in the crossword
            int maxLoop = Mathf.FloorToInt(allWords.Count * allWords.Count);

            int z = 0;
            int i = 0;
            for (; 0 != allWords.Count && z < maxLoop; z++)
            {
                // The current word we want to place
                CrossedWord currentWordToPlace = new CrossedWord(allWords[i]);


                // Will tell us if we succeed placing it
                bool bIsPlaced = false;

                // Will always be the best position we find, initialise here with arbitrary values
                Tile BestStartingPosition           = new Tile(0, 0);
                CrossedWord.Direction BestDirection = CrossedWord.Direction.Horizontal;

                // Will be a score to tell us which position is "conceptually" the best
                float score = float.MaxValue;

                // Loop on all the existing words in the crossword
                for (int j = 0; j < finalWords.Count; j++)
                {
                    // The current already placed word that we will used to try to place the new word
                    CrossedWord currentWordPlaced = finalWords[j];

                    // If we must placed the new one according to the existing one, the new one will be the other direction
                    currentWordToPlace.WordDirection = currentWordPlaced.WordDirection == CrossedWord.Direction.Horizontal ? CrossedWord.Direction.Vertical : CrossedWord.Direction.Horizontal;

                    // 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
                    List <Tile>[] intersectionForEachLetter = currentWordPlaced.SimilarLetterTiles(currentWordToPlace);

                    // Loop on all the letters
                    for (int k = 0; k < intersectionForEachLetter.Length; k++)
                    {
                        // Looking for each given tile for one letter
                        for (int l = 0; l < intersectionForEachLetter[k].Count; l++)
                        {
                            // Getting the tile
                            Tile currentCommonTile = intersectionForEachLetter[k][l];

                            // Given the direction of the placed word and the intersection tile we calculate the new word potential starting position
                            if (currentWordPlaced.WordDirection == CrossedWord.Direction.Horizontal)
                            {
                                currentWordToPlace.StartingPosition = new Tile(currentCommonTile.X, currentCommonTile.Y - k);
                            }
                            else
                            {
                                currentWordToPlace.StartingPosition = new Tile(currentCommonTile.X - k, currentCommonTile.Y);
                            }

                            // 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
                            // the int to tell us how many correct intersection we have
                            int iCanBePlaced = 0;
                            // the boolean to tell us a conflict
                            bool bCanBePlaced = true;
                            for (int m = 0; m < finalWords.Count && bCanBePlaced; m++)
                            {
                                // ca = 0 means no conflict, -1 means a conflict, 1 means a good intersection
                                int ca = finalWords[m].CanAccept(currentWordToPlace);
                                if (ca > 0)
                                {
                                    iCanBePlaced += ca;
                                }
                                if (ca == -1)
                                {
                                    bCanBePlaced = false;
                                }
                            }

                            // The place is OK and have minimum one good intersection
                            if (bCanBePlaced && iCanBePlaced > 0)
                            {
                                // Calculate a score to find the best place

                                // how much intersection but the opposite value
                                int crossedNumber = (0 - iCanBePlaced);

                                // a conceptual score that should be the less the better
                                float tmpScore = UnityEngine.Random.Range(0, 10) + crossedNumber * 100;

                                // 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
                                if (tmpScore < score)
                                {
                                    bIsPlaced = true;

                                    // Updating the new best score
                                    score = tmpScore;
                                    BestStartingPosition = currentWordToPlace.StartingPosition;
                                    BestDirection        = currentWordToPlace.WordDirection;
                                }
                            }
                        }
                    }
                }

                // We have at least one position to place this new word
                if (bIsPlaced)
                {
                    // getting this saved position
                    currentWordToPlace.StartingPosition = BestStartingPosition;
                    currentWordToPlace.WordDirection    = BestDirection;
                    // adding this word to the crossword
                    finalWords.Add(currentWordToPlace);

                    // Shuffling the crossword array to have more random factor on the grid creation (doesn't really matters but linear operation so it's ok)
                    for (int j = finalWords.Count - 1; j > 0; j--)
                    {
                        int         r   = UnityEngine.Random.Range(0, j + 1);
                        CrossedWord tmp = finalWords[r];
                        finalWords[r] = finalWords[j];
                        finalWords[j] = tmp;
                    }

                    // Updating the grid Rectangle if necessary
                    minX = Mathf.Min(minX, currentWordToPlace.StartingPosition.X);
                    minY = Mathf.Min(minY, currentWordToPlace.StartingPosition.Y);

                    maxX = Mathf.Max(maxX, currentWordToPlace.WordDirection == CrossedWord.Direction.Horizontal ? currentWordToPlace.StartingPosition.X + currentWordToPlace.Size - 1 : currentWordToPlace.StartingPosition.X);
                    maxY = Mathf.Max(maxY, currentWordToPlace.WordDirection == CrossedWord.Direction.Vertical ? currentWordToPlace.StartingPosition.Y + currentWordToPlace.Size - 1 : currentWordToPlace.StartingPosition.Y);

                    allWords.RemoveAt(i);
                    if (allWords.Count > 0)
                    {
                        i = i % allWords.Count;
                    }
                }
                else
                {
                    i = (i + 1) % allWords.Count;
                }
            }

            // Final new length of the grid
            float newLength = Mathf.Sqrt((maxX - minX) * (maxX - minX) + (maxY - minY) * (maxY - minY));
            // Final new number of word we succeed to put on the grid
            int currentWordsPlaced = finalWords.Count;

            // if it's a better grid (smaller and more words). Indeed, we allow a bigger crossword proportionally to how much more words it contains
            if (newLength - (currentWordsPlaced - WordsPlaced) * 4 < crosswordLength && WordsPlaced < currentWordsPlaced)
            {
                // Keeping this grid in memory
                CrossWordsToKeep = finalWords;
                // Updating best grid values
                crosswordLength = newLength;
                WordsPlaced     = currentWordsPlaced;

                crosswordMinX = minX;
                crosswordMinY = minY;
            }
        }

        Debug.Log(CrossWordsToKeep.Count + "/" + fixedwordsList.Count + " size: " + crosswordLength);

        print("--CrossWordsToKeep.Count----->>>" + CrossWordsToKeep.Count);
        for (int r = 0; r < 3; r++)
        {
            CrossWordsToKeep[r].StartingPosition.X -= crosswordMinX;
            CrossWordsToKeep[r].StartingPosition.Y  = -CrossWordsToKeep[r].StartingPosition.Y + crosswordMinY;
        }

        CrToShow = CrossWordsToKeep;
    }