Dominó BRAV

Dominó BRAV es una variante que me inventé del tradicional juego de dominó, que consiste en hacer coincidir colores con las cartas adyacentes.

Las cartas son cuadradas y están divididas en cuatro sectores coloreados en diferentes combinaciones de blanco, rojo, azul y verde (de ahí el nombre BRAV), de modo que al colocar una carta junto a otra dos sectores de cada una quedan en contacto con los de la otra.

Cada sector que coincide con el color del sector correspondiente de la carta adyacente es un punto para el jugador que colocó la carta.

He aquí el aspecto de la "mesa de juego". La interfaz es mínima y no hay mensajes, pero funciona así.



Instrucciones para el Dominó Brav.

Al hacer clic sobre el "mazo" que está abajo a la derecha pregunta si quiere empezar un nuevo juego. Esto se puede hacer en cualquier momento para iniciar otro juego aunque haya uno ya empezado.

Al responder que sí, parecen las cartas. El primer turno es del jugador de la derecha.

Al hacer clic izquierdo sobre una carta ésta se "activa" y se desplaza ligeramente. Al hacer clic nuevamente se "desactiva".

Para girar la carta hacer clic derecho sobre la carta activa tantas veces como sea necesario hasta obtener la posición deseada.

Una vez activada y rotada la carta convenientemente, hacer clic sobre el lugar donde se desea jugar la carta.

La cantidad de coincidencias obtenida aparece en en el recuadrito debajo de las cartas.

La carta jugada se repone inmediatamente con una nueva del mazo. La cantidad de cartas remanentes en el mazo aparece en el recuadrito abajo en el centro.

Una vez jugada una carta, el turno pasa al otro jugador.

Cuando el contador de cartas remanentes llega a 0 el juego prosigue pero ya no se reponen las cartas jugadas.

El juego termina cuando ambos jugadores han jugado todas las cartas.

Gana el que obtuvo más coincidencias.


Código fuente. (Descargar)

El juego está programado en Visual Basic 6.0. Los nombres de las variables y funciones, así como los comentarios, están en inglés.

Archivo de proyecto BravDomino.vbp

Type=Exe
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\Windows\SysWOW64\stdole2.tlb#OLE Automation
Form=frmDominoTable.frm
Class=Brav; Brav.cls
Class=BravDeck; BravDeck.cls
Class=BravCard; BravCard.cls
Class=CardNode; CardNode.cls
Module=mdlBravDomino; mdlBravDomino.bas
Startup="frmDominoTable"
HelpFile=""
ExeName32="BravDomino.exe"
Command32=""
Name="BravDomino"
HelpContextID="0"
CompatibleMode="0"
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=0
ServerSupportFiles=0
VersionCompanyName="VBProjects"
CompilationType=0
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=0
Unattended=0
Retained=0
ThreadPerObject=0
MaxNumberOfThreads=1
 

Formulario principal frmDominoTable.frm

VERSION 5.00
Begin VB.Form frmDominoTable
   BackColor       =   &H00008000&
   BorderStyle     =   1  'Fixed Single
   Caption         =   "Brav Domino"
   ClientHeight    =   8295
   ClientLeft      =   45
   ClientTop       =   390
   ClientWidth     =   8505
   LinkTopic       =   "Form1"
   MaxButton       =   0   'False
   ScaleHeight     =   8295
   ScaleWidth      =   8505
   StartUpPosition =   2  'CenterScreen
   WindowState     =   2  'Maximized
   Begin VB.PictureBox picRight
      Appearance      =   0  'Flat
      BackColor       =   &H00008000&
      BorderStyle     =   0  'None
      ForeColor       =   &H80000008&
      Height          =   1215
      Index           =   0
      Left            =   7200
      ScaleHeight     =   1215
      ScaleWidth      =   1215
      TabIndex        =   3
      Top             =   120
      Width           =   1215
   End
   Begin VB.PictureBox picLeft
      Appearance      =   0  'Flat
      BackColor       =   &H00008000&
      BorderStyle     =   0  'None
      ForeColor       =   &H80000008&
      Height          =   1215
      Index           =   0
      Left            =   120
      ScaleHeight     =   1215
      ScaleWidth      =   1215
      TabIndex        =   2
      Top             =   120
      Width           =   1215
   End
   Begin VB.PictureBox picBack
      Appearance      =   0  'Flat
      BackColor       =   &H00808000&
      BorderStyle     =   0  'None
      ForeColor       =   &H80000008&
      Height          =   1215
      Left            =   7080
      ScaleHeight     =   1215
      ScaleWidth      =   1215
      TabIndex        =   1
      Top             =   6840
      Width           =   1215
   End
   Begin VB.PictureBox picPlay
      Appearance      =   0  'Flat
      BackColor       =   &H0080FF80&
      BorderStyle     =   0  'None
      FontTransparent =   0   'False
      ForeColor       =   &H80000008&
      Height          =   1215
      Index           =   0
      Left            =   3720
      ScaleHeight     =   1215
      ScaleWidth      =   1215
      TabIndex        =   0
      Top             =   3600
      Width           =   1215
   End
   Begin VB.Label lblNodeCount
      Alignment       =   2  'Center
      BeginProperty Font
         Name            =   "MS Reference Sans Serif"
         Size            =   12
         Charset         =   0
         Weight          =   700
         Underline       =   0   'False
         Italic          =   0   'False
         Strikethrough   =   0   'False
      EndProperty
      Height          =   375
      Left            =   3840
      TabIndex        =   6
      Top             =   7800
      Width           =   855
   End
   Begin VB.Label lblRight
      Alignment       =   2  'Center
      BeginProperty Font
         Name            =   "MS Reference Sans Serif"
         Size            =   12
         Charset         =   0
         Weight          =   700
         Underline       =   0   'False
         Italic          =   0   'False
         Strikethrough   =   0   'False
      EndProperty
      Height          =   375
      Left            =   7440
      TabIndex        =   5
      Top             =   6240
      Width           =   855
   End
   Begin VB.Label lblLeft
      Alignment       =   2  'Center
      BeginProperty Font
         Name            =   "MS Reference Sans Serif"
         Size            =   12
         Charset         =   0
         Weight          =   700
         Underline       =   0   'False
         Italic          =   0   'False
         Strikethrough   =   0   'False
      EndProperty
      Height          =   375
      Left            =   240
      TabIndex        =   4
      Top             =   6600
      Width           =   855
   End
