RetroCoders Community

FreeBasic Programming => FreeBasic Game Dev => Topic started by: mysoft on Jun 16, 2023, 04:03 PM

Title: gem matching game
Post by: mysoft on Jun 16, 2023, 04:03 PM
so another simple game made for lessons...

mouse: click & drag to form triples
keyboard: arrows to move enter to select (after select arrow will drag to that direction)
space: (cheat! show avaliable moves :P)

#include "fbgfx.bi"

dim shared as integer matriz( -2 to 8+3 , -2 to 8+3 )
dim shared as integer MostraPossibilidade=0
dim as integer lin,Col,N,I

locate ,,0 'hide cursor
width 10*3-2,10*2-2

'write a single block
sub DesenhaBloco( Lin as integer , Col as integer , Num as integer , Sel as integer )
 
  if Num = 0 then 'break dimension effect
    color 13, 0
    locate lin*2+0 , col*3 : print chr(32+rnd*95,32+rnd*95,32+rnd*95);   
    locate lin*2+1 , col*3 : print chr(32+rnd*95,32+rnd*95,32+rnd*95); 
    sleep Sel,1   
    exit sub
  end if
   
 
  if Num < 0 then 'black if hidden
    color 0,0
  else
    if sel<>0 then color Num+8,Num else color Num,Num+8
  end if
 
  locate lin*2+0 , col*3 : print chr(&hC9,&hCD,&hBB);   
  locate lin*2+1 , col*3 : print chr(&hC8,&hCD,&hBC); 
 
end sub

'draws whole map (matrix)
sub DesenhaMatriz()
  dim as integer lin,Col,N 
  for lin=1 to 8
    for Col=1 to 8
      DesenhaBloco( lin,Col , matriz(lin,col) , 0 )
    next col
  next lin
end sub

'check matrix for triplets to drop
function VerificaMatriz() as integer
  dim as integer Lin,Col , N
  dim as integer Cor=0,Qtd=0
  dim as integer Resultado=0
 
  'check for 3+ consecutives same color blocks in a column
  For Col=1 to 8
    For Lin=1 to 9
      if Cor=abs(matriz(Lin,Col)) then 'if color matches then increment count
        Qtd = Qtd + 1
      else 'if does not match, but there was 3+ matches then drop it and in both cases restart counter
        if Qtd >= 3 then 'if 3+ matches negative them so they fall         
          for N = 1 to Qtd
            if matriz(Lin-N,Col)>0 then DesenhaBloco( Lin-N , Col , 0 , 150 )
            matriz(Lin-N,Col) = -Cor
          next N
          Resultado = Resultado+1
        end if
        Cor=abs(matriz(Lin,Col)) : Qtd=1
      end if
    next
  next
 
  'check for 3+ consecutive same color blocks in a row
  For Lin=1 to 8
    For Col=1 to 9
      if Cor=abs(matriz(Lin,Col)) then 'if color matches then increment count
        Qtd = Qtd + 1
      else 'if does not match, but there was 3+ matches then drop it and in both cases restart counter
        if Qtd >= 3 then 'if 3+ matches negative them so they fall
          for N = 1 to Qtd
            if matriz(Lin,Col-N)>0 then DesenhaBloco( Lin , Col-N , 0 , 150 )
            matriz(Lin,Col-N) = -Cor
          next N
          Resultado = Resultado+1
        end if
        Cor=abs(matriz(Lin,Col)) : Qtd=1
      end if
    next
  next
 
  return Resultado
 
end function

'drop negatived elements
sub DesabaMatriz()
  dim as integer lin,col,N,desabou
 
  for lin=8 to 1 step -1 'for each line starting from bottom
   
    desabou=0
    for col=1 to 8 'if negative(removed)
      if matriz(lin,col)<0 then 'drop this column
        for N = lin to 2 step -1
          matriz(N,col) = matriz(N-1,col)
        next N
        matriz(1,col) = int(rnd*7)+1
        desabou = 1
      end if
    next col
    if desabou<>0 then
      DesenhaMatriz() : sleep 100,1
      lin = lin+1 'if dropped then verify same line again
    end if
   
  next lin
   
  DesenhaMatriz()
   
end sub

