Buenas noches a todos. Les hago una pregunta.
Tengo en un formulario un TextBox (oculto) un texto en el cual está correctamente escrito, sin errores. Y otro TextBox el cual se ve, en el cual debo intentar escribir lo que está en el TextBox oculto lo más correctamente posible.
De no estar correctamente escrito en este último, que me cuente la cantidad de errores existentes y si es posible, también marcar cuáles fueron los errores.
¿Es posible hacer esto desde VB.NET?
Vi en algunas páginas proyectos hechos donde implementan RichTextBox, y en otros casos algo relacionado con XAML, pero la verdad es que no he conseguido salir de este problema.
Espero que me puedan, al menos orientar de cómo hacerlo en el caso de que sea posible.
PD: Mi idea es intentar hacer algo parecido a lo que es el programa de mecanografía Typing Master en una de sus funciones cuando compara y muestra los errores, como para que tengan una idea de lo que intento realizar.
Muchas gracias a todos, saludos!
Cita de: dont'Exist en 12 Abril 2017, 06:04 AM
Tengo en un formulario un TextBox (oculto) un texto en el cual está correctamente escrito, sin errores. Y otro TextBox el cual se ve, en el cual debo intentar escribir lo que está en el TextBox oculto lo más correctamente posible.
De no estar correctamente escrito en este último, que me cuente la cantidad de errores existentes y si es posible, también marcar cuáles fueron los errores.
Básicamente eso es lo que hace el juego del Mastermind. Lo único que cambia es que en el mastermind, se usan bolas de colores y tu usas letras y bueno, como es un juego se da un límite máximo de intentos.
Guglea si qieres buscando código.
Cita de: dont'Exist en 12 Abril 2017, 06:04 AM
¿Es posible hacer esto desde VB.NET?
Qué, cómo.?????????
Cita de: dont'Exist en 12 Abril 2017, 06:04 AM
Vi en algunas páginas proyectos hechos donde implementan RichTextBox, y en otros casos algo relacionado con XAML, pero la verdad es que no he conseguido salir de este problema.
Se puede complicar uno la vida todo lo que quiera, pero basta con tu idea original, incluso sin siquiera ese textbox oculto, basta que esté en una variable del código.
Cita de: dont'Exist en 12 Abril 2017, 06:04 AM
PD: Mi idea es intentar hacer algo parecido a lo que es el programa de mecanografía Typing Master en una de sus funciones cuando compara y muestra los errores, como para que tengan una idea de lo que intento realizar.
Ahora mismo, no caigo en cual es es eprograma (hay tantos...). Pero ya te digo, que lo que quieres hacer es el típico mastermind, pero más simplificado aún.
Una idea aproximada de lo que tienes que hacer:
- Crear una propiedad que indique el tamaño (númeor de caracteres de la palabra). (esto puede ser una opción en un menú o bien con un control "slider", "scrollhorizontal", etc... siempre entre un rango mínimo y máximo (min=6, Máx=16, por ejemplo).
- Crear una función Nuevo: que genere una palabra al azar del tamaño indicado, y guardarla en un campo oculto, convertida en un array de caracteres.
- Crear una función Intento (llamada desde un botón y con un texto, que yace sobre un control de texto (textbox, es más que sufieciente, si quieres colorealo, para que sea más 'atractivo'...
--- Tu escribes en el texto, en el evento 'change' del textbox, miras si la palaba escrita tiene el largo (ni más ni menos) que se requiere y si es que sí, activas el botón para "Escrutar", si no, sigue desactivado.
--- También puedes dejar siempre activo el botón y no hacer nada en eventos del texto, y cuando se pulse el botón, miras si el texto contiene el númeor de caracteres concreto, si no es así, un mensaje al usuario de 'faltan/sobran letras'... el código del botón.
--- El botón, invoca la función Intento, pasándole el texto que contiene el control si devuelve false, pegar de nuevo el texto 'Palabra' en el textbox.
Y el código de la función lo que hará es:
Funcion Intento(byref Palabra as string) as boolean
--- Recibir un texto del mismo largo que la palabra oculta.
--- Convertirlo a un array de caracteres.
--- Iniciar un bucle, que recorra desde 0 hasta el final del array.
--- Dentro del bucle:
---------- Si Oculto(k) <> TxtUser(k) luego
--------------- TxtUser(k)= "*"
--------------- n +=1
---------- Fin si
--- fin bucle
--- Si n> 0 entonces 'implica que no todos los caracteres fueron encontrados
-------- Convertir el array txtUser que ha sido modificado, indicando con *, cada carácter donde falló, a una cadena de texto, reescribiendo el parámetro: 'Palabra' (se devuelve por referencia).
------------ El botón que recibe de vuelta False, pega entonces el parámetro en el textbox.
--- Si no
------- Devolver: True
------- El botón que recibe el true saca un Mensaje: enhorabuena acertaste la palabra oculta...
fin función.
p.d.: Eso sí, antes de todo tú decides si se truncan mayúsculas a inúsculas o viceversa o no... Así : ¿MARTE=MarTE???, y por tanto obra en consecuencia.
texto= texto.toupper ó texto= texto.ToLower, o nada si se distingue capitalización de caracteres.
Hola.
Si quieres algo sofisticado entonces lee sobre el algoritmo Diff y el problema LCS (Longest Common Subsequence) e implementa el algoritmo. Existen librerías Diff gratuitas para .NET por lo que no tienes que hacer practicamente nada.
Aparte, lo que pides se puede interpretar de muchas maneras y se puede implementar de infinitas formas dependiendo de las necesidades del programa, así que como no especifiques un poco más siendo breve y conciso aclarando punto por punto como debería comportarse el algoritmo ante cada situación de coincidencia o no coincidencia pues... vamos mal, jeje.
De todas formas te voy a mostrar dos ejemplos que he escrito con los que te puedas hacer una idea de como implementar un algoritmo básico de comparación de cadenas de texto. Ambos ejemplos evaluan las diferencias y usan un RichTextBox para colorear los caracteres que coinciden y los que no, pero ambos ejemplos tienen propósitos distintos para distintos escenarios... pues como ya dije hay infinitas maneras de implementar esto y depende de las necesidades del programa.
(http://i.imgur.com/i3BwKy8.gif)
El primer ejemplo está enfocado a la evaluación por individual del caracter actual que se haya escrito en el control de edición, esto quiere decir que si modificas otro caracter no se actualizarán las diferencias/colorización del resto de caracteres en el RichTextBox.
Public NotInheritable Class Form1 : Inherits Form
Private ReadOnly Property OrgText As String = "Hello World!"
Private ReadOnly Property CurText As String
Get
If (Me.RichTextBox1 IsNot Nothing) Then
Return Me.RichTextBox1.Text
Else
Return String.Empty
End If
End Get
End Property
Private Sub RichTextBox1_TextChanged(sender As Object, e As EventArgs) Handles RichTextBox1.TextChanged
Dim rtb As RichTextBox = DirectCast(sender, RichTextBox)
Dim chPos As Integer = (rtb.SelectionStart - 1)
Dim ch As Char = rtb.Text.Substring(chPos, 1)
Dim diffState As TriState
If (chPos >= Me.OrgText.Length) Then
diffState = TriState.UseDefault
ElseIf (Me.OrgText(chPos) = ch) Then
diffState = TriState.True
Else
diffState = TriState.False
End If
ColorizeDifference(rtb, chPos, diffState)
End Sub
Friend Shared Sub ColorizeDifference(ByVal rtb As RichTextBox, ByVal charPos As Integer, ByVal diffState As TriState)
Dim oldSelectionStart As Integer = rtb.SelectionStart
Dim oldSelectionLength As Integer = rtb.SelectionLength
Dim fontStyle As FontStyle = rtb.Font.Style
rtb.SelectionStart = charPos
rtb.SelectionLength = 1
Select Case diffState
Case TriState.True ' El caracter coincide.
rtb.SelectionColor = Color.YellowGreen
fontStyle = fontStyle And Not FontStyle.Underline
Case TriState.False ' El caracter no coincide.
rtb.SelectionColor = Color.IndianRed
fontStyle = fontStyle Or FontStyle.Underline
Case TriState.UseDefault ' El índice del caracter está fuera de rango.
rtb.SelectionColor = Color.Gray
fontStyle = fontStyle Or FontStyle.Underline
End Select
Using font As New Font(rtb.Font, fontStyle)
rtb.SelectionFont = font
End Using
rtb.SelectionStart = oldSelectionStart
rtb.SelectionLength = oldSelectionLength
rtb.ResumeLayout(performLayout:=True)
End Sub
End Class
El segundo ejemplo está enfocado a la evaluación del texto entero; cada vez que se modifique el texto del RichTextBox se actualizarán las diferencias/colorización de todos los caracteres. Este es el código que he usado en la imagen que he compartido arriba.
Public NotInheritable Class Form1 : Inherits Form
Private ReadOnly Property OrgText As String = "Hello World!"
Private ReadOnly Property CurText As String
Get
If (Me.RichTextBox1 IsNot Nothing) Then
Return Me.RichTextBox1.Text
Else
Return String.Empty
End If
End Get
End Property
Private Sub RichTextBox1_TextChanged(sender As Object, e As EventArgs) Handles RichTextBox1.TextChanged
Dim diffIndices As Dictionary(Of Integer, TriState) = GetDifferences(Me.OrgText, Me.CurText)
ColorizeDifferences(Me.RichTextBox1, diffIndices)
End Sub
Friend Shared Function GetDifferences(ByVal orgText As String, ByVal curText As String) As IDictionary(Of Integer, TriState)
Dim orgChars As Char() = orgText.ToArray()
Dim curChars As Char() = curText.ToArray()
Dim orgLength As Integer = orgChars.Length
Dim curLength As Integer = curChars.Length
Dim diffIndices As New Dictionary(Of Integer, TriState)(curLength, EqualityComparer(Of Integer).Default)
For i As Integer = 0 To (curLength - 1)
If (i < orgLength) Then
diffIndices.Add(i, (orgChars(i) = curChars(i)))
Else
diffIndices.Add(i, TriState.UseDefault)
End If
Next i
Return diffIndices
End Function
Friend Shared Sub ColorizeDifferences(ByVal rtb As RichTextBox, ByVal diffIndices As IDictionary(Of Integer, TriState))
Dim oldSelectionStart As Integer = rtb.SelectionStart
Dim oldSelectionLength As Integer = rtb.SelectionLength
Dim fontStyle As FontStyle = rtb.Font.Style
rtb.SuspendLayout()
For Each kvp As KeyValuePair(Of Integer, TriState) In diffIndices
rtb.SelectionStart = kvp.Key
rtb.SelectionLength = 1
Select Case kvp.Value
Case TriState.True ' El caracter coincide.
rtb.SelectionColor = Color.YellowGreen
fontStyle = fontStyle And Not FontStyle.Underline
Case TriState.False ' El caracter no coincide.
rtb.SelectionColor = Color.IndianRed
fontStyle = fontStyle Or FontStyle.Underline
Case TriState.UseDefault ' El índice del caracter está fuera de rango.
rtb.SelectionColor = Color.Gray
fontStyle = fontStyle Or FontStyle.Underline
End Select
Using font As New Font(rtb.Font, fontStyle)
rtb.SelectionFont = font
End Using
Next
rtb.SelectionStart = oldSelectionStart
rtb.SelectionLength = oldSelectionLength
rtb.ResumeLayout(performLayout:=True)
End Sub
End Class
¡Saludos!
Muchas gracias a ambos. Me sirvieron de guía, ahora mismo estoy tratando de ajustarlo a lo que necesito... Aunque tambien estuve probando con RichTextbox.Find() y he obtenido resultados parecidos.
Saludos