End
Attribute VB_Name = "frmDominoTable"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit

Private m_Deck As BravDeck

Private m_LeftHand(0 To 4) As BravCard
Private m_RightHand(0 To 4) As BravCard

Private m_iLeftIndex As Integer
Private m_iRightIndex As Integer

Private m_iLeftBorder As Integer
Private m_iRightBorder As Integer
Private m_iCardSize As Integer

Private m_iTableTopX As Integer
Private m_iTableTopY As Integer
Private m_iTableBottomX As Integer
Private m_iTableBottomY As Integer

Private m_Root As CardNode
Private m_iPicture As Integer
Private m_bLeft As Boolean

Private Sub Form_Load()
  Set m_Deck = New BravDeck
 
  m_Deck.UseFirst = False
 
  SetSides
 
  Randomize
End Sub

Private Sub Form_Paint()
  Line
(m_iTableTopX, m_iTableTopY)- _
    (m_iTableBottomX, m_iTableBottomY),
&H80FF80, BF
End Sub

Private Sub Form_Resize()
  If WindowState <> 1 Then SetLayout  ' If not minimized
End Sub

Private Sub SetLayout()
  Dim I As Integer
 
  m_iCardSize = _

    (ScaleHeight - c_DoubleMargin * (c_TableHeight + 1)) \ _

    c_TableHeight
  I = (ScaleWidth - c_DoubleMargin * 4) \ (c_TableWidth + 2)
 
  If I < m_iCardSize Then m_iCardSize = I
 
  m_iLeftBorder = c_DoubleMargin
  With picLeft(0)
    .Width = m_iCardSize
    .Height = m_iCardSize
    .Top = c_DoubleMargin
    .Left = m_iLeftBorder
  End With
 
  For I = 1 To 4
    With picLeft(I)
      .Width = m_iCardSize
      .Height = m_iCardSize
      .Top = BottomSide(picLeft(I - 1)) + c_DoubleMargin
      .Left = m_iLeftBorder
      .Visible = True
    End With
  Next
 
  With lblLeft
    .Top = BottomSide(picLeft(4)) + c_DoubleMargin
    .Left = RightSide(picLeft(4)) - .Width
  End With
 
  With picRight(0)
    .Width = m_iCardSize
    .Height = m_iCardSize
    m_iRightBorder = ScaleWidth - .Width - c_DoubleMargin
    .Top = c_DoubleMargin
    .Left = m_iRightBorder
  End With
 
  For I = 1 To 4
    With picRight(I)
      .Width = m_iCardSize
      .Height = m_iCardSize
      .Top = BottomSide(picRight(I - 1)) + c_DoubleMargin
      .Left = m_iRightBorder
      .Visible = True
    End With
  Next
 
  With lblRight
    .Top = BottomSide(picRight(4)) + c_DoubleMargin
    .Left = picRight(4).Left
  End With
 
  With lblNodeCount
    .Top = ScaleHeight - .Height - c_DoubleMargin
    .Left = (ScaleWidth - .Width) / 2
    .Caption = 35 - m_iPicture
  End With
 
  With picPlay(0)
    .Width = m_iCardSize
    .Height = m_iCardSize
    .Top = (lblNodeCount.Top - m_iCardSize) / 2
    .Left = (ScaleWidth - .Width) / 2
   
    m_iTableTopY = _

      .Top - m_iCardSize * c_MaxY - c_DoubleMargin
    m_iTableTopX = _

      .Left - m_iCardSize * c_MaxX - c_DoubleMargin
    m_iTableBottomY = _

      .Top + m_iCardSize * (c_MaxY + 1) + c_DoubleMargin
    m_iTableBottomX = _

      .Left + m_iCardSize * (c_MaxX + 1) + c_DoubleMargin
  End With
 
  With picBack
    .Width = m_iCardSize
    .Height = m_iCardSize
    .Top = ScaleHeight - .Height - c_DoubleMargin
    .Left = picRight(0).Left
  End With
