wordsearch-creator/WordSearch.cs

194 lines
6.8 KiB
C#

/*
Wordsearch Creator
Copyright (C) 2023 Tesses
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System.Text;
using SixLabors.Fonts;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
namespace WordSearch
{
public class WordSearchGenerator
{
Random rand=new Random((int)(DateTime.Now.Ticks % int.MaxValue));
List<string> words = new List<string>();
List<string> wordsOg = new List<string>();
int largestWord=0;
public IReadOnlyList<string> Words => wordsOg;
public int LargestWord => largestWord;
public void AddWord(string word)
{
if(string.IsNullOrWhiteSpace(word)) return;
if(word.Length > largestWord) largestWord = word.Length;
words.Add(word.Replace(" ","").ToUpper());
wordsOg.Add(word);
}
public override string ToString()
{
StringBuilder builder=new StringBuilder();
var grid=GenerateGrid();
for(int y=0;y<largestWord;y++)
{
for(int x=0;x<largestWord;x++)
{
builder.Append(grid[x,y]);
}
builder.AppendLine();
}
builder.AppendLine();
foreach(var word in words)
{
builder.AppendLine(word);
}
return builder.ToString();
}
public Image<Rgb24> GenerateImage(Font font,Rgb24 foreground,Rgb24 background)
{
var grid=GenerateGrid();
StringBuilder b = new StringBuilder();
for(int y = 0;y<largestWord;y++)
{
for(int x=0;x<largestWord;x++)
{
if(x>0)
b.Append(' ');
b.Append(grid[x,y]);
}
b.AppendLine();
b.AppendLine();
}
for(int i = 0;i<wordsOg.Count;i++)
{
b.Append(wordsOg[i]);
if((i % 3) == 2)
{
b.AppendLine();
}
else
{
b.Append(' ');
}
}
b.AppendLine();
string text= b.ToString();
var sz=TextMeasurer.MeasureSize(text,new TextOptions(font));
Image<Rgb24> image = new Image<Rgb24>((int)Math.Ceiling(sz.Width)+40,(int)Math.Ceiling(sz.Height)+40,background);
image.Mutate(e=>e.DrawText(text,font,foreground,new PointF(20,20)));
return image;
}
public char[,] GenerateGrid()
{
DateTime mustbeDoneBefore=DateTime.Now.AddMinutes(1);
char[,] grid = new char[largestWord,largestWord];
foreach(var word in words)
{
err:
if(DateTime.Now > mustbeDoneBefore) throw new Exception();
int x=rand.Next(0,largestWord);
int y = rand.Next(0,largestWord);
int mode = rand.Next(0,4);
switch(mode)
{
case 0:
//Horizontal
if(x+word.Length>largestWord) goto err;
for(int i = 0;i<word.Length;i++)
{
if(DateTime.Now > mustbeDoneBefore) throw new Exception();
//check whether these are all zeros
if(grid[x+i,y] != 0) goto err;
}
for(int i =0;i<word.Length;i++)
{
grid[x+i,y] = word[i];
}
break;
case 1:
if(y+word.Length>largestWord) goto err;
for(int i = 0;i<word.Length;i++)
{
if(DateTime.Now > mustbeDoneBefore) throw new Exception();
//check whether these are all zeros
if(grid[x,y+i] != 0) goto err;
}
for(int i =0;i<word.Length;i++)
{
grid[x,y+i] = word[i];
}
break;
case 2: //\
if(y+word.Length>largestWord || x+word.Length> largestWord) goto err;
for(int i = 0;i<word.Length;i++)
{
if(DateTime.Now > mustbeDoneBefore) throw new Exception();
//check whether these are all zeros
if(grid[x+i,y+i] != 0) goto err;
}
for(int i =0;i<word.Length;i++)
{
grid[x+i,y+i] = word[i];
}
break;
case 3:// /
if(y+word.Length>largestWord || x-word.Length< 0) goto err;
for(int i = 0;i<word.Length;i++)
{
if(DateTime.Now > mustbeDoneBefore) throw new Exception();
//check whether these are all zeros
if(grid[x-i,y+i] != 0) goto err;
}
for(int i =0;i<word.Length;i++)
{
grid[x-i,y+i] = word[i];
}
break;
}
}
for(int y=0;y<largestWord;y++)
{
for(int x = 0;x<largestWord;x++)
{
if(grid[x,y] == 0)
{
int val=rand.Next(0,26);
if(val < 26)
{
grid[x,y] = (char)(val+'A');
}
}
}
}
return grid;
}
}
}