public bool _canTheseOrthogonalVectorsExistTogether(WordVector horiz, WordVector vert) { //this code is non obvious, NOTE: // A) orthogonal vectors often intersect. They are supposed to in a crossword // B) All intersections (letters are equal) are already approved. switch (Othogonal_Rule) { case WordPlacement_Othogonal_Rules.CanTouch: return(true); case WordPlacement_Othogonal_Rules.NoTouch: //also this statements are non obvious (looks wrong) till you do the working out if ((horiz.Y >= vert.Y) && (horiz.Y <= vert.LastY)) { return(((horiz.X + horiz.Length) != vert.X) && (horiz.X != (vert.X + 1))); } if ((vert.X >= horiz.X) && (vert.X <= horiz.LastX)) { return(((vert.Y + vert.Length) != horiz.Y) && (vert.Y != (horiz.Y + 1))); } return(true); default: return(true); } }
private List <Tuple <WordVector, int> > GetPossibleVectors(string text) { List <Dir2D> dirs = new List <Dir2D>() { Dir2D.Right, Dir2D.Down }; List <Tuple <WordVector, int> > possibleVecs = new List <Tuple <WordVector, int> >(); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { foreach (Dir2D dir in dirs) { WordVector vec = new WordVector(new Point(x, y), dir, text.Length); int intersectionCount = testPlacement(text, vec); if (intersectionCount > 0) { possibleVecs.Add(new Tuple <WordVector, int>(vec, intersectionCount)); } } } } return(possibleVecs); }
private int testPlacement(string text, WordVector vec) { bool ok = true; int intersectionCount = 0; if ((vec.LastX >= Width) || (vec.LastX < 0) || (vec.LastY >= Height) || (vec.LastY < 0)) { return(0); //placement leaves grid } Point pos = vec.Pos; for (int i = 0; i < vec.Length; i++) { char?charGrid = grid[pos.X, pos.Y]; char charText = text[i]; if (charGrid != null) { if (charGrid.Value == charText) { intersectionCount++; } else { ok = false; break; } } //next pos pos = pos.NextPoint(vec.Dir); } return(ok ? intersectionCount : 0); }
/// <summary> /// Assigns 1 across etc /// </summary> private void AssignIndexes() { var acrossWords = from wrd in Words where (wrd.Dir == Dir2D.Right) orderby wrd.Pos.Y, wrd.Pos.X select wrd; var downWords = from wrd in Words where (wrd.Dir == Dir2D.Down) orderby wrd.Pos.Y, wrd.Pos.X select wrd; int i = 1; foreach (WordVector wv in acrossWords) { wv.IndexValue = i; i++; } foreach (WordVector wv in downWords) { WordVector other = acrossWords.FirstOrDefault(W => W.Pos == wv.Pos); if (other == null) { wv.IndexValue = i; i++; } else { wv.IndexValue = other.IndexValue; //ie 15 across..., 15 down... } } }
public static bool VectorHasLetters(this IWordGrid g, WordVector vec) { Point p = vec.Pos; for (int i = 0; i < vec.Length; i++) { if (g[p] == null) { return(false); } p = p.NextPoint(vec.Dir); } return(true); }
public static void placeWord(this IWordGrid g, string text, WordVector vec) { if (vec.Dir == Dir2D.None) { return; } Point p = vec.Pos; int len = 0; while (g.InBounds(p) && (len < vec.Length)) { g[p] = text[len]; len++; p = p.NextPoint(vec.Dir); } }
public bool canTheseTwoVectorsExistTogether(WordVector a, WordVector b) { if (a.isVertical && b.isVertical) { return(_canTheseHorizontalVectorsExistTogether(Transpose(a), Transpose(b))); } else if (a.isHorizontal && b.isHorizontal) { return(_canTheseHorizontalVectorsExistTogether(a, b)); } else if (a.isHorizontal && b.isVertical) { return(_canTheseOrthogonalVectorsExistTogether(a, b)); } else { return(_canTheseOrthogonalVectorsExistTogether(b, a)); } }
public static string GetWord(this IWordGrid g, WordVector vec) { if (vec.Dir == Dir2D.None) { return(null); } Point p = vec.Pos; int len = 0; string str = ""; while (g.InBounds(p) && (g[p] != null) && (len < vec.Length)) { str = str + g[p].Value; len++; p = p.NextPoint(vec.Dir); } return((len == vec.Length) ? str : null); }
/// <summary> /// Can this word be placed along the vector with out altering any existing letters? /// </summary> /// <param name="vec"></param> /// <param name="str"></param> /// <returns></returns> public static bool AnyConflicts(this IWordGrid g, WordVector vec, string str) { if (vec.Dir == Dir2D.None) { return(true); } Point p = vec.Pos; int len = 0; while (g.InBounds(p) && (len < vec.Length) && isSameLetterOrNull(g[p], str[len]) ) { len++; p = p.NextPoint(vec.Dir); } return((len - 1) == vec.Length); }
internal bool Intersects(WordVector other) { //TODO: simple algorithm, needs to be replaced with something more efficient Point p = Pos; for (int i = 0; i < Length; i++) { if (other.Intersects(p)) { return(true); } p = p.NextPoint(Dir); } return(false); /* * if(this.Dir == Dir2D.None) { * return other.Intersects(this.Pos); * } * else if(other.Dir == Dir2D.None) { * return this.Intersects(other.Pos); * } * else if(isHorizontal(this.Dir)) * { * if(isHorizontal(other.Dir)) * { * //Range. * } * else * { * } * } * else //this is vertical * { * } */ }
private WordVector Transpose(WordVector v) { return(new WordVector(new Point(v.Pos.Y, v.Pos.X), otherDir(v.Dir), v.Length)); }
public bool _canTheseHorizontalVectorsExistTogether(WordVector _a, WordVector _b) { //check this to eliminate many checks later if ((Parallel_Rule == WordPlacement_Parallel_Rules.EvenLinesOnly) && (((_a.Y % 2) == 1) || ((_b.Y % 2) == 1))) { return(false); } //a is the left most bool swap = (_a.Pos.X > _b.Pos.X); WordVector a = swap ? _b : _a; WordVector b = swap ? _a : _b; RangeInt aRange = RangeInt.FromStartAndLength(a.Pos.X, a.Length); RangeInt bRange = RangeInt.FromStartAndLength(b.Pos.X, b.Length); //rule out vectors not near each other to eliminate many checks later RangeInt aRangePlus = RangeInt.FromStartAndLength(a.Pos.X, a.Length + 1); RangeInt bRangePlus = RangeInt.FromStartAndLength(b.Pos.X, b.Length + 1); if (!aRangePlus.Intersects(bRangePlus)) { return(true); //no reason to test } if (a.Pos.Y == b.Pos.Y) { //run on rules apply switch (RunOnRule) { case WordPlacement_RunOn_Rules.NoRestrictions: return(true); case WordPlacement_RunOn_Rules.NoContainment: return(!(aRange.Contains(bRange) || bRange.Contains(aRange))); case WordPlacement_RunOn_Rules.NoRunOnOverLap: return(!aRange.Intersects(bRange)); case WordPlacement_RunOn_Rules.NoRunOnTouching: return(false); //because of previous tests we know they must at least but together default: throw new InvalidOperationException(); } } else if (Math.Abs(a.Pos.Y - b.Pos.Y) == 1) { //parallel rules apply switch (Parallel_Rule) { case WordPlacement_Parallel_Rules.NoRestrictions: return(true); case WordPlacement_Parallel_Rules.MustHaveGap: return(false); case WordPlacement_Parallel_Rules.EvenLinesOnly: return(true); //previous testing has already solved the case for false default: throw new InvalidOperationException(); } } else { //they are not near each other vertically return(true); } }
//---------------------------------------------------------------------------------- // Creating crosswords //---------------------------------------------------------------------------------- public void Generate(LanguageDictionary dictionary, int seed = -1) { int maxWords = TargetWordCount; seeedRandomGenerator(seed); this.Dictionary = dictionary; //start with a long word Word word = getNextWord(maxWords); string text = word.PrimarySpelling.ToLower(); WordVector vec = new WordVector(new Point(roundUpTillEven((Width - text.Length) / 2), roundUpTillEven(Height / 2)), Dir2D.Right, text.Length); vec.Word = word; grid.placeWord(text, vec); addUsedWord(text); this.words.Add(vec); dump(words); int esc = 0; //place Word while ((WordCount < maxWords) && (word != null)) { word = getNextWord(maxWords); if (word == null) { break; //done } //temp, escape esc++; if (esc > 10000) { break; } text = word.PrimarySpelling.ToLower(); List <Tuple <WordVector, int> > possibleVecs = GetPossibleVectors(text); //remove any rule violations possibleVecs = possibleVecs.Where(V => !this.Words.Any(N => !canTheseTwoVectorsExistTogether(N, V.Item1))).ToList(); if (possibleVecs.Count > 0) { //we want the most intersectiony option int maxIntersects = possibleVecs.Max(V => V.Item2); possibleVecs = possibleVecs.Where(V => V.Item2 == maxIntersects).ToList(); vec = possibleVecs.GetRandomItem(rnd).Item1; vec.Word = word; grid.placeWord(text, vec); addUsedWord(text); this.words.Add(vec); dump(words); esc = 0; } } //finish up the related tasks AssignIndexes(); }
private List <WordVector> GetPossibleVectors_old(string text) { List <WordVector> possibleVecs = new List <WordVector>(); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { //is there a character at the grid which matches our text char?_c = grid[x, y]; if ((_c != null) && (text.Contains(_c.Value))) { List <WordVector> interSectingVecsToCurrentGridPoint = (from v in Words where v.Intersects(x, y) select v).ToList(); //only one word should intersect this letter (so far) //we are trying to place this word orthogonally across it if (interSectingVecsToCurrentGridPoint.Count == 1) { WordVector intersect = interSectingVecsToCurrentGridPoint[0]; Dir2D newDir = otherDir(intersect.Dir); Dir2D newDirOrthogonal = intersect.Dir; //check all possible intersection points foreach (int pos in text.IndexOfAll(_c.Value)) { //create the vector that would position the word orthogonally across the other WordVector newVec; if (newDir == Dir2D.Down) { newVec = new WordVector(new Point(x, y - pos), newDir, text.Length); } else //across { newVec = new WordVector(new Point(x - pos, y), newDir, text.Length); } //check it works (does not put a different letter on top of another word) if (!this.grid.AnyConflicts(newVec, text)) { if (words.TrueForAll(W => canTheseTwoVectorsExistTogether(W, newVec))) { possibleVecs.Add(newVec); } /* * //get the orthogonal words intersected * List<WordVector> interSectingVecsToNewVec = (from v in Words where v.Intersects(newVec) select v).ToList(); * * //can't intersect another WordVector in the same direction * if (interSectingVecsToNewVec.TrueForAll(V => V.Dir == newDirOrthogonal)) * { * //the word should not impinge on exclusion zones of the existing vectors * //other than the one it intersects orthogonally to * List<WordVector> nonIntersectingVectors = Words.Where(V => !interSectingVecsToNewVec.Contains(V)).ToList(); * * if (nonIntersectingVectors.TrueForAll(V => !(newVec.InCrosswordStyleExclusionZoneOF(V)))) * { * possibleVecs.Add(newVec); * } * }*/ } } } } } } //done return(possibleVecs); }
protected WordVector(WordVector other) { this.Pos = other.Pos; this.Dir = other.Dir; this.Length = other.Length; }