End Sub

Private Sub SetNeighbours(ByRef Node As CardNode)
  Dim I As Integer
  Dim N As CardNode
  Dim P As PictureBox
  Dim pic As PictureBox
 
  Set pic = Node.Picture
 
  For I = 0 To 3
    Set N = Node.Neighbour(I)
    If Not N Is Nothing Then
      If N.Picture Is Nothing Then
        m_iPicture = m_iPicture + 1
        Load picPlay(m_iPicture)
       
        Set P = picPlay(m_iPicture)
       
        With P
          .Width = m_iCardSize
          .Height = m_iCardSize
         
          Select Case I
            Case eSideTop
              .Top = pic.Top - .Height
              .Left = pic.Left
            Case eSideRight
              .Top = pic.Top
              .Left = RightSide(pic)
            Case eSideBottom
              .Top = BottomSide(pic)
              .Left = pic.Left
            Case eSideLeft
              .Top = pic.Top
              .Left = pic.Left - .Width
          End Select
        End With
 
        With N
          Set .Picture = P
          .Index = m_iPicture
        End With
      End If
    End If
  Next
End Sub

Private Sub lblLeft_Click()
  CheckAll m_Root    ' Just for debugging
End Sub

Private Sub lblRight_Click()
  UncheckAll m_Root
  ' Just for debugging
End Sub

Private Sub picBack_Click()
  If MsgBox("Start new game?", vbQuestion + vbYesNo, "New game") = _

    vbYes Then NewGame
End Sub

Private Sub picBack_Paint()
  With picBack
    .Cls
    .FillStyle = 7
    picBack.Line _

      (30, 30)-Step(.ScaleWidth - 75, .ScaleHeight - 75), , B
  End With
End Sub

Private Sub SetSides()
  Dim I As Integer
  Dim C As BravCard
 
  Set C = New BravCard
  With C
    Set .Picture = picLeft(0)
    .Index = 0
  End With
  Set m_LeftHand(0) = C
 
  For I = 1 To 4
    Load picLeft(I)
   
    Set C = New BravCard
    With C
      Set .Picture = picLeft(I)
      .Index = I
    End With
    Set m_LeftHand(I) = C
  Next
 
  Set C = New BravCard
  With C
    Set .Picture = picRight(0)
    .Index = 0
  End With
  Set m_RightHand(0) = C
 
  For I = 1 To 4
    Load picRight(I)
   
    Set C = New BravCard
    With C
      Set .Picture = picRight(I)
      .Index = I
    End With
    Set m_RightHand(I) = C
  Next
End Sub

Private Sub SetRoot()
  Set m_Root = New CardNode
 
  With m_Root
    .Index = 0
    .X = 0
    .Y = 0
    Set .Picture = picPlay(0)
    Set .Brav = m_Deck.Card(0)
  End With
 
  SetNeighbours m_Root
End Sub

Public Function FindNode(ByRef Node As CardNode, _

  ByVal iIndex As Integer) As CardNode
  Dim N As CardNode
  Dim I As Integer
 
  If Node Is Nothing Then
    Set N = Nothing
  ElseIf Node.Checked Then
    Set N = Nothing
  Else
    Node.Checked = True
    If Node.Index = iIndex Then
      Set N = Node
      UncheckAll Node
    Else
      For I = 0 To 3
        Set N = FindNode(Node.Neighbour(I), iIndex)
        If Not N Is Nothing Then Exit For
      Next
    End If
  End If
 
  Set FindNode = N
End Function

Private Sub NewGame()
  Dim I As Integer
 
  If Not m_Root Is Nothing Then m_Root.Dispose
 
  Do While m_iPicture
    Unload picPlay(m_iPicture)
    m_iPicture = m_iPicture - 1
  Loop
 
  SetRoot
 
  With m_Deck
    .Mix
   
    For I = 0 To 4
      Set m_LeftHand(I).Brav = .NextCard
      Set m_RightHand(I).Brav = .NextCard
    Next
 
    lblNodeCount = 35 - .Top
  End With
 
  m_iLeftIndex = -1
  m_iRightIndex = -1
  lblLeft = 0
  lblRight = 0