'show possible moves (cheat, but should be limited attempts :P)
sub Mostra(Lin as integer ,Col as integer,OLin as integer,OCol as integer, Sel as integer)
  if MostraPossibilidade=0 then exit sub
  dim as integer L,C 
  for L=Lin to Lin+OLin
    for C=Col to Col+OCol
      DesenhaBloco( L,C , Matriz(L,C) , Sel )
    next C
  next L
end sub

'there are movements possible?
function ExisteMovimentos() as integer
  '  3  2 ?4  1  3  5
  '                   
  '  1  3? 5 ?2  1  3
  '                   
  '  2  4 [3] 1  2  4
  '                   
  '  1 *2 [3] 5 *1  2
  '                   
  ' *2 ?5 <4>?4> 3 *1
  '                   
  '  1 *4 ?2  1 *5  4
  '                   
 
  'if there's 2 consecutives blocks on a row or column
  'check surrounding blocks to see if same block
  dim as integer I,N,Num,Sel
  dim as integer Resultado = 0
  for Sel = 1 to 4
    For I=1 to 7
      For N=1 to 8
       
        Num = matriz(I,N) 'check column <> *
        if Num = matriz(I,N+1) then
          rem check surroundings
          if matriz(I  ,N-2)=Num then Mostra(I,N,0,1,Sel mod 2) : Resultado =  1
          if matriz(I-1,N-1)=Num then Mostra(I,N,0,1,Sel mod 2) : Resultado =  1
          if matriz(I+1,N-1)=Num then Mostra(I,N,0,1,Sel mod 2) : Resultado =  1
          if matriz(I-1,N+2)=Num then Mostra(I,N,0,1,Sel mod 2) : Resultado =  1
          if matriz(I+1,N+2)=Num then Mostra(I,N,0,1,Sel mod 2) : Resultado =  1
          if matriz(I  ,N+3)=Num then Mostra(I,N,0,1,Sel mod 2) : Resultado =  1
        end if
       
        Num = matriz(N,I) 'check rows [] ?
        if Num=matriz(N+1,I) then
          rem check surroundings
          if matriz(N-2,I  )=Num then Mostra(N,I,1,0,Sel mod 2) : Resultado =  1
          if matriz(N-1,I-1)=Num then Mostra(N,I,1,0,Sel mod 2) : Resultado =  1
          if matriz(N-1,I+1)=Num then Mostra(N,I,1,0,Sel mod 2) : Resultado =  1
          if matriz(N+2,I-1)=Num then Mostra(N,I,1,0,Sel mod 2) : Resultado =  1
          if matriz(N+2,I+1)=Num then Mostra(N,I,1,0,Sel mod 2) : Resultado =  1
          if matriz(N+3,I  )=Num then Mostra(N,I,1,0,Sel mod 2) : Resultado =  1
        end if
       
      next
    next
    if Resultado=0 or MostraPossibilidade=0 then exit for
    sleep 250,1
  next Sel
  return Resultado
 
end function

'init the random number generator
randomize()

do 'create random map
 
  For lin=1 to 8
    For col=1 to 8
      matriz(lin,col)=int(rnd*7)+1
    next col
  next lin
   
  'if triples are found restart... (cheap trick, but easy)
  For I=1 to 6
    For N=1 to 8
      if matriz(I,N)=matriz(I+1,N) and matriz(I,N)=matriz(I+2,N) then continue do
      if matriz(N,I)=matriz(N,I+1) and matriz(N,I)=matriz(N,I+2) then continue do     
    next
  next 
 
  exit do
loop

DesenhaMatriz()

dim as integer cursor,alternacursor
dim as integer cursorlin=4,cursorcol=4
dim as integer antigalin,antigacol
dim as integer sellin,selcol
dim as integer MLin,MCol,MBut,MEsquerdo
dim as string tecla

