Rudi
  • Home
  • About
  • Contact
  • VB.Net
    • Flippin
    • Calculator
    • Mine Scout
    • Slot Machine
    • Snake
    • Find Words
    • Accounting using Child forms
  • Excel
    • Calendar 1
    • Calendar 2
    • Sudoku
    • Mine Scout
    • Tilexcel
    • ExceLudo
    • Alphabet Game
    • Word Search
    • Redback
  • C# Child Forms
  • C# Struct Array
Redback
Picture
In this game move the numbers so that they descend from 13 down to 1. To do this select the number to be moved, then hold down Ctrl and select an empty cell with a number above one higher than the cell to be moved. Click the Move Cell(S) button.
Picture
It's possible to move more than on cell. Here I've moved the 11 and 10 in one operation.
Picture
The yellow boxes are Rectangles, the top 3 of which run macros.

There are some global variables required.

Option Explicit

Public Numbers(103) As Integer
Public intCellsUsed As Integer
Public blnFinished As Boolean

We have to arrange 8 suits of 13  to 1 stacks which equates to 104 numbers in total.

Start with the New button. 

Sub NewGame()

  Dim intRnd As Integer
  Dim intTemp As Integer
  
  Dim intRow As Integer
  Dim intCol As Integer
  
  Range("A2:J50").ClearContents
  intCellsUsed = 0
  blnFinished = False
  
  Randomize
  
  'Fill the array
  
  For intRow = 1 To 13
    For intCol = 1 To 8
    
      Numbers(intCellsUsed) = intRow
      intCellsUsed = intCellsUsed + 1
  
    Next intCol
  Next intRow
  
  'Shuffle the array
  
  For intCellsUsed = 0 To 103
  
    intRnd = Int(103 * Rnd) + 1
    
    intTemp = Numbers(intRnd)
    Numbers(intRnd) = Numbers(intCellsUsed)
    Numbers(intCellsUsed) = intTemp
    
  Next intCellsUsed
  
  'Display initial numbers
  
  intCellsUsed = 0
  
  For intRow = 2 To 6
    For intCol = 1 To 10
  
      Cells(intRow, intCol) = Numbers(intCellsUsed)
      intCellsUsed = intCellsUsed + 1
    
    Next intCol
  Next intRow
  
  For intCol = 1 To 4
  
    Cells(intRow, intCol) = Numbers(intCellsUsed)
    intCellsUsed = intCellsUsed + 1
    
  Next intCol
  
  'Show how many times Add Numbers is still to be clicked.
  
  [L8] = 5

End Sub

I added a routine just after the Dims to guard against accidentally clicking the New button.

  If Not blnFinished Then
    If MsgBox("Start new game?", vbYesNo, "New game") = vbNo Then Exit Sub
  End If

A number of checks are in the MoveCells procedure to ensure the move is legal.