End Sub

Private Sub picLeft_MouseDown(Index As Integer, _

  Button As Integer, Shift As Integer, X As Single, Y As Single)
  If Not m_bLeft Then Exit Sub
  If m_LeftHand(Index).IsEmpty Then Exit Sub
 
  If Button And vbRightButton Then
    If Index <> m_iLeftIndex Then Exit Sub
    m_LeftHand(m_iLeftIndex).RotateRight
    BestNode m_Root, m_LeftHand(m_iLeftIndex), True
    UncheckAll m_Root
  Else
    If m_iLeftIndex >= 0 Then picLeft(m_iLeftIndex).Left = m_iLeftBorder
    If m_iLeftIndex = Index Then
      m_iLeftIndex = -1
    Else
      picLeft(Index).Left = m_iLeftBorder + c_DoubleMargin
      m_iLeftIndex = Index
      BestNode m_Root, m_LeftHand(m_iLeftIndex), True
      UncheckAll m_Root
    End If
  End If
End Sub

Private Sub picRight_MouseDown(Index As Integer, _

  Button As Integer,
Shift As Integer, X As Single, Y As Single)
  If m_bLeft Then Exit Sub
  If m_RightHand(Index).IsEmpty Then Exit Sub
 
  If Button And vbRightButton Then
    If Index <> m_iRightIndex Then Exit Sub
    m_RightHand(m_iRightIndex).RotateRight
    BestNode m_Root, m_RightHand(m_iRightIndex), True
    UncheckAll m_Root
  Else
    If m_iRightIndex >= 0 Then _

      picRight(m_iRightIndex).Left = m_iRightBorder
    If m_iRightIndex = Index Then
      m_iRightIndex = -1
    Else
      picRight(Index).Left = m_iRightBorder - c_DoubleMargin
      m_iRightIndex = Index
      BestNode m_Root, m_RightHand(m_iRightIndex), True
      UncheckAll m_Root
    End If
  End If
End Sub

Private Sub picLeft_Paint(Index As Integer)
  m_LeftHand(Index).Draw
End Sub

Private Sub picRight_Paint(Index As Integer)
  m_RightHand(Index).Draw
End Sub

Private Sub picPlay_Paint(Index As Integer)
  Dim N As CardNode
 
  Set N = FindNode(m_Root, Index)
 
  If Not N Is Nothing Then N.Draw
End Sub

Private Sub picPlay_Click(Index As Integer)
  Dim N As CardNode
  Dim C As BravCard
  Dim iBorder As Integer
  Dim bCount As Byte
 
  Set N = FindNode(m_Root, Index)
  If Not N.IsEmpty Then Exit Sub
 
  If m_bLeft Then
    If m_iLeftIndex < 0 Then Exit Sub
   
    Set C = m_LeftHand(m_iLeftIndex)
    iBorder = m_iLeftBorder
    m_iLeftIndex = -1
  Else
    If m_iRightIndex < 0 Then Exit Sub
   
    Set C = m_RightHand(m_iRightIndex)
    iBorder = m_iRightBorder
    m_iRightIndex = -1
  End If
 
  With C
    .Picture.Left = iBorder
    Set N.Brav = .Brav
    Set .Brav = m_Deck.NextCard
  End With
 
  bCount = MatchCount(N)
 
  If m_bLeft Then
    lblLeft = Val(lblLeft) + bCount
  Else
    lblRight = Val(lblRight) + bCount
  End If
 
  SetNeighbours N
 
  lblNodeCount = 35 - m_Deck.Top
  m_bLeft = Not m_bLeft
End Sub

Private Function MatchCount(ByRef Node As CardNode) As Byte
  Dim I As Integer
  Dim N As CardNode
  Dim bCount As Byte
 
  bCount = 0
 
  For I = 0 To 3
    Set N = Node.Neighbour(I)
    If Not N Is Nothing Then bCount = bCount + Node.Card.MatchCount(N.Card, I)
  Next
 
  MatchCount = bCount
End Function

Private Function TryCount(ByRef Card As BravCard, _

  ByRef Node As CardNode) As Byte
  Dim I As Integer
  Dim N As CardNode
  Dim bCount As Byte
 
  bCount = 0
  For I = 0 To 3
    Set N = Node.Neighbour(I)
    If Not N Is Nothing Then bCount = bCount + Card.MatchCount(N.Card, I)
  Next
 
  TryCount = bCount
End Function

