Welcome Guest!
 VB.NET Helper
 Previous Message All Messages Next Message 
VB .NET Helper Newsletter  Rod Stephens
 Sep 10, 2010 08:30 PDT 

If you haven't seen Cool Math Games.com (http://www.coolmath-games.com),
take a look (right after you finishing posting that book review!). It
has some pretty interesting games. Bloxorz is my current favorite. It
took me a couple of days (not playing continuously) to get through it
all.
-----
Have a great week and thanks for subscribing!

Rod
RodSte-@vb-helper.com

Twitter feeds:
    VBHelper
    CSharpHelper
----------
==========

    VB.NET Contents:
1. New HowTo: Make a picture tiles jigsaw game in Visual Basic .NET
2. New HowTo: Recursively search for files and replace text in them in
Visual Basic .NET

    Both Contents:
3. New Links
==========
++++++++++
      <VB.NET>
++++++++++
==========
1. New HowTo: Make a picture tiles jigsaw game in Visual Basic .NET
http://www.vb-helper.com/howto_net_picture_tiles.html
http://www.vb-helper.com/HowTo/howto_net_picture_tiles.zip

(Picture at http://www.vb-helper.com/howto_picture_tiles_game.png)

This example is a game sort of like a jigsaw puzzle. You load a picture,
which is broken into tiles. You need to put the tiles in their proper
positions to rebuild the image.

The program draws a grid on the background showing where the tiles
belong. It outlines unpositioned tiles in black. Once you place a tile
in its correct position, it is locked in that position, moved to the
back, and outlined in white.

The program is simpler than you might imagine. It uses a Piece class to
represent the current and "home" location of each piece. The program
keeps the pieces in a List(Of Piece) named Pieces.

To draw the board, the program draws the background grid and then just
loops through the pieces drawing them.

Unfortunately drawing images seems to be relatively slow so the program
didn't redraw fast enough when the user was moving a piece and there
were a large number of pieces. Each time the mouse moved, the program
needed to redraw every piece and it was taking too long.

To avoid this problem, the new design uses a background image. When you
start moving a piece, the program makes an image of the background
without the piece that you are moving. Then instead of redrawing every
piece, it only needs to redisplay this background and then draw the
piece you are moving in its current position.

Even that causes some delay building the background image when you first
click on a piece and when you drop the piece. To fix that problem, the
program makes an initial background image that contains all of the
pieces. When you click on a piece, the program fixes the background by
redrawing the pieces that overlap that piece's area.

That may seem difficult but it's actually pretty simple. The code just
calls SetClip to set the Graphics object's clipping region and then
redraws everything. SetClip only allows drawing within the region to
appear. The code still "draws" everything but the graphics system can
clip off parts that lie outside of the clipping region much faster than
it can actually redraw the whole background image.

The following code shows the MakeBackground subroutine that updates the
background image in the Rectangle rect.

' Make the background image without MovingPiece
' confined to the rectangle rect.
Private Sub MakeBackground(ByVal rect As Rectangle)
    Using gr As Graphics = Graphics.FromImage(Background)
        gr.SetClip(rect)
        MakeBackgroundOnGraphics(gr)
    End Using
End Sub

The code creates a Graphics object for the background image and uses
SetClip to restrict drawing to the target area. It then calls
MakeBackgroundOnGraphics to redraw everything.

The following code shows the MakeBackgroundonGraphics subroutine.

' Make the background image without MovingPiece.
Private Sub MakeBackgroundOnGraphics(ByVal gr As Graphics)
    ' Clear.
    gr.Clear(picPuzzle.BackColor)

    ' Draw a grid on the background.
    Using thick_pen As New Pen(Color.DarkGray, 4)
        For y As Integer = 0 To FullPicture.Height Step RowHgt
            gr.DrawLine(thick_pen, 0, y, FullPicture.Width, y)
        Next y
        gr.DrawLine(thick_pen, 0, FullPicture.Height, FullPicture.Width,
FullPicture.Height)

        For x As Integer = 0 To FullPicture.Width Step ColWid
            gr.DrawLine(thick_pen, x, 0, x, FullPicture.Height)
        Next x
        gr.DrawLine(thick_pen, FullPicture.Width, 0, FullPicture.Width,
FullPicture.Height)
    End Using

    ' Draw the pieces.
    Using white_pen As New Pen(Color.White, 3)
        Using black_pen As New Pen(Color.Black, 3)
            For Each a_piece As Piece In Pieces
                ' Don't draw the piece we are moving.
                If (a_piece IsNot MovingPiece) Then
                    gr.DrawImage(FullPicture, _
                        a_piece.CurrentLocation, _
                        a_piece.HomeLocation, _
                        GraphicsUnit.Pixel)
                    If (Not GameOver) Then
                        If (a_piece.IsHome()) Then
                            ' Draw locked pieces with a white border.
                            gr.DrawRectangle(white_pen,
a_piece.CurrentLocation)
                        Else
                            ' Draw locked pieces with a black border.
                            gr.DrawRectangle(black_pen,
a_piece.CurrentLocation)
                        End If
                    End If
                End If
            Next a_piece
        End Using
    End Using

    picPuzzle.Visible = True
    picPuzzle.Refresh()
End Sub

This code draws the grid on the background. It then loops through the
pieces drawing each in its current position. How a piece is outlined
depends on whether that piece is locked and whether the game is over.

*** The moral of the story is that SetClip can sometimes speed up
drawing if you need to redraw a small part of a complex picture. ***

See the code for additional details.

There's still room for improvement.

    - Pieces with jigsaw-style edges rather than rectangles. That would
let you fit pieces by shape and find the picture's edges.
    - Rotating pieces. That would be very advanced.
    - Pieces that stick together. When you join two pieces that belong
together, it would be nice if they stuck so you could move them as a
unit.
==========
2. New HowTo: Recursively search for files and replace text in them in
Visual Basic .NET
http://www.vb-helper.com/howto_net_recursive_replace.html
http://www.vb-helper.com/HowTo/howto_net_recursive_replace.zip

(Picture at http://www.vb-helper.com/howto_recursive_replace.png)

This program recursively searches a directory subtree for files matching
one or more patterns. Optionally it replaces instances of a target
string in those files with a new string.

Both the Find and Find & Replace buttons call the SearchForFiles
subroutine. The only difference is that the Find button passes that
subroutine a null parameter for the "replace with" string.

The following code shows the SearchForFiles subroutine.

' Find files matching the pattern that contain the target string
' and make the replacement if appropriate.
Private Sub SearchForFiles(ByVal lst As ListBox, ByVal start_dir As
String, _
ByVal pattern As String, ByVal from_string As String, ByVal to_string
As String)
    Try
        ' Clear the result ListBox.
        lstFiles.Items.Clear()

        ' Parse the patterns.
        Dim patterns() As String = ParsePatterns(pattern)

        ' If from_string is blank, don't replace.
        If (from_string.Length < 1) Then from_string = Nothing

        Dim dir_info As New DirectoryInfo(start_dir)
        SearchDirectory(lst, dir_info, patterns, from_string, to_string)

        If (from_string Is Nothing) Then
            MessageBox.Show("Found " & lst.Items.Count & " files.")
        Else
            MessageBox.Show("Made replacements in " & lst.Items.Count &
" files.")
        End If
    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try
End Sub

The SearchForFiles subroutine clears the program's result ListBox. It
then calls ParsePatterns to convert the file search pattern into an
array of patterns. For example, if the pattern is "Text Files (*.rtf,
*.txt)" then ParsePatterns returns an array holding the values *.rtf and
*.txt. (Parse pattern uses the String class's IndexOf, SubString, and
Split methods. It's not too complex so it isn't shown here. Download the
example and look at the code to see how it works.)

Next SearchForFiles creates a DirectoryInfo object representing the
directory whose name the user entered. It then calls the SearchDirectory
subroutine to do most of the real work.

The following code shows the SearchDirectory subroutine.

' Find files matching the pattern that contain the target string
' and make the replacement if appropriate.
Private Sub SearchDirectory(ByVal lst As ListBox, ByVal dir_info As
DirectoryInfo, _
ByVal patterns() As String, ByVal from_string As String, ByVal
to_string As String)
    ' Search this directory.
    For Each pattern As String In patterns
        ' Check this pattern.
        For Each file_info As FileInfo In dir_info.GetFiles(pattern)
            ' Process this file.
            ProcessFile(lst, file_info, from_string, to_string)
        Next file_info
    Next pattern

    ' Search subdirectories.
    For Each subdir_info As DirectoryInfo In dir_info.GetDirectories()
        SearchDirectory(lst, subdir_info, patterns, from_string,
to_string)
    Next subdir_info
End Sub

First the subroutine processes this directory's files. For each file
pattern, the code uses GetFiles to get the files that match the pattern.
For each file, the code calls ProcessFile to process the file.

After it processes the files, the code loops through this directory's
subdirectorys calling SearchDirectory for each.

The following code shows the ProcessFile subroutine.

' Replace all occurrences of from_string with to_string.
' Return true if there was a problem and we should stop.
Private Sub ProcessFile(ByVal lst As ListBox, ByVal file_info As
FileInfo, ByVal from_string As String, ByVal to_string As String)
    Try
        If (from_string Is Nothing) Then
            ' Add the file to the list.
            lst.Items.Add(file_info.FullName)
        Else
            ' See if the file contains from_string.
            Dim txt As String =
System.IO.File.ReadAllText(file_info.FullName)
            If (txt.Contains(from_string)) Then
                ' Add the file to the list.
                lst.Items.Add(file_info.FullName)

                ' See if we should make a replacement.
                If (to_string IsNot Nothing) Then
                    System.IO.File.WriteAllText(file_info.FullName, _
                        txt.Replace(from_string, to_string))
                End If
            End If
        End If
    Catch ex As Exception
        MessageBox.Show("Error processing file " & _
            file_info.FullName & "\n" & ex.Message)
    End Try
End Sub

If from_string is null, the program should find all files without
checking to see whether they contain a target string (because there
isn't one). In that case, the program simply adds the file's name to the
result ListBox.

If from_string is not null, the code reads the file into a string and
sees whether it contains from_string. If the file does contain
from_string, the code adds the file's name to the list. If to_string is
also not null, the code replaces from_string with to_string in the text
and writes the text back into the file.

The final piece that I'll mention here is the following, which executes
when you double-click on the list of files found.

' Open the double-clicked file with the system's default application.
Private Sub lstFiles_DoubleClick(ByVal sender As Object, ByVal e As
EventArgs) Handles lstFiles.DoubleClick
    For Each selected_file As String In lstFiles.SelectedItems
        System.Diagnostics.Process.Start(selected_file)
    Next selected_file
End Sub

This code simply loops through the list's selected files and uses
Process.Start to open each in the system's default application for the
file.

*****
Note that this code will try to read and process files that are not text
files. For example, it will read RTF files. This will often succeed,
although it may be confused by binary data or codes (such as RTF codes)
in the file. Searching for files will probably still not cause problems,
but you should be careful when you make replacements in non-text files
because the program may mess up codes.
*****
==========
++++++++++
      <Both>
++++++++++
==========
3. New Links
http://www.vb-helper.com/links.html

Cool Math Games
http://www.coolmath-games.com/
All sorts of interesting games. Two of my favorites are Geography Map
Snaps (you drag states or countries into position on maps) and Bloxorz
(you roll a brick around to make it fall in a hole--more interesting
than it sounds!).
==========
Archives:
    http://www.topica.com/lists/VBHelper
    http://www.topica.com/lists/VB6Helper
    http://www.topica.com/lists/VBNetHelper

Twitter feeds:
    VBHelper
    CSharpHelper

Post questions at:
    http://www.topica.com/lists/VBHelperQA
	
 Previous Message All Messages Next Message 
  Check It Out!

  Topica Channels
 Best of Topica
 Art & Design
 Books, Movies & TV
 Developers
 Food & Drink
 Health & Fitness
 Internet
 Music
 News & Information
 Personal Finance
 Personal Technology
 Small Business
 Software
 Sports
 Travel & Leisure
 Women & Family

  Start Your Own List!
Email lists are great for debating issues or publishing your views.
Start a List Today!

© 2001 Topica Inc. TFMB
Concerned about privacy? Topica is TrustE certified.
See our Privacy Policy.