Provide feedback
Saved searches
Use saved searches to filter your results more quickly
Sign up
Распознавание голоса и речи на C#
UnmanagedCoder 05.05.2025
Интеграция голосового управления в приложения на C# стала намного доступнее благодаря развитию специализированных библиотек и API. При этом многие разработчики до сих пор считают голосовое управление. . .
Реализация своих итераторов в C++
NullReferenced 05.05.2025
Итераторы в C++ — это абстракция, которая связывает весь экосистему Стандартной Библиотеки Шаблонов (STL) в единое целое, позволяя алгоритмам работать с разнородными структурами данных без знания их. . .
Разработка собственного фреймворка для тестирования в C#
UnmanagedCoder 04.05.2025
C# довольно богат готовыми решениями – NUnit, xUnit, MSTest уже давно стали своеобразными динозаврами индустрии. Однако, как и любой динозавр, они не всегда могут протиснуться в узкие коридоры. . .
Распределенная трассировка в Java с помощью OpenTelemetry
Javaican 04.05.2025
Микросервисная архитектура стала краеугольным камнем современной разработки, но вместе с ней пришла и головная боль, знакомая многим — отслеживание прохождения запросов через лабиринт взаимосвязанных. . .
Шаблоны обнаружения сервисов в Kubernetes
Mr. Docker 04.05.2025
Современные Kubernetes-инфраструктуры сталкиваются с серьёзными вызовами. Развертывание в нескольких регионах и облаках одновременно, необходимость обеспечения низкой задержки для глобально. . .
Создаем SPA на C# и Blazor
stackOverflow 04.05.2025
Мир веб-разработки за последние десять лет претерпел коллосальные изменения. Переход от традиционных многостраничных сайтов к одностраничным приложениям (Single Page Applications, SPA) — это. . .
Реализация шаблонов проектирования GoF на C++
NullReferenced 04.05.2025
«Банда четырёх» (Gang of Four или GoF) — Эрих Гамма, Ричард Хелм, Ральф Джонсон и Джон Влиссидес — в 1994 году сформировали канон шаблонов, который выдержал проверку временем. И хотя C++ претерпел. . .
C# и сети: Сокеты, gRPC и SignalR
UnmanagedCoder 04.05.2025
Сетевые технологии не стоят на месте, а вместе с ними эволюционируют и инструменты разработки. В . NET появилось множество решений — от низкоуровневых сокетов, позволяющих управлять каждым байтом. . .
Создание микросервисов с Domain-Driven Design
ArchitectMsa 04.05.2025
Архитектура микросервисов за последние годы превратилась в мощный архитектурный подход, который позволяет разрабатывать гибкие, масштабируемые и устойчивые системы. А если добавить сюда ещё и. . .
Многопоточность в C++: Современные техники C++26
bytestream 04.05.2025
C++ долго жил по принципу «один поток — одна задача» — как старательный солдатик, выполняющий команды одну за другой. В то время, когда процессоры уже обзавелись несколькими ядрами, этот подход стал. . .
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.
Introduction
Having an over-active brain and over-active imagination can sometimes be a blessing, but mostly it is a curse—especially for me, especially when I am thinking up wonderful ideas to write about. A topic that seems too complicated can end up being a gremlin of a project, whereas a topic that seems complicated up front can be a breeze.
Today’s project ended up being much bigger than what I initially thought, and there is still so much more potential that this project can end up huge! This is why I love developing: You never know what a project might become.
Today you will create a Crossword puzzle generator in Visual Basic. Hold on tight; it’s going to be an interesting ride!
Our Project
Open Visual Studio and create a new Visual Basic WPF application. The main reason I made this project in WPF form is because it has a handy little grid control that eases the design for the crossword. More on this a bit later.
Add the following controls to your WPF Form:
Three ListViews and a label for each, as shown in Figure 1:
Figure 1: ListViews
A Grid control, as shown in Figure 2:
Figure 2: Grid
A Textbox and two buttons, as shown in Figure 3:
Figure 3: Buttons and TextBox
Add six more buttons to your Form. Set their background colors to any color of your choice. These buttons will be used to fill the crossword grid. After you have formatted them, make all.
You already can shape an idea of what you will be doing, based on the preceding pictures. Just in case, let me explain it:
- You will type a word in the TextBox and click Add. All the words will be added like this.
- Once you click Generate the Puzzle, the words will be displayed in the grid as well as which words are shown Vertically and which are shown Horizontally.
You are welcome to name and format and rearrange all your objects as you please.
Add a Class to your project and name it clsCrossword.
Add the following Members to it:
Shared rndRandom As Random Private Shared strWordList As IList(Of String) Const strLetters As String = "abcdefghijklmnopqrstuvwxyz" Private intHWords As Integer(,) Private intVWords As Integer(,) Private intX As Integer() = {0, 1} Private intY As Integer() = {1, 0} Private intDirX As Integer Private intDirY As Integer Private intHWordsCount As Integer Private intVWordsCount As Integer Private Shared intSol As Integer Private chrGameBoard As Char(,) Private Shared chrTempGameBoard As Char(,) Private dtTime As DateTime
These variables control the direction in which the word should be displayed on the board as well as setting up the game board and word structure. You will make use of strLetters, which will get split into either the Horizontal words or Vertical words arrays.
Add the Constructor:
Public Sub New(X As Integer, Y As Integer) intDirX = X intDirY = Y rndRandom = New Random() chrGameBoard = New Char(X - 1, Y - 1) {} intHWords = New Integer(X - 1, Y - 1) {} intVWords = New Integer(X - 1, Y - 1) {} For i As Integer = 0 To intDirX - 1 For j As Integer = 0 To intDirY - 1 chrGameBoard(i, j) = " "c Next Next End Sub
The Constructor simply initializes all the objects. It sets up the game board and creates a new Random object. Add the next two Properties for this class:
Public ReadOnly Property X() As Integer Get Return intDirX End Get End Property Public ReadOnly Property Y() As Integer Get Return intDirY End Get End Property Public ReadOnly Property GetBoard() As Char(,) Get Return chrGameBoard End Get End Property
As you can probably deduce, these will be used to determine in which direction a word should be placed.
Now the fun begins…
Probably the most important thing to remember here is that we are only dealing with so many blocks. The total amount of blocks is 252. Now, with every word, the empty blocks should become fewer and the occupied blocks greater—that seems obvious, but achieving this in code needs a lot of effort. Another thing to consider is where a previous character was placed. Add the following functions to determine the best position for a desired letter:
Private Function BestPos(strWord As String) As _ Tuple(Of Integer, Integer, Integer) Dim lstPos = FindPos(strWord) If lstPos.Count > 0 Then Dim intIndex As Integer = _ rndRandom.[Next](lstPos.Count) Return lstPos(intIndex) End If Return Nothing End Function Private Function FindPos(strWord As String) As _ List(Of Tuple(Of Integer, Integer, Integer)) Dim intMaxWordCount As Integer = 0 Dim lstPos = New List(Of Tuple(Of Integer, _ Integer, Integer))() For x As Integer = 0 To intDirX - 1 For y As Integer = 0 To intDirY - 1 For i As Integer = 0 To intX.Length - 1 Dim intDirection As Integer = i Dim strWordToInsert As String = strWord Dim intCount = DetermineSpace(strWordToInsert, _ x, y, intDirection) If intCount < intMaxWordCount Then Continue For End If If intCount > intMaxWordCount Then lstPos.Clear() End If intMaxWordCount = intCount lstPos.Add(New Tuple(Of Integer, Integer, _ Integer)(x, y, intDirection)) Next Next Next Return lstPos End Function Private Function PosValid(intX As Integer, _ intY As Integer) As Boolean Return intX >= 0 AndAlso intY >= 0 AndAlso intX < _ intDirX AndAlso intY < intDirY End Function
BestPos and FindPos determine the best place to insert the next letter of a word in a sequence whereas PosValid ensures it is a legal block for the desired character.
Add the following code to identify the space in and around each inserted letter and word:
Private Function intSpace() As Integer Dim intCount As Integer = 0 For i As Integer = 0 To X - 1 For j As Integer = 0 To Y - 1 If chrGameBoard(i, j) = " "c OrElse chrGameBoard(i, j) = _ "*"c Then intCount += 1 End If Next Next Return intCount End Function Private Function DetermineSpace(strWord As String, intxX As Integer, _ intyY As Integer, intDirection As Integer) As Integer Dim intResult As Integer = 0 If intDirection = 0 Then For i As Integer = 0 To strWord.Length - 1 Dim xX As Integer = intxX, yY As Integer = intyY + i If Not (PosValid(xX, yY) AndAlso (chrGameBoard(xX, yY) = _ " "c OrElse chrGameBoard(xX, yY) = _ strWord(i))) Then Return -1 End If If PosValid(xX - 1, yY) Then If intHWords(xX - 1, yY) > 0 Then Return -1 End If End If If PosValid(xX + 1, yY) Then If intHWords(xX + 1, yY) > 0 Then Return -1 End If End If If chrGameBoard(xX, yY) = strWord(i) Then intResult += 1 End If Next Else For i As Integer = 0 To strWord.Length - 1 Dim xX As Integer = intxX + i, yY As Integer = intyY If Not (PosValid(xX, yY) AndAlso (chrGameBoard(xX, yY) = _ " "c OrElse chrGameBoard(xX, yY) = _ strWord(i))) Then Return -1 End If If PosValid(xX, yY - 1) Then If intVWords(xX, yY - 1) > 0 Then Return -1 End If End If If PosValid(xX, yY + 1) Then If intVWords(xX, yY + 1) > 0 Then Return -1 End If End If If chrGameBoard(xX, yY) = strWord(i) Then intResult += 1 End If Next End If Dim xPos As Integer = intxX - intX(intDirection) Dim yPos As Integer = intyY - intY(intDirection) If PosValid(xPos, yPos) Then If Not (chrGameBoard(xPos, yPos) = " "c _ OrElse chrGameBoard(xPos, yPos) = "*"c) Then Return -1 End If End If xPos = intxX + intX(intDirection) * strWord.Length yPos = intyY + intY(intDirection) * strWord.Length If PosValid(xPos, yPos) Then If Not (chrGameBoard(xPos, yPos) = " "c OrElse _ chrGameBoard(xPos, yPos) = "*"c) Then Return -1 End If End If Return If(intResult = strWord.Length, -1, intResult) End Function
Add the logic to add the Current word to a Grid:
Private Sub AddToGrid(strWord As String, intxX As Integer, _ intyY As Integer, intDirection As Integer, intVal As Integer) Dim intDir = If(intDirection = 0, intHWords, intVWords) For i As Integer = 0 To strWord.Length - 1 Dim x As Integer = intxX + intX(intDirection) * i Dim y As Integer = intyY + intY(intDirection) * i chrGameBoard(x, y) = strWord(i) intDir(x, y) = intVal Next Dim xPos As Integer = intxX - intX(intDirection) Dim yPos As Integer = intyY - intY(intDirection) If PosValid(xPos, yPos) Then chrGameBoard(xPos, yPos) = "*"c End If xPos = intxX + intX(intDirection) * strWord.Length yPos = intyY + intY(intDirection) * strWord.Length If PosValid(xPos, yPos) Then chrGameBoard(xPos, yPos) = "*"c End If End Sub Public Function Add(strWord As String) As Integer Dim strNextWord As String = strWord Dim tplWordInfo = BestPos(strNextWord) If tplWordInfo IsNot Nothing Then If tplWordInfo.Item3 = 0 Then intHWordsCount += 1 Else intVWordsCount += 1 End If Dim intValue As Integer = If(tplWordInfo.Item3 = _ 0, intHWordsCount, intVWordsCount) AddToGrid(strNextWord, tplWordInfo.Item1, _ tplWordInfo.Item2, tplWordInfo.Item3, intValue) Return tplWordInfo.Item3 End If Return -1 End Function
Add the rest of the class to clean up the class and ensure we are dealing with only text characters:
Public Function IsCharacter(cA As Char) As Boolean Return strLetters.Contains(cA.ToString()) End Function Private Shared Function Helper(Of T)(ByRef tTarget As T, _ ByVal tValue As T) As T tTarget = tValue Return tValue End Function Public Sub Reset() For i As Integer = 0 To intDirX - 1 For j As Integer = 0 To intDirY - 1 chrGameBoard(i, j) = " "c intVWords(i, j) = 0 intHWords(i, j) = 0 intHWordsCount = Helper(intVWordsCount, 0) Next Next End Sub Public Sub GenWords(strWords As IList(Of String)) strWordList = strWords intSol = X * Y dtTime = DateTime.Now Generate(0) chrGameBoard = chrTempGameBoard End Sub Private Sub Generate(intPos As Integer) If intPos >= strWordList.Count OrElse (DateTime.Now - _ dtTime).Minutes > 1 Then Return End If For i As Integer = intPos To strWordList.Count - 1 Dim tBestPos = BestPos(strWordList(i)) If tBestPos IsNot Nothing Then Dim strWord As String = strWordList(i) Dim intVal As Integer = If(tBestPos.Item3 = 0, _ intHWordsCount, intVWordsCount) AddToGrid(strWord, tBestPos.Item1, tBestPos.Item2, _ tBestPos.Item3, intVal) Generate(intPos + 1) RemoveWord(strWord, tBestPos.Item1, tBestPos.Item2, _ tBestPos.Item3) Else Generate(intPos + 1) End If Next Dim iSpace As Integer = intSpace() If iSpace >= intSol Then Return End If intSol = iSpace chrTempGameBoard = TryCast(chrGameBoard.Clone(), Char(,)) End Sub Private Sub RemoveWord(strWord As String, intxX As Integer, _ intyY As Integer, intDirection As Integer) Dim HWordLoc = If(intDirection = 0, intHWords, intVWords) Dim VWordLoc = If(intDirection = 0, intVWords, intHWords) For i As Integer = 0 To strWord.Length - 1 Dim x As Integer = intxX + intX(intDirection) * i Dim y As Integer = intyY + intY(intDirection) * i If VWordLoc(x, y) = 0 Then chrGameBoard(x, y) = " "c End If HWordLoc(x, y) = 0 Next Dim xPos As Integer = intxX - intX(intDirection) Dim yPos As Integer = intyY - intY(intDirection) If PosValid(xPos, yPos) AndAlso FactibleValue(xPos, yPos) Then chrGameBoard(xPos, yPos) = " "c End If xPos = intxX + intX(intDirection) * strWord.Length yPos = intyY + intY(intDirection) * strWord.Length If PosValid(xPos, yPos) AndAlso FactibleValue(xPos, yPos) Then chrGameBoard(xPos, yPos) = " "c End If End Sub Private Function FactibleValue(intxX As Integer, _ intyY As Integer) As Boolean For i As Integer = 0 To intX.Length - 1 Dim x As Integer = intxX + intX(i) Dim y As Integer = intyY + intY(i) If PosValid(x, y) AndAlso (chrGameBoard(x, y) <> _ " "c OrElse chrGameBoard(x, y) = "*"c) Then Return True End If x = intxX - intX(i) y = intyY - intY(i) If PosValid(x, y) AndAlso (chrGameBoard(x, y) <> _ " "c OrElse chrGameBoard(x, y) = "*"c) Then Return True End If Next Return False End Function
Open the MainWindow.xaml.vb file (the code file for your main Window) and add the following member objects:
Private ReadOnly lWords As New List(Of String)() Private lstOrder As List(Of String) Private ReadOnly lstButtons As List(Of Button) Dim cwBoard As New clsCrossword(14, 18)
Here we instantiate a new game board object, the button colors, and the word list objects.
Add the Constructor:
Public Sub New() InitializeComponent() lstButtons = New List(Of Button)() From { _ bcolor2, _ bcolor1, _ bcolor3, _ btn1, _ btn2, _ btn3 _ } For i As Integer = 0 To cwBoard.X - 1 For j As Integer = 0 To cwBoard.Y - 1 Dim bButton = New Button() With { _ .Background = lstButtons(0).Background, _ .Content = "" _ } Grid.SetRow(bButton, i) Grid.SetColumn(bButton, j) grdCrossword.Children.Add(bButton) Next Next End Sub
This sets up our game.
Add the following code to add the entered words into the list for the Crossword:
Private Sub txtWordToAdd_KeyDown(sender As Object, e As KeyEventArgs) _ Handles txtWordToAdd.KeyDown If e.Key = Key.Return Then btnAddWord_Click_1(Nothing, Nothing) End If End Sub Private Sub btnAddWord_Click(sender As Object, e As RoutedEventArgs) _ Handles btnAddWord.Click Dim strWord As String = txtWordToAdd.Text.Trim() If strWord.Length <> 0 Then If lWords.Contains(strWord) Then MessageBox.Show("Word Already Exists.", "Attention", _ MessageBoxButton.OK, MessageBoxImage.Information) Return End If lWords.Add(strWord) lstWords.Items.Add(strWord) End If txtWordToAdd.Text = "" txtWordToAdd.Focus() End Sub
Generate the Crossword:
Private Sub btnGenerate_Click(sender As Object, e As RoutedEventArgs) _ Handles btnGenerate.Click lWords.Reverse() lstOrder = lWords GenerateCrossword() txtWordToAdd.Focus() End Sub Private Sub GenerateCrossword() lstHorizontal.Items.Clear() lstVertical.Items.Clear() cwBoard.Reset() Clear() For Each strWord As String In lstOrder Select Case cwBoard.Add(strWord) Case 0 lstHorizontal.Items.Add(strWord) Exit Select Case 1 lstVertical.Items.Add(strWord) Exit Select Case Else Exit Select End Select Next ShowWords() End Sub Private Sub ShowWords() Dim cBoard = cwBoard.GetBoard Dim intCurrChild As Integer = 0 For i As Integer = 0 To cwBoard.X - 1 For j As Integer = 0 To cwBoard.Y - 1 Dim cLetter As Char = If(cBoard(i, j) = "*"c, _ " "c, cBoard(i, j)) DirectCast(grdCrossword.Children(intCurrChild), _ Button).Content = cLetter.ToString() DirectCast(grdCrossword.Children(intCurrChild), _ Button).Background = If(cLetter <> " "c, _ lstButtons(4).Background, lstButtons(0).Background) intCurrChild += 1 Next Next End Sub
Clear the Crossword:
Private Sub Clear() Dim intCountChildren As Integer = 0 For i As Integer = 0 To cwBoard.X - 1 For j As Integer = 0 To cwBoard.Y - 1 DirectCast(grdCrossword.Children(intCountChildren), _ Button).Content = "" DirectCast(grdCrossword.Children(intCountChildren), _ Button).Background = lstButtons(0).Background intCountChildren += 1 Next Next End Sub
Figure 4: Running
Conclusion
You can do anything with Visual Basic! As you can see, all you need is logic. The crossword you have helped me create today can be expanded greatly. You could add a word list for Hints. You could add a word list that lists the unused words, and you could add export functions to Excel, for example, and even printing capabilities. I’ll let you play further.
-
Main page
-
Chris Merritt
This is the first part of a three video series that demonstrate how to create a crossword puzzle game application using Visual Studio, C#, and WinForms. It’s an intermediate to advanced tutorial.
On this page of the site you can watch the video online (Part 1) C# WinForm Visual Studio Crossword Puzzle Tutorial with a duration of hours minute second in good quality, which was uploaded by the user Chris Merritt 19 February 2014, share the link with friends and acquaintances, this video has already been watched 28,060 times on youtube and it was liked by 225 viewers. Enjoy your viewing!
Игра — Японский кроссворд
1. Описание игры
Японский кроссворд в незаполненном виде представляет собой прямоугольное поле, разбитое на клетки. Можно также представить его как таблицу, в пересечениях строк и столбцов которой находятся клетки японского кроссворда.
При заполнении всех необходимых клеток японского кроссворда они образуют собой рисунок. Иногда к рисунку прилагается ключевое слово, которое надо угадать (метод угадывания ключевых слов мне неизвестен, оттого здесь не описан).
С двух прилежащих друг к другу сторон от поля (обычно сверху и слева) находятся поля чисел.
Для упрощения размер (длину или ширину) в одну клетку японского кроссворда единицей.
Полосой называется заполненный (или подлежащий заполнению) непрерывный прямоугольник, одно из измерений которого (длина или ширина) равно единице.
Таким образом, этот прямоугольник вписывается в строку (столбец). Величина другого измерения прямоугольника задаётся соответствующим числом в поле чисел.
2. Скриншот архива с проектом
3. Пример исходного кода
4. Содержание архива
- исходный код
язык программирования С# NET.Framework 4.5.2, WinForm
среда разработки исходного кода Microsoft Visual Studio Community 2019 PreviewВерсия 16.11.3 Preview 1.0