Private Function BestNode(ByRef Node As CardNode, _

  ByRef Card As BravCard, ByVal bRestart As Boolean) As CardNode
  Static bMaxCount As Byte
  Static MaxNode As CardNode
 
  Dim N As CardNode
  Dim I As Integer
  Dim C As Byte
 
  If bRestart Then
    bMaxCount = 0
    Set MaxNode = Node
  End If
 
  With Node
    .Checked = True
   
    If .IsEmpty Then
      C = TryCount(Card, Node)
     
      If C > bMaxCount Then
        bMaxCount = C
        Set MaxNode = Node
      End If
    End If
   
    For I = 0 To 3
      Set N = .Neighbour(I)
      If Not N Is Nothing Then If Not N.Checked Then _

        Set MaxNode = BestNode(N, Card, False)
    Next
  End With
 
  Set BestNode = MaxNode
End Function

' Just for debugging
Private Sub CheckAll(ByRef Node As CardNode)
  Dim N As CardNode
  Dim I As Integer
 
  With Node
    .Checked = True
    Debug.Print "Checking "; .X; ","; .Y
    For I = 0 To 3
      Set N = .Neighbour(I)
      If Not N Is Nothing Then If Not N.Checked Then CheckAll N
    Next
  End With
End Sub

Private Sub UncheckAll(ByRef Node As CardNode)
  Dim N As CardNode
  Dim I As Integer
 
  With Node
    .Checked = False
    Debug.Print "Unchecking "; .X; ","; .Y
    For I = 0 To 3
      Set N = .Neighbour(I)
      If Not N Is Nothing Then If N.Checked Then UncheckAll N
    Next
  End With
End Sub



módulo mdlBravDomino.bas


Attribute VB_Name = "mdlBravDomino"
Option Explicit

Public Enum enumSide
  eSideTop
  eSideRight
  eSideBottom
  eSideLeft
End Enum

Public Enum enumColor
  eColWhite
  eColRed
  eColGreen
  eColBlue
End Enum

Public Const c_TableWidth As Integer = 11
Public Const c_TableHeight As Integer = 7

Public Const c_MaxY As Integer = c_TableHeight \ 2
Public Const c_MaxX As Integer = c_TableWidth \ 2
Public Const c_MinY As Integer = -c_MaxY
Public Const c_MinX As Integer = -c_MaxX

Public Const c_Margin As Integer = 120
Public Const c_HalfMargin As Integer = c_Margin \ 2
Public Const c_DoubleMargin As Integer = c_Margin * 2

Public Const c_pxMargin As Integer = c_Margin \ 15
Public Const c_pxHalfMargin As Integer = c_pxMargin \ 2
Public Const c_pxDoubleMargin As Integer = c_pxMargin * 2

Public Const c_RotLeft As Byte = 1
Public Const c_RotRight As Byte = 3

Public Function RightSide(ByRef obj As Object) As Long
  With obj
    RightSide = .Left + .Width
  End With
End Function

Public Function BottomSide(ByRef obj As Object) As Long
  With obj
    BottomSide = .Top + .Height
  End With
End Function

Public Function ColorArray(ByVal eColor As enumColor) As Long
  Select Case eColor
    Case eColWhite
      ColorArray = vbWhite
    Case eColRed
      ColorArray = vbRed
    Case eColGreen
      ColorArray = vbGreen
    Case eColBlue
      ColorArray = vbBlue
  End Select
End Function
Módulo de clase Brav.cls

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "Brav"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Private m_bRotation As Byte       ' 0..3
Private m_Sector(0 To 3) As Byte  ' 0=White, 1=Red, 2=Green, 3=Blue
Private m_Id As Byte

Public Property Let Rotation(ByVal bRotation As Byte)
  m_bRotation = bRotation Mod 4
End Property

Public Property Get Rotation() As Byte
  Rotation = m_bRotation
End Property

Public Sub Rotate(ByVal bRotation As Byte)
  m_bRotation = (m_bRotation + bRotation) Mod 4
End Sub

Public Property Let Sector(ByVal iSector As Byte, _

  ByVal bColor As Byte)
  Dim bOffset As Byte
 
  iSector = iSector Mod 4
  bColor = bColor Mod 4
 
  m_Sector(iSector) = bColor
 
  bOffset = 4 ^ iSector
  m_Id = m_Id And Not (3 * bOffset)   'Clean 2 bits
  m_Id = m_Id Or (bColor * bOffset)   'Set 2 bits
End Property

Public Property Get Id() As Byte
  Id = m_Id
End Property

Public Property Get Sector(ByVal iSector As Byte) As Byte
  Sector = m_Sector(iSector Mod 4)
End Property

Public Function Side(ByVal eSide As enumSide) As Byte
  Dim bStart As Byte
 
  bStart = m_bRotation + eSide
 
  Side = m_Sector(bStart Mod 4) * 10 + m_Sector((bStart + 1) Mod 4)
End Function

