Tetris: Difference between revisions
(→{{headerJava}}: added link to Java entry) |
(→{{header|BASH}}: link to bash entry) |
||
Line 18: | Line 18: | ||
No further requirement about randomizer / rotation system / DAS / colors / difficulty levels / score / hold, but you may do it if you wish. |
No further requirement about randomizer / rotation system / DAS / colors / difficulty levels / score / hold, but you may do it if you wish. |
||
=={{header|BASH}}== |
=={{header|BASH}}== |
||
<lang BASH>#!/bin/bash |
|||
See [[Tetris/Bash]]. |
|||
# 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" || $key == "w" ]]; then sig=$sigRotate |
|||
elif [[ $key == "S" || $key == "s" ]]; then sig=$sigDown |
|||
elif [[ $key == "A" || $key == "a" ]]; then sig=$sigLeft |
|||
elif [[ $key == "D" || $key == "d" ]]; then sig=$sigRight |
|||
elif [[ "[$key]" == "[]" ]]; then sig=$sigAllDown |
|||
elif [[ $key == "Q" || $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> |
|||
=={{header|Java}}== |
=={{header|Java}}== |
Revision as of 11:23, 23 March 2016
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
See Tetris/Bash.
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>