Как сделать кроссворд в windows forms

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:

Grid

Figure 2: Grid

A Textbox and two buttons, as shown in Figure 3:

Buttons and TextBox

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

Running

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.

  1. Main page

  2. 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

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Windows form button close form
  • Windows embedded compact 7 системные требования
  • Как на windows phone установить xap на windows phone
  • Acronis для windows server 2012
  • Windows server принцип работы