Public Function MatchCount(ByRef Neighbour As Brav, _

  ByVal eSide As enumSide) As Byte
  Dim bMySide As Byte
  Dim bNeighbourSide As Byte
  Dim bCount As Byte
 
  bMySide = Side(eSide)
  bNeighbourSide = Neighbour.Side((eSide + 2) Mod 4)
  bCount = 0
 
  If bMySide \ 10 = bNeighbourSide Mod 10 Then bCount = bCount + 1
  If bMySide Mod 10 = bNeighbourSide \ 10 Then bCount = bCount + 1
 
  MatchCount = bCount
End Function


Módulo de clase BravCard.cls

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "BravCard"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Public Event Activate()

Private m_Brav As Brav
Private m_Picture As PictureBox
Private m_iIndex As Integer

Private m_iBorder As Integer

Private Sub Class_Initialize()
  Dispose
  m_iIndex = -1
  m_iBorder = 15
End Sub

Public Sub Dispose()
  Set m_Brav = Nothing
  Set m_Picture = Nothing
End Sub

Public Property Get Brav() As Brav
  Set Brav = m_Brav
End Property

Public Property Set Brav(ByRef B As Brav)
  Set m_Brav = B
 
  If m_Brav Is Nothing Then
    m_Picture.Cls
  Else
    Draw
    RaiseEvent Activate
  End If
 
End Property

Public Property Get Picture() As PictureBox
  Set Picture = m_Picture
End Property

Public Property Set Picture(ByRef P As PictureBox)
  Set m_Picture = P
 
  m_Picture.Visible = True
End Property

Public Property Get Index() As Integer
  Index = m_iIndex
End Property

Public Property Let Index(ByVal iIndex As Integer)
  m_iIndex = iIndex
End Property

Public Property Get Border() As Integer
  Border = m_iBorder
End Property

Public Property Let Border(ByVal iBorder As Integer)
  m_iBorder = iBorder
End Property

Public Sub Draw()
  Dim iWidth As Integer
  Dim iHeight As Integer
  Dim X As Integer
  Dim Y As Integer
  Dim W As Integer
  Dim H As Integer
  Dim R As Byte
 
  If m_Picture Is Nothing Then Exit Sub
 
  With m_Picture
    iWidth = .ScaleWidth \ 2 - (m_iBorder + 10)
    iHeight = .ScaleHeight \ 2 - (m_iBorder + 10)
   
    .Cls
  End With
 
  If m_Brav Is Nothing Then
    With m_Picture
      .DrawStyle = 2
      m_Picture.Line _

        (0, 0)-Step(.ScaleWidth - 10, .ScaleHeight - 10), , B
    End With
  Else
    m_Picture.DrawStyle = 0
   
    With m_Brav
      R = .Rotation
     
      X = m_iBorder
      Y = m_iBorder
      m_Picture.Line _

        (X, Y)-Step(iWidth, iHeight), ColorArray(.Sector(R)), BF
      m_Picture.Line _

        (X, Y)-Step(iWidth, iHeight), , B
     
      X = m_iBorder + iWidth
      Y = m_iBorder
      m_Picture.Line _

        (X, Y)-Step(iWidth, iHeight), _

          ColorArray(.Sector((R + 1) Mod 4)), BF
      m_Picture.Line _

        (X, Y)-Step(iWidth, iHeight), , B
     
      X = m_iBorder + iWidth
      Y = m_iBorder + iHeight
      m_Picture.Line _

        (X, Y)-Step(iWidth, iHeight), _

          ColorArray(.Sector((R + 2) Mod 4)), BF
      m_Picture.Line _

        (X, Y)-Step(iWidth, iHeight), , B
     
      X = m_iBorder
      Y = m_iBorder + iHeight
      m_Picture.Line _

        (X, Y)-Step(iWidth, iHeight), _
          ColorArray(.Sector((R + 3) Mod 4)), BF
      m_Picture.Line (X, Y)-Step(iWidth, iHeight), , B
    End With
  End If
End Sub

Public Property Get IsEmpty() As Boolean
  IsEmpty = m_Brav Is Nothing
End Property

Public Function MatchCount(ByRef Neighbour As BravCard, _

  ByVal eSide As enumSide) As Byte
  With Neighbour
    If .IsEmpty Then
      MatchCount = 0
    Else
      MatchCount = m_Brav.MatchCount(.Brav, eSide)
    End If
  End With
End Function

Public Sub RotateRight()
  m_Brav.Rotate c_RotRight
  Draw
End Sub

Public Sub RotateLeft()
  m_Brav.Rotate c_RotLeft
  Draw
End Sub

Módulo de clase BravDeck.cls


VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "BravDeck"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Private Const c_LastCard As Integer = 34

Private m_Brav(0 To c_LastCard) As Brav
Private m_bUseFirst As Boolean
Private m_iTopCard As Integer