do
  if antigalin<>cursorlin or antigacol<>cursorcol then
    if cursor<>0 then DesenhaBloco( antigalin,antigacol , matriz(antigalin,antigacol) , 0 )
    antigalin=cursorlin : antigacol=cursorcol
  endif
 
  alternacursor=alternacursor+1
  if alternacursor>=5 then
    alternacursor=0
    if cursor=1 then cursor=0 else cursor=1
  end if
  if sellin<>0 then cursor=1
  DesenhaBloco( cursorlin,cursorcol , matriz(cursorlin,cursorcol) , cursor )

  tecla=inkey
  if tecla="" then sleep 50
  if tecla=chr(255,fb.sc_up)    and cursorlin>1 then
    cursorlin=cursorlin-1 : if sellin<>0 then tecla=chr(13)
  end if
  if tecla=chr(255,fb.sc_down)  and cursorlin<8 then
    cursorlin=cursorlin+1 : if sellin<>0 then tecla=chr(13)
  end if
  if tecla=chr(255,fb.sc_left)  and cursorcol>1 then
    cursorcol=cursorcol-1 : if sellin<>0 then tecla=chr(13) 
  end if
  if tecla=chr(255,fb.sc_right) and cursorcol<8 then
    cursorcol=cursorcol+1 : if sellin<>0 then tecla=chr(13)
  end if
  if tecla=" " then
    MostraPossibilidade = 1
    ExisteMovimentos()
    MostraPossibilidade = 0
  end if
 
  '----- mouse -----
  'MLin,MCol,MBut,MButAntigo
  getmouse MCol,MLin,,MBut
  color 7,0 : locate 1,1
  Lin = (MLin-1+2)\2 : Col = (MCol-2+3)\3
  if MBut=1 and MEsquerdo=0 then 'left button pressed
    if Lin >= 1 and Col >= 1 and Lin <= 8 and Col <= 8 then
      MEsquerdo = 1
      sellin = Lin : selcol = Col
      cursorlin = Lin : cursorcol = Col
    end if
  end if
  if MBut=1 and MEsquerdo=1 and SelLin<>0 then 'was pressed, verify movement
    if Lin >= 1 and Col >= 1 and Lin <= 8 and Col <= 8 then     
      if (abs(Lin-SelLin)+abs(Col-SelCol))=1 then
        cursorlin = Lin : cursorcol = Col
        tecla=chr(13) 'make it as if ENTER was pressed
      end if
    end if
  end if
  if MBut=0 and MEsquerdo=1 then 'released left button
    MEsquerdo = 0
    sellin = 0 : selcol = 0
    #if 0
  if Lin >= 1 and Col >= 1 and Lin <= 8 and Col <= 8 then
    MEsquerdo = 0
    if (abs(Lin-SelLin)+abs(Col-SelCol))=1 then
      cursorlin = Lin : cursorcol = Col
      tecla=chr(13) 'make it as if ENTER was pressed
    else
      sellin = 0 : selcol = 0 'clear selection if invalid click
    end if
  end if
    #endif
  end if
 
  '-----------------
 
  if tecla=chr(26) and sellin=0 then 'ctrl+z
    for lin=8 to 1 step -1
      for col=1 to 8
        matriz(lin,col) = -1
        DesenhaBloco( lin , col , 0 , 30 )
      next col
    next lin
   
    sellin=cursorlin : selcol=cursorcol : tecla=chr(13)
   
  end if
   
   
  if tecla=chr(13) then 'enter
    if sellin=0 then
      sellin=cursorlin
      selcol=cursorcol
    else
      dim as integer desabou = 0
      swap matriz(sellin,selcol),matriz(cursorlin,cursorcol)     
      do
        if VerificaMatriz()<>0 then 'if triples found then drop them
          DesabaMatriz() : desabou=1
        else 'if not then it was a bad movement
          if desabou<>0 then
            if ExisteMovimentos()=0 then
              'if no movements are possible clear the map and restart
              '(this time no triples prevention checks are needed)
              for lin=8 to 1 step -1
                for col=1 to 8
                  matriz(lin,col) = -1
                  DesenhaBloco( lin , col , 0 , 30 )
                next col
              next lin
              continue do 'and make it verify matrix for triples again
            end if
            exit do 'if it dropped at least once then we're done
          end if
          'didnt dropped anything so undo movement (invalid)
          DesenhaMatriz() : sleep 250
          swap matriz(sellin,selcol),matriz(cursorlin,cursorcol)         
          exit do
        end if
      loop
     
      DesenhaMatriz()
      sellin=0  : selcol=0
    endif
  endif
 
loop


sleep