Tetris
Create a playable Tetris game.
The visible game matrix should be 10*20.
It must have:
- left/right key;
- a hard drop key (the current piece will be dropped and locked at once);
- (better with another soft drop key);
- at least one rotation key;
- (better with two, for both clockwise and counter-clockwise 90° rotation);
- full set of 7 kinds of shapes (ITOSZJL).
The piece should be rotatable at its initial position (unlike sega arcade tetris), and automatically falling at reasonable speed.
At least 1 preview piece should be shown.
No further requirement about randomizer / rotation system / DAS / colors / difficulty levels / score / hold, but you may do it if you wish.
BASH
<lang BASH>#!/bin/bash
- Tetris Game
- 10.21.2003 xhchen
- http://read.pudn.com/downloads99/sourcecode/game/404711/tetris.sh__.htm
- Copyright (C) xhchen
- color definition
cRed=1 cGreen=2 cYellow=3 cBlue=4 cFuchsia=5 cCyan=6 cWhite=7 colorTable=($cRed $cGreen $cYellow $cBlue $cFuchsia $cCyan $cWhite)
- size & position
iLeft=3 iTop=2 ((iTrayLeft = iLeft + 2)) ((iTrayTop = iTop + 1)) ((iTrayWidth = 10)) ((iTrayHeight = 15))
- style definition
cBorder=$cGreen cScore=$cFuchsia cScoreValue=$cCyan
- control signal
sigRotate=25 sigLeft=26 sigRight=27 sigDown=28 sigAllDown=29 sigExit=30
- boxes
box0=(0 0 0 1 1 0 1 1) box1=(0 2 1 2 2 2 3 2 1 0 1 1 1 2 1 3) box2=(0 0 0 1 1 1 1 2 0 1 1 0 1 1 2 0) box3=(0 1 0 2 1 0 1 1 0 0 1 0 1 1 2 1) box4=(0 1 0 2 1 1 2 1 1 0 1 1 1 2 2 2 0 1 1 1 2 0 2 1 0 0 1 0 1 1 1 2) box5=(0 1 1 1 2 1 2 2 1 0 1 1 1 2 2 0 0 0 0 1 1 1 2 1 0 2 1 0 1 1 1 2) box6=(0 1 1 1 1 2 2 1 1 0 1 1 1 2 2 1 0 1 1 0 1 1 2 1 0 1 1 0 1 1 1 2) box=(${box0[@]} ${box1[@]} ${box2[@]} ${box3[@]} ${box4[@]} ${box5[@]} ${box6[@]}) countBox=(1 2 2 2 4 4 4 ) offsetBox=(0 1 3 5 7 11 15)
- score
iScoreEachLevel=50 #be greater than 7
- Runtime data
sig=0 iScore=0 iLevel=0 boxNew=() #new box cBoxNew=0 #new box color iBoxNewType=0 #new box type iBoxNewRotate=0 #new box rotate degree boxCur=() #current box cBoxCur=0 #current box color iBoxCurType=0 #current box type iBoxCurRotate=0 #current box rotate degree boxCurX=-1 #current X position boxCurY=-1 #current Y position iMap=() for ((i = 0; i < iTrayHeight * iTrayWidth; i++)); do iMap[$i]=-1; done RunAsKeyReceiver() {
local pidDisplayer key aKey sig cESC sTTY pidDisplayer=$1 aKey=(0 0 0) cESC=`echo -ne "\033"` cSpace=`echo -ne "\040"` sTTY=`stty -g` trap "MyExit;" INT TERM trap "MyExitNoSub;" $sigExit echo -ne "\033[?25l" while : do read -s -n 1 key aKey[0]=${aKey[1]} aKey[1]=${aKey[2]} aKey[2]=$key sig=0 if [[ $key == $cESC && ${aKey[1]} == $cESC ]] then MyExit elif [[ ${aKey[0]} == $cESC && ${aKey[1]} == "[" ]] then if $key == "A" ; then sig=$sigRotate elif $key == "B" ; then sig=$sigDown elif $key == "D" ; then sig=$sigLeft elif $key == "C" ; then sig=$sigRight fi elif | $key == "w" ; then sig=$sigRotate elif | $key == "s" ; then sig=$sigDown elif | $key == "a" ; then sig=$sigLeft elif | $key == "d" ; then sig=$sigRight elif [[ "[$key]" == "[]" ]]; then sig=$sigAllDown elif | $key == "q" then MyExit fi if $sig != 0 then kill -$sig $pidDisplayer fi done
} MyExitNoSub(){
local y stty $sTTY ((y = iTop + iTrayHeight + 4)) echo -e "\033[?25h\033[${y};0H" exit
} MyExit(){
kill -$sigExit $pidDisplayer MyExitNoSub
} RunAsDisplayer(){
local sigThis InitDraw trap "sig=$sigRotate;" $sigRotate trap "sig=$sigLeft;" $sigLeft trap "sig=$sigRight;" $sigRight trap "sig=$sigDown;" $sigDown trap "sig=$sigAllDown;" $sigAllDown trap "ShowExit;" $sigExit while : do for ((i = 0; i < 21 - iLevel; i++)) do usleep 20000 sigThis=$sig sig=0 if ((sigThis == sigRotate)); then BoxRotate; elif ((sigThis == sigLeft)); then BoxLeft; elif ((sigThis == sigRight)); then BoxRight; elif ((sigThis == sigDown)); then BoxDown; elif ((sigThis == sigAllDown)); then BoxAllDown; fi done #kill -$sigDown $$ BoxDown done
} BoxMove(){
local j i x y xTest yTest yTest=$1 xTest=$2 for ((j = 0; j < 8; j += 2)) do ((i = j + 1)) ((y = ${boxCur[$j]} + yTest)) ((x = ${boxCur[$i]} + xTest)) if (( y < 0 || y >= iTrayHeight || x < 0 || x >= iTrayWidth)) then return 1 fi if ((${iMap[y * iTrayWidth + x]} != -1 )) then return 1 fi done return 0;
} Box2Map(){
local j i x y xp yp line for ((j = 0; j < 8; j += 2)) do ((i = j + 1)) ((y = ${boxCur[$j]} + boxCurY)) ((x = ${boxCur[$i]} + boxCurX)) ((i = y * iTrayWidth + x)) iMap[$i]=$cBoxCur done line=0 for ((j = 0; j < iTrayWidth * iTrayHeight; j += iTrayWidth)) do for ((i = j + iTrayWidth - 1; i >= j; i--)) do if ((${iMap[$i]} == -1)); then break; fi done if ((i >= j)); then continue; fi ((line++)) for ((i = j - 1; i >= 0; i--)) do ((x = i + iTrayWidth)) iMap[$x]=${iMap[$i]} done for ((i = 0; i < iTrayWidth; i++)) do iMap[$i]=-1 done done if ((line == 0)); then return; fi ((x = iLeft + iTrayWidth * 2 + 7)) ((y = iTop + 11)) ((iScore += line * 2 - 1)) echo -ne "\033[1m\033[3${cScoreValue}m\033[${y};${x}H${iScore} " if ((iScore % iScoreEachLevel < line * 2 - 1)) then if ((iLevel < 20)) then ((iLevel++)) ((y = iTop + 14)) echo -ne "\033[3${cScoreValue}m\033[${y};${x}H${iLevel} " fi fi echo -ne "\033[0m" for ((y = 0; y < iTrayHeight; y++)) do ((yp = y + iTrayTop + 1)) ((xp = iTrayLeft + 1)) ((i = y * iTrayWidth)) echo -ne "\033[${yp};${xp}H" for ((x = 0; x < iTrayWidth; x++)) do ((j = i + x)) if ((${iMap[$j]} == -1)) then echo -ne " " else echo -ne "\033[1m\033[7m\033[3${iMap[$j]}m\033[4${iMap[$j]}m\040\040\033[0m" fi done done
} BoxDown(){
local y s ((y = boxCurY + 1)) if BoxMove $y $boxCurX then s="`DrawCurBox 0`" ((boxCurY = y)) s="$s`DrawCurBox 1`" echo -ne $s else Box2Map RandomBox fi
} BoxLeft(){
local x s ((x = boxCurX - 1)) if BoxMove $boxCurY $x then s=`DrawCurBox 0` ((boxCurX = x)) s=$s`DrawCurBox 1` echo -ne $s fi
} BoxRight(){
local x s ((x = boxCurX + 1)) if BoxMove $boxCurY $x then s=`DrawCurBox 0` ((boxCurX = x)) s=$s`DrawCurBox 1` echo -ne $s fi
} BoxAllDown(){
local k j i x y iDown s iDown=$iTrayHeight for ((j = 0; j < 8; j += 2)) do ((i = j + 1)) ((y = ${boxCur[$j]} + boxCurY)) ((x = ${boxCur[$i]} + boxCurX)) for ((k = y + 1; k < iTrayHeight; k++)) do ((i = k * iTrayWidth + x)) if (( ${iMap[$i]} != -1)); then break; fi done ((k -= y + 1)) if (( $iDown > $k )); then iDown=$k; fi done s=`DrawCurBox 0` ((boxCurY += iDown)) s=$s`DrawCurBox 1` echo -ne $s Box2Map RandomBox
} BoxRotate(){
local iCount iTestRotate boxTest j i s iCount=${countBox[$iBoxCurType]} ((iTestRotate = iBoxCurRotate + 1)) if ((iTestRotate >= iCount)) then ((iTestRotate = 0)) fi for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++)) do boxTest[$j]=${boxCur[$j]} boxCur[$j]=${box[$i]} done if BoxMove $boxCurY $boxCurX then for ((j = 0; j < 8; j++)) do boxCur[$j]=${boxTest[$j]} done s=`DrawCurBox 0` for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++)) do boxCur[$j]=${box[$i]} done s=$s`DrawCurBox 1` echo -ne $s iBoxCurRotate=$iTestRotate else for ((j = 0; j < 8; j++)) do boxCur[$j]=${boxTest[$j]} done fi
} DrawCurBox(){
local i j t bDraw sBox s bDraw=$1 s="" if (( bDraw == 0 )) then sBox="\040\040" else sBox="\040\040" s=$s"\033[1m\033[7m\033[3${cBoxCur}m\033[4${cBoxCur}m" fi for ((j = 0; j < 8; j += 2)) do ((i = iTrayTop + 1 + ${boxCur[$j]} + boxCurY)) ((t = iTrayLeft + 1 + 2 * (boxCurX + ${boxCur[$j + 1]}))) s=$s"\033[${i};${t}H${sBox}" done s=$s"\033[0m" echo -n $s
} RandomBox(){
local i j t #change current box iBoxCurType=${iBoxNewType} iBoxCurRotate=${iBoxNewRotate} cBoxCur=${cBoxNew} for ((j = 0; j < ${#boxNew[@]}; j++)) do boxCur[$j]=${boxNew[$j]} done if (( ${#boxCur[@]} == 8 )) then #calculate current box's starting position for ((j = 0, t = 4; j < 8; j += 2)) do if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi done ((boxCurY = -t)) for ((j = 1, i = -4, t = 20; j < 8; j += 2)) do if ((${boxCur[$j]} > i)); then i=${boxCur[$j]}; fi if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi done ((boxCurX = (iTrayWidth - 1 - i - t) / 2)) echo -ne `DrawCurBox 1` if ! BoxMove $boxCurY $boxCurX then kill -$sigExit ${PPID} ShowExit fi fi #clear old box for ((j = 0; j < 4; j++)) do ((i = iTop + 1 + j)) ((t = iLeft + 2 * iTrayWidth + 7)) echo -ne "\033[${i};${t}H " done #get a random new box ((iBoxNewType = RANDOM % ${#offsetBox[@]})) ((iBoxNewRotate = RANDOM % ${countBox[$iBoxNewType]})) for ((j = 0, i = (${offsetBox[$iBoxNewType]} + $iBoxNewRotate) * 8; j < 8; j++, i++)) do boxNew[$j]=${box[$i]}; done ((cBoxNew = ${colorTable[RANDOM % ${#colorTable[@]}]})) #display new box echo -ne "\033[1m\033[7m\033[3${cBoxNew}m\033[4${cBoxNew}m" for ((j = 0; j < 8; j += 2)) do ((i = iTop + 1 + ${boxNew[$j]})) ((t = iLeft + 2 * iTrayWidth + 7 + 2 * ${boxNew[$j + 1]})) echo -ne "\033[${i};${t}H\040\040" done echo -ne "\033[0m"
} InitDraw(){
clear RandomBox RandomBox local i t1 t2 t3 #draw border echo -ne "\033[1m" echo -ne "\033[3${cBorder}m\033[4${cBorder}m" ((t2 = iLeft + 1)) ((t3 = iLeft + iTrayWidth * 2 + 3)) for ((i = 0; i < iTrayHeight; i++)) do ((t1 = i + iTop + 2)) echo -ne "\033[${t1};${t2}H\040\040" echo -ne "\033[${t1};${t3}H\040\040" done ((t2 = iTop + iTrayHeight + 2)) for ((i = 0; i < iTrayWidth + 2; i++)) do ((t1 = i * 2 + iLeft + 1)) echo -ne "\033[${iTrayTop};${t1}H\040\040" echo -ne "\033[${t2};${t1}H\040\040" done echo -ne "\033[0m" #draw score & level prompt echo -ne "\033[1m" ((t1 = iLeft + iTrayWidth * 2 + 7)) ((t2 = iTop + 10)) echo -ne "\033[3${cScore}m\033[${t2};${t1}HScore" ((t2 = iTop + 11)) echo -ne "\033[3${cScoreValue}m\033[${t2};${t1}H${iScore}" ((t2 = iTop + 13)) echo -ne "\033[3${cScore}m\033[${t2};${t1}HLevel" ((t2 = iTop + 14)) echo -ne "\033[3${cScoreValue}m\033[${t2};${t1}H${iLevel}" echo -ne "\033[0m"
} ShowExit(){
local y ((y = iTrayHeight + iTrayTop + 3)) echo -e "\033[${y};0HGameOver!\033[0m" exit
}
- Start from here.
if $1 != "--go" then
$0 --go& RunAsKeyReceiver $! exit
else
RunAsDisplayer exit
fi </lang>
Java
See Tetris/Java.
Microsoft Small Basic
This game was coded by Small Basic coder Kenneth Kasajian. <lang smallbasic>GraphicsWindow.KeyDown = HandleKey GraphicsWindow.BackgroundColor = GraphicsWindow.GetColorFromRGB( 253, 252, 251 )
While "True"
BOXES = 4 ' number of boxes per piece BWIDTH = 25 ' box width in pixels XOFFSET = 40 ' Screen X offset in pixels of where the board starts YOFFSET = 40 ' Screen Y offset in pixels of where the board starts CWIDTH = 10 ' Canvas Width, in number of boxes CHEIGHT = 20 ' Canvas Height, in number of boxes. STARTDELAY = 800 ENDDELAY = 175 PREVIEW_xpos = 13 PREVIEW_ypos = 2
GraphicsWindow.Clear() GraphicsWindow.Title = "Small Basic Tetris" GraphicsWindow.Height = 580 GraphicsWindow.Width = 700 GraphicsWindow.Show()
SetupTemplates() SetupCanvas() MainLoop()
GraphicsWindow.ShowMessage( "Game Over", "Small Basic Tetris" )
EndWhile
Sub MainLoop
template = Text.Append("template", Math.GetRandomNumber(7))
CreatePiece() ' in: template ret: h nextPiece = h
end = 0 sessionDelay = STARTDELAY While end = 0 If sessionDelay > ENDDELAY Then sessionDelay = sessionDelay - 1 EndIf
delay = sessionDelay thisPiece = nextPiece template = Text.Append("template", Math.GetRandomNumber(7))
CreatePiece() ' in: template ret: h nextPiece = h DrawPreviewPiece()
h = thisPiece
ypos = 0 done = 0 xpos = 3 ' always drop from column 3 CheckStop() ' in: ypos, xpos, h ret: done If done = 1 Then ypos = ypos - 1 MovePiece() 'in: ypos, xpos, h end = 1 EndIf
yposdelta = 0 While done = 0 Or yposdelta > 0 MovePiece() 'in: ypos, xpos, h
' Delay, but break if the delay get set to 0 if the piece gets dropped delayIndex = delay While delayIndex > 0 And delay > 0 Program.Delay(10) delayIndex = delayIndex - 10 EndWhile
If yposdelta > 0 Then yposdelta = yposdelta - 1 ' used to create freespin, when the piece is rotated Else ypos = ypos + 1 ' otherwise, move the piece down. EndIf
' Check if the piece should stop. CheckStop() ' in: ypos, xpos, h ret: done EndWhile EndWhile
EndSub
Sub HandleKey
' Stop game If GraphicsWindow.LastKey = "Escape" Then Program.End() EndIf
' Move piece left If GraphicsWindow.LastKey = "Left" Then moveDirection = -1 ValidateMove() ' in: ypos, xpos, h, moveDirection ret: invalidMove = 1 or -1 or 2 if move is invalid, otherwise 0 If invalidMove = 0 Then xpos = xpos + moveDirection EndIf MovePiece() 'in: ypos, xpos, h EndIf
' Move piece right If GraphicsWindow.LastKey = "Right" Then moveDirection = 1 ValidateMove() ' in: ypos, xpos, h, moveDirection ret: invalidMove = 1 or -1 or 2 if move is invalid, otherwise 0 If invalidMove = 0 Then xpos = xpos + moveDirection EndIf MovePiece() 'in: ypos, xpos, h EndIf
' Move piece down If GraphicsWindow.LastKey = "Down" or GraphicsWindow.LastKey = "Space" Then delay = 0 EndIf
' Rotate piece If GraphicsWindow.LastKey = "Up" Then basetemplate = Array.GetValue(h, -1) ' Array.GetValue(h, -1) = the template name template = "temptemplate" rotation = "CW" CopyPiece() 'in basetemplate, template, rotation
Array.SetValue(h, -1, template) ' Array.GetValue(h, -1) = the template name moveDirection = 0 ValidateMove() ' in: ypos, xpos, h, moveDirection ret: invalidMove = 1 or -1 or 2 if move is invalid, otherwise 0
' See if it can be moved so that it will rotate. xposbk = xpos yposdelta = 0 While yposdelta = 0 And Math.Abs(xposbk - xpos) < 3 ' move up to 3 times only ' if the rotation move worked, copy the temp to "rotatedtemplate" and use that from now on If invalidMove = 0 Then basetemplate = template template = "rotatedtemplate" Array.SetValue(h, -1, template) ' Array.GetValue(h, -1) = the template name rotation = "COPY" CopyPiece() 'in basetemplate, template, rotation yposdelta = 1 ' Don't move down if we rotate MovePiece() 'in: ypos, xpos, h ElseIf invalidMove = 2 Then ' Don't support shifting piece when hitting another piece to the right or left. xpos = 99 ' exit the loop Else ' if the rotated piece can't be placed, move it left or right and try again. xpos = xpos - invalidMove ValidateMove() ' in: ypos, xpos, h, moveDirection ret: invalidMove = 1 or -1 or 2 if move is invalid, otherwise 0 EndIf EndWhile
If invalidMove <> 0 Then xpos = xposbk Array.SetValue(h, -1, basetemplate) ' Array.GetValue(h, -1) = the template name template = "" EndIf EndIf
EndSub
Sub DrawPreviewPiece
xpos = PREVIEW_xpos ypos = PREVIEW_ypos h = nextPiece
XOFFSETBK = XOFFSET YOFFSETBK = YOFFSET XOFFSET = XOFFSET + Array.GetValue(Array.GetValue(h, -1), "pviewx") ' Array.GetValue(h, -1) = the template name YOFFSET = YOFFSET + Array.GetValue(Array.GetValue(h, -1), "pviewy") ' Array.GetValue(h, -1) = the template name MovePiece() 'in: ypos, xpos, h
XOFFSET = XOFFSETBK YOFFSET = YOFFSETBK
EndSub
' creates template that's a rotated basetemplate Sub CopyPiece 'in basetemplate, template, rotation
L = Array.GetValue(basetemplate, "dim")
If rotation = "CW" Then For i = 0 to BOXES - 1 ' x' = y y' = L - 1 - x v = Array.GetValue(basetemplate, i)
'x = Math.Floor(v/10) 'y = Math.Remainder(v, 10)
' new x and y x = (Math.Remainder(v, 10)) y = (L - 1 - Math.Floor(v/10)) Array.SetValue(template, i, x * 10 + y) EndFor ' Count-Cockwise is not currently used ElseIf rotation = "CCW" Then For i = 0 to BOXES - 1 ' x' = L - 1 - y y' = x v = Array.GetValue(basetemplate, i) 'x = Math.Floor(v/10) 'y = Math.Remainder(v, 10)
' new x and y x = (L - 1 - Math.Remainder(v, 10)) y = Math.Floor(v/10) Array.SetValue(template, i, x * 10 + y) EndFor ElseIf rotation = "COPY" Then For i = 0 to BOXES - 1 Array.SetValue(template, i, Array.GetValue(basetemplate, i)) EndFor Else GraphicsWindow.ShowMessage("invalid parameter", "Error") Program.End() EndIf
' Copy the remain properties from basetemplate to template. Array.SetValue(template, "color", Array.GetValue(basetemplate, "color")) Array.SetValue(template, "dim", Array.GetValue(basetemplate, "dim")) Array.SetValue(template, "pviewx", Array.GetValue(basetemplate, "pviewx")) Array.SetValue(template, "pviewy", Array.GetValue(basetemplate, "pviewy"))
EndSub
Sub CreatePiece ' in: template ret: h
' Create a new handle, representing an arrayName, that will represent the piece hcount = hcount + 1 h = Text.Append("piece", hcount)
Array.SetValue(h, -1, template) ' Array.GetValue(h, -1) = the template name
GraphicsWindow.PenWidth = 1 GraphicsWindow.PenColor = "Black" GraphicsWindow.BrushColor = Array.GetValue(template, "color")
For i = 0 to BOXES - 1 s = Shapes.AddRectangle(BWIDTH, BWIDTH) Shapes.Move(s, -BWIDTH, -BWIDTH) ' move off screen Array.SetValue(h, i, s) EndFor
EndSub
Sub MovePiece 'in: ypos, xpos, h. ypos/xpos is 0-19, representing the top/left box coordinate of the piece on the canvas. h returned by CreatePiece
For i = 0 to BOXES - 1 v = Array.GetValue(Array.GetValue(h, -1), i) ' Array.GetValue(h, -1) = the template name x = Math.Floor(v/10) y = Math.Remainder(v, 10)
' Array.GetValue(h, i) = box for piece h. ' xpos/ypos = are topleft of shape. x/y is the box offset within the shape. Shapes.Move(Array.GetValue(h, i), XOFFSET + xpos * BWIDTH + x * BWIDTH, YOFFSET + ypos * BWIDTH + y * BWIDTH) EndFor
EndSub
Sub ValidateMove ' in: ypos, xpos, h, moveDirection ret: invalidMove = 1 or -1 or 2 if move is invalid, otherwise 0
i = 0 invalidMove = 0 While i < BOXES v = Array.GetValue(Array.GetValue(h, -1), i) ' Array.GetValue(h, -1) = the template name
'x/y is the box offset within the shape. x = Math.Floor(v/10) y = Math.Remainder(v, 10)
If (x + xpos + moveDirection) < 0 Then invalidMove = -1 i = BOXES ' force getting out of the loop EndIf
If (x + xpos + moveDirection) >= CWIDTH Then invalidMove = 1 i = BOXES ' force getting out of the loop EndIf
If Array.GetValue("c", (x + xpos + moveDirection) + (y + ypos) * CWIDTH) <> "." Then invalidMove = 2 i = BOXES ' force getting out of the loop EndIf
i = i + 1 EndWhile
EndSub
Sub CheckStop ' in: ypos, xpos, h ret: done
done = 0 i = 0 While i < BOXES v = Array.GetValue(Array.GetValue(h, -1), i) ' Array.GetValue(h, -1) = the template name
'x/y is the box offset within the shape. x = Math.Floor(v/10) y = Math.Remainder(v, 10)
If y + ypos > CHEIGHT Or Array.GetValue("c", (x + xpos) + (y + ypos) * CWIDTH) <> "." Then done = 1 i = BOXES ' force getting out of the loop EndIf
i = i + 1 EndWhile
' If we need to stop the piece, move the box handles to the canvas If done = 1 Then For i = 0 to BOXES - 1 v = Array.GetValue(Array.GetValue(h, -1), i) ' Array.GetValue(h, -1) = the template name 'x = Math.Floor(v/10) 'y = Math.Remainder(v, 10) Array.SetValue("c", (Math.Floor(v/10) + xpos) + (Math.Remainder(v, 10) + ypos - 1) * CWIDTH, Array.GetValue(h, i)) EndFor
' 1 points for every piece successfully dropped score = score + 1 PrintScore()
' Delete clared lines DeleteLines() EndIf
EndSub
Sub DeleteLines
linesCleared = 0
' Iterate over each row, starting from the bottom For y = CHEIGHT - 1 to 0 Step -1
' Check to see if the whole row is filled x = CWIDTH While x = CWIDTH x = 0 While x < CWIDTH piece = Array.GetValue("c", x + y * CWIDTH) If piece = "." then x = CWIDTH EndIf x = x + 1 EndWhile
' if non of them were empty (i.e "."), then remove the line. If x = CWIDTH Then
' Delete the line For x1 = 0 to CWIDTH - 1 Shapes.Remove(Array.GetValue("c", x1 + y * CWIDTH)) EndFor linesCleared = linesCleared + 1
' Move everything else down one. For y1 = y To 1 Step -1 For x1 = 0 to CWIDTH - 1 piece = Array.GetValue("c", x1 + (y1 - 1) * CWIDTH) Array.SetValue("c", x1 + y1 * CWIDTH, piece) Shapes.Move(piece, Shapes.GetLeft(piece), Shapes.GetTop(piece) + BWIDTH) EndFor EndFor EndIf EndWhile EndFor
If linesCleared > 0 Then score = score + 100 * Math.Round(linesCleared * 2.15 - 1) PrintScore() EndIf
EndSub
Sub SetupCanvas ' GraphicsWindow.DrawResizedImage( Flickr.GetRandomPicture( "bricks" ), 0, 0, GraphicsWindow.Width, GraphicsWindow.Height)
GraphicsWindow.BrushColor = GraphicsWindow.BackgroundColor GraphicsWindow.FillRectangle(XOFFSET, YOFFSET, CWIDTH*BWIDTH, CHEIGHT*BWIDTH)
Program.Delay(200) GraphicsWindow.PenWidth = 1 GraphicsWindow.PenColor = "Pink" For x = 0 To CWIDTH-1 For y = 0 To CHEIGHT-1 Array.SetValue("c", x + y * CWIDTH, ".") ' "." indicates spot is free GraphicsWindow.DrawRectangle(XOFFSET + x * BWIDTH, YOFFSET + y * BWIDTH, BWIDTH, BWIDTH) EndFor EndFor
GraphicsWindow.PenWidth = 4 GraphicsWindow.PenColor = "Black" GraphicsWindow.DrawLine(XOFFSET, YOFFSET, XOFFSET, YOFFSET + CHEIGHT*BWIDTH) GraphicsWindow.DrawLine(XOFFSET + CWIDTH*BWIDTH, YOFFSET, XOFFSET + CWIDTH*BWIDTH, YOFFSET + CHEIGHT*BWIDTH) GraphicsWindow.DrawLine(XOFFSET, YOFFSET + CHEIGHT*BWIDTH, XOFFSET + CWIDTH*BWIDTH, YOFFSET + CHEIGHT*BWIDTH)
GraphicsWindow.PenColor = "Lime" GraphicsWindow.DrawLine(XOFFSET - 4, YOFFSET, XOFFSET - 4, YOFFSET + CHEIGHT*BWIDTH + 6) GraphicsWindow.DrawLine(XOFFSET + CWIDTH*BWIDTH + 4, YOFFSET, XOFFSET + CWIDTH*BWIDTH + 4, YOFFSET + CHEIGHT*BWIDTH + 6) GraphicsWindow.DrawLine(XOFFSET - 4, YOFFSET + CHEIGHT*BWIDTH + 4, XOFFSET + CWIDTH*BWIDTH + 4, YOFFSET + CHEIGHT*BWIDTH + 4)
GraphicsWindow.PenColor = "Black" GraphicsWindow.BrushColor = "Pink" x = XOFFSET + PREVIEW_xpos * BWIDTH - BWIDTH y = YOFFSET + PREVIEW_ypos * BWIDTH - BWIDTH GraphicsWindow.FillRectangle(x, y, BWIDTH * 5, BWIDTH * 6) GraphicsWindow.DrawRectangle(x, y, BWIDTH * 5, BWIDTH * 6)
GraphicsWindow.FillRectangle(x - 20, y + 190, 310, 170) GraphicsWindow.DrawRectangle(x - 20, y + 190, 310, 170)
GraphicsWindow.BrushColor = "Black" GraphicsWindow.FontItalic = "False" GraphicsWindow.FontName = "Comic Sans MS" GraphicsWindow.FontSize = 16 GraphicsWindow.DrawText(x, y + 200, "Game control keys:") GraphicsWindow.DrawText(x + 25, y + 220, "Left Arrow = Move piece left") GraphicsWindow.DrawText(x + 25, y + 240, "Right Arrow = Move piece right") GraphicsWindow.DrawText(x + 25, y + 260, "Up Arrow = Rotate piece") GraphicsWindow.DrawText(x + 25, y + 280, "Down Arrow = Drop piece") GraphicsWindow.DrawText(x, y + 320, "Press to stop game")
Program.Delay(200) ' without this delay, the above text will use the fontsize of the score
GraphicsWindow.BrushColor = "Black" GraphicsWindow.FontName = "Georgia" GraphicsWindow.FontItalic = "True" GraphicsWindow.FontSize = 36 GraphicsWindow.DrawText(x - 20, y + 400, "Small Basic Tetris") Program.Delay(200) ' without this delay, the above text will use the fontsize of the score GraphicsWindow.FontSize = 16 GraphicsWindow.DrawText(x - 20, y + 440, "ver.0.1")
Program.Delay(200) ' without this delay, the above text will use the fontsize of the score score = 0 PrintScore()
EndSub
Sub PrintScore
GraphicsWindow.PenWidth = 4 GraphicsWindow.BrushColor = "Pink" GraphicsWindow.FillRectangle(500, 65, 153, 50) GraphicsWindow.BrushColor = "Black" GraphicsWindow.DrawRectangle(500, 65, 153, 50) GraphicsWindow.FontItalic = "False" GraphicsWindow.FontSize = 32 GraphicsWindow.FontName = "Impact" GraphicsWindow.BrushColor = "Black" GraphicsWindow.DrawText(505, 70, Text.Append(Text.GetSubText( "00000000", 0, 8 - Text.GetLength( score ) ), score))
EndSub
Sub SetupTemplates
' each piece has 4 boxes. ' the index of each entry within a piece represents the box number (1-4) ' the value of each entry represents to box zero-based box coordinate within the piece: tens place is x, ones place y
'_X_ '_X_ '_XX
Array.SetValue("template1", 0, 10) Array.SetValue("template1", 1, 11) Array.SetValue("template1", 2, 12) Array.SetValue("template1", 3, 22) Array.SetValue("template1", "color", "Yellow") Array.SetValue("template1", "dim", 3) Array.SetValue("template1", "pviewx", -12) Array.SetValue("template1", "pviewy", 12)
'_X_ '_X_ 'XX_ Array.SetValue("template2", 0, 10) Array.SetValue("template2", 1, 11) Array.SetValue("template2", 2, 12) Array.SetValue("template2", 3, 02) Array.SetValue("template2", "color", "Magenta") Array.SetValue("template2", "dim", 3) Array.SetValue("template2", "pviewx", 12) Array.SetValue("template2", "pviewy", 12)
'_X_ 'XXX '_ Array.SetValue("template3", 0, 10) Array.SetValue("template3", 1, 01) Array.SetValue("template3", 2, 11) Array.SetValue("template3", 3, 21) Array.SetValue("template3", "color", "Gray") Array.SetValue("template3", "dim", 3) Array.SetValue("template3", "pviewx", 0) Array.SetValue("template3", "pviewy", 25)
'XX_ 'XX_ '_ Array.SetValue("template4", 0, 00) Array.SetValue("template4", 1, 10) Array.SetValue("template4", 2, 01) Array.SetValue("template4", 3, 11) Array.SetValue("template4", "color", "Cyan") Array.SetValue("template4", "dim", 2) Array.SetValue("template4", "pviewx", 12) Array.SetValue("template4", "pviewy", 25)
'XX_ '_XX '_ Array.SetValue("template5", 0, 00) Array.SetValue("template5", 1, 10) Array.SetValue("template5", 2, 11) Array.SetValue("template5", 3, 21) Array.SetValue("template5", "color", "Green") Array.SetValue("template5", "dim", 3) Array.SetValue("template5", "pviewx", 0) Array.SetValue("template5", "pviewy", 25)
'_XX 'XX_ '_ Array.SetValue("template6", 0, 10) Array.SetValue("template6", 1, 20) Array.SetValue("template6", 2, 01) Array.SetValue("template6", 3, 11) Array.SetValue("template6", "color", "Blue") Array.SetValue("template6", "dim", 3) Array.SetValue("template6", "pviewx", 0) Array.SetValue("template6", "pviewy", 25)
'_X '_X '_X '_X Array.SetValue("template7", 0, 10) Array.SetValue("template7", 1, 11) Array.SetValue("template7", 2, 12) Array.SetValue("template7", 3, 13) Array.SetValue("template7", "color", "Red") Array.SetValue("template7", "dim", 4) Array.SetValue("template7", "pviewx", 0) Array.SetValue("template7", "pviewy", 0)
EndSub</lang>