Private Sub Class_Initialize()
  SetDeck
 
  m_bUseFirst = True
  m_iTopCard = 0
End Sub

Private Sub Class_Terminate()
  Dispose
End Sub

Public Sub Dispose()
  Dim I As Integer

  For I = 0 To c_LastCard
    Set m_Brav(I) = Nothing
  Next
End Sub

Private Sub SetDeck()
  Dim B As Brav
  Dim iBrav As Integer
 
  Dim I As Byte
  Dim S As Byte
  Dim C As Byte
 
  ' 1+1+1+1
  Set B = New Brav
  For S = 0 To 3
    B.Sector(S) = S
  Next
 
  iBrav = 0
  Set m_Brav(iBrav) = B
 
  ' 1+1+2
  For S = 0 To 3
    For C = 0 To 3
      If C <> S Then
        Set B = New Brav
        For I = 0 To 3
          If I = S Then
            B.Sector(I) = C
          Else
            B.Sector(I) = I
          End If
        Next
       
        iBrav = iBrav + 1
        Set m_Brav(iBrav) = B
      End If
    Next
  Next

  ' 2+2
  For S = 0 To 2
    For C = S + 1 To 3
      Set B = New Brav
      For I = 0 To 3
        If I = S Then
          B.Sector(I) = S
        ElseIf I = C Then
          B.Sector(I) = C
        ElseIf (I + 1) Mod 4 = S Then
          B.Sector(I) = S
        ElseIf (I + 1) Mod 4 = C Then
          B.Sector(I) = C
        ElseIf C - S = 1 Then
          B.Sector(I) = C
        Else
          B.Sector(I) = S
        End If
      Next
     
      iBrav = iBrav + 1
      Set m_Brav(iBrav) = B
    Next
  Next

  ' 1+3
  For S = 0 To 3
    For C = 0 To 3
      If C <> S Then
        Set B = New Brav
        For I = 0 To 3
          If I = S Then
            B.Sector(I) = I
          Else
            B.Sector(I) = C
          End If
        Next
       
        iBrav = iBrav + 1
        Set m_Brav(iBrav) = B
      End If
    Next
  Next

  ' 4
  For S = 0 To 3
    Set B = New Brav
    For I = 0 To 3
      B.Sector(I) = S
    Next
   
    iBrav = iBrav + 1
    Set m_Brav(iBrav) = B
  Next
End Sub

Public Property Get UseFirst() As Boolean
  UseFirst = m_bUseFirst
End Property

Public Property Let UseFirst(ByVal bUse As Boolean)
  m_bUseFirst = bUse
End Property

Public Property Get DeckEnd() As Boolean
  DeckEnd = m_iTopCard > c_LastCard
End Property

Public Property Get NextCard() As Brav
  If m_iTopCard > c_LastCard Then
    Set NextCard = Nothing
  Else
    Set NextCard = m_Brav(m_iTopCard)
    m_iTopCard = m_iTopCard + 1
  End If
End Property

Public Property Get TopCard() As Brav
  If m_iTopCard > c_LastCard Then
    Set TopCard = Nothing
  Else
    Set TopCard = m_Brav(m_iTopCard)
  End If
End Property

Public Property Get Card(ByVal iIndex As Integer) As Brav
  If iIndex < 0 Or iIndex > c_LastCard Then
    Set Card = Nothing
  Else
    Set Card = m_Brav(iIndex)
  End If
End Property

Public Property Get Top() As Integer
  Top = m_iTopCard
End Property

Public Sub Reset()
  m_iTopCard = IIf(m_bUseFirst, 0, 1)
End Sub

Public Sub Mix()
  Dim I As Integer
  Dim N As Integer
 
  Reset
 
  N = c_LastCard - m_iTopCard + 1
  For I = m_iTopCard To c_LastCard
    Swap I, Int(Rnd * N) + m_iTopCard
  Next
End Sub

Private Sub Swap(ByVal I As Integer, ByVal J As Integer)
  Dim Card As Brav
 
  Set Card = m_Brav(I)
  Set m_Brav(I) = m_Brav(J)
  Set m_Brav(J) = Card
End Sub

Módulo de clase CardNode.cls


VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "CardNode"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Private WithEvents m_Card As BravCard
Attribute m_Card.VB_VarHelpID = -1

Private m_X As Integer
Private m_Y As Integer

Private m_Neighbour(0 To 3) As CardNode
Private m_bChecked As Boolean

Private Sub Class_Initialize()
  Dim I As Integer
 
  Set m_Card = New BravCard
 
  For I = 0 To 3
    Set m_Neighbour(I) = Nothing
  Next
End Sub

Public Sub Dispose()
  Dim I As Integer
 
  For I = 0 To 3
    If Not m_Neighbour(I) Is Nothing Then
      With m_Neighbour(I)
        Set .Neighbour((I + 2) Mod 4) = Nothing

                                            '