Sub MoveCells()

  If blnFinished Then Exit Sub

  Dim cell As Range
  Dim intCell As Integer
  Dim strCell_1 As String
  Dim strCell_2 As String
  Dim intRow_1 As Integer
  Dim intRow_2 As Integer
  Dim intCol_1 As Integer
  Dim intCol_2 As Integer
  Dim intNum_1 As Integer
  Dim intNum_2 As Integer
  Dim intRows As Integer
  Dim intRow As Integer
  Dim intCol As Integer
  
  intCell = 1
  
  If Selection.Cells.Count <> 2 Then
    MsgBox "Please select 2 cells."
    Exit Sub
  End If
  
  'Record the details of each cell selected
  
  For Each cell In Selection.Cells
  
    If intCell = 1 Then
    
      strCell_1 = cell.Address
      intRow_1 = Range(strCell_1).Row
      intCol_1 = Range(strCell_1).Column
      intNum_1 = Range(strCell_1).Value
  
    Else
    
      strCell_2 = cell.Address
      intRow_2 = Range(strCell_2).Row
      intCol_2 = Range(strCell_2).Column
      intNum_2 = Range(strCell_2).Value
      
    End If
    
    intCell = 2
    
  Next cell
  
  'Exit if illegal moves
      
  If Range(strCell_1) = "" Then
    MsgBox "First cell can't be empty"
    Exit Sub
  End If
  
  If Range(strCell_2).Value <> 0 Then
    MsgBox "Second cell must be empty"
    Exit Sub
  End If
  
  If intRow_2 <> 2 Then
    If intNum_1 <> Cells(intRow_2 - 1, intCol_2) - 1 Then
      MsgBox "Cell value of " & Cells(intRow_2 - 1, intCol_2).Address _
      & " above Target cell must be " & intNum_1 + 1
      Exit Sub
    End If
  End If
  
  intCell = 0
    
  Do
  
  intCell = intCell + 1
  
  If Cells(intRow_1 + intCell, intCol_1) <> "" Then
    If Cells(intRow_1 + intCell, intCol_1) + 1 _
    <> Cells(intRow_1 + intCell - 1, intCol_1) Then
    
      MsgBox "Cell values are not descending."
      Exit Sub
    End If
    
  End If
  
  Loop Until Cells(intRow_1 + intCell, intCol_1) = ""
  
  'Move the cells
  
  intRow = 0
  
  For intRows = intRow_1 To intRow_1 + intCell
  
    Cells(intRow_2 + intRow, intCol_2) = Cells(intRow_1 + intRow, intCol_1)
    Cells(intRow_1 + intRow, intCol_1) = ""
    intRow = intRow + 1
    
  Next intRows
  
  'Check whether column of 13 can be deleted
  'Add the Call once the Sub is written

    
  Call CheckFor13(intRow_2 + intRow - 2, intCol_2)
      
  'Is the game finished?
  blnFinished = True
  
  For intCol = 1 To 10
    If Cells(2, intCol) <> "" Then
      blnFinished = False
    End If
  Next intCol
  
  If blnFinished Then
  
    For intCol = 1 To 10

      Cells(4, intCol) = Mid("*Finished*", intCol, 1)
      Cells(6, intCol) = Mid("Well Done!", intCol, 1)

    Next intCol
    
  End If
  
End Sub

Since I use Ctrl to select the second cell I added a shortcut to the MoveCells procedure.
Press Alt + F8, select the procedure, then Options, and press Shift + X. So, straight after holding down Ctrl to select the second cell I press Ctrl + Shift + X to move the cell(s).

It didn't take long to get used to and to become fluid and quite fast. For a better look add this line just before the End If above.

    Range("A1").Select

We'd better delete any completed stacks!

Sub CheckFor13(intCheckRow As Integer, intCheckCol As Integer)
  
  Dim intLoop As Integer
  Dim intRow As Integer
  
  If Cells(intCheckRow, intCheckCol) <> 1 Then Exit Sub
  
  For intLoop = intCheckRow - 1 To 2 Step -1
    
    If Cells(intLoop, intCheckCol) <> Cells(intLoop + 1, intCheckCol) + 1 Then Exit Sub
    
    If Cells(intLoop, intCheckCol) = 13 Then
    
        MsgBox "Removing column of 13."
        For intRow = intCheckRow To intLoop Step -1
          Cells(intRow, intCheckCol) = ""
        Next intRow
        
    End If
    
  Next intLoop

End Sub

Which brings me to the last procedure.

Sub AddNumbers()
  
  If blnFinished Then Exit Sub
  
  Dim intRow As Integer
  Dim intCol As Integer
  Dim intCells As Integer
  
  'Exit if there is a vacant first spot in row 2
  
  For intCol = 1 To 10
  
    If Cells(2, intCol) = "" Then
    
      MsgBox "Fill the empty row 2 cell(s)"
      Exit Sub
      
    End If
    
  Next intCol
  
  For intCol = 1 To 10
  
    intCells = 0
    
    For intRow = 2 To 50
    
      If Cells(intRow, intCol) = "" Then
        
        intCells = intCells + 1
        
        If intCells = 11 Then Exit Sub
        If intCellsUsed > 103 Then Exit Sub
        
        Cells(intRow, intCol) = Numbers(intCellsUsed)
        
        'If it's a 1 then check whether 13 can be deleted
        
        Call CheckFor13(intRow, intCol)
        
        intCellsUsed = intCellsUsed + 1
        Exit For
        
      End If
      
    Next intRow
  Next intCol
  
  [L8] = [L8] - 1
  
  End Sub

Picture
Proudly powered by Weebly