Don't come back to Me!
        .Dispose
      End With
      Set m_Neighbour(I) = Nothing
    End If
  Next
 
  If Not m_Card Is Nothing Then
    m_Card.Dispose
    Set m_Card = Nothing
  End If
End Sub

Public Property Set Brav(ByRef B As Brav)
  Set m_Card.Brav = B
End Property

Public Property Get Card() As BravCard
  Set Card = m_Card
End Property

Public Property Set Card(ByRef C As BravCard)
  Set m_Card = C
End Property

Public Property Get Picture() As PictureBox
  Set Picture = m_Card.Picture
End Property

Public Property Set Picture(ByRef pic As PictureBox)
  Set m_Card.Picture = pic
End Property

Public Property Get Index() As Integer
  Index = m_Card.Index
End Property

Public Property Let Index(ByVal iIndex As Integer)
  m_Card.Index = iIndex
End Property

Public Property Get Checked() As Boolean
  Checked = m_bChecked
End Property

Public Property Let Checked(ByVal bChecked As Boolean)
  m_bChecked = bChecked
End Property

Private Sub CreateNeighbours()
  Dim I As Integer
  Dim bIsInside As Boolean
  Dim N As CardNode
 
  For I = 0 To 3              ' Look at 4 sides
    If m_Neighbour(I) Is Nothing Then  

                              ' If no neighbour yet on this side
      Select Case I           ' Check bounds
        Case eSideTop
          bIsInside = (m_Y > c_MinY)
        Case eSideRight
          bIsInside = (m_X < c_MaxX)
        Case eSideBottom
          bIsInside = (m_Y < c_MaxY)
        Case eSideLeft
          bIsInside = (m_X > c_MinX)
      End Select
     
      If bIsInside Then          ' If bounds are right
        Set N = FindNeighbour(I) ' Is there a neighbour's neighbour?
        If N Is Nothing Then     ' If not, create a new one
          Set N = New CardNode
          With N          ' Set the coords for the new node
            Select Case I ' depending on its relative position to Me
              Case eSideTop
                .X = m_X
                .Y = m_Y - 1
              Case eSideRight
                .X = m_X + 1
                .Y = m_Y
              Case eSideBottom
                .X = m_X
                .Y = m_Y + 1
              Case eSideLeft
                .X = m_X - 1
                .Y = m_Y
            End Select
          End With
        End If
       

        ' Link neighbour node to Me
        Set N.Neighbour((I + 2) Mod 4) = Me

        ' Link Me to the neighbour node

        Set m_Neighbour(I) = N      End If
    End If
  Next
End Sub

Public Property Get Neighbour(ByVal eSide As enumSide) As CardNode
  Set Neighbour = m_Neighbour(eSide)
End Property

Public Property Set Neighbour(ByVal eSide As enumSide, _

  ByRef N As CardNode)
  Set m_Neighbour(eSide) = N
End Property

Public Property Get IsEmpty() As Boolean
  IsEmpty = m_Card.IsEmpty
End Property

Public Function MatchCount(ByVal N As CardNode, _

  ByVal eSide As enumSide) As Byte
  MatchCount = m_Card.MatchCount(N.Card, eSide)
End Function

Public Sub Draw()
  m_Card.Draw
End Sub

Private Sub m_Card_Activate()
  CreateNeighbours
End Sub

Public Sub RotateRight()
  m_Card.RotateRight
End Sub

Public Sub RotateLeft()
  m_Card.RotateLeft
End Sub

Public Function FindNeighbour(ByVal eSide As enumSide) As CardNode
  Dim N As CardNode
 
  ' Try on left side
  Set N = m_Neighbour((eSide + c_RotLeft) Mod 4)
  If Not N Is Nothing Then Set N = _

    N.Neighbour(eSide)
  If Not N Is Nothing Then Set N = _

    N.Neighbour((eSide + c_RotRight) Mod 4)
 
  If N Is Nothing Then
  ' No neighbour found, so try on right side
    Set N = m_Neighbour((eSide + c_RotRight) Mod 4)
    If Not N Is Nothing Then Set N = _

      N.Neighbour(eSide)
    If Not N Is Nothing Then Set N = _

      N.Neighbour((eSide + c_RotLeft) Mod 4)
  End If
 
  Set FindNeighbour = N
End Function

Public Property Get X() As Integer
  X = m_X
End Property

Public Property Let X(ByVal iX As Integer)
  m_X = iX
End Property

Public Property Get Y() As Integer
  Y = m_Y
End Property

Public Property Let Y(ByVal iY As Integer)
  m_Y = iY
End Property


Comentarios

Entradas populares de este blog

Fractales

Vida

Permutaciones, combinaciones, variaciones y particiones