Tetris: Difference between revisions

5,439 bytes added ,  5 years ago
No edit summary
Line 24:
See [[Tetris/Java]].
 
=={{header|JavaScriptJulia}}==
 
See [[Tetris/JavaScriptJulia]].
{{works with|Julia|1.0}}
<lang julia>using Random
struct B4
bg::Int # ANSI code of tetromino color (bground of " ")
d::Array{Int,2} # d[b,1:2] = row,col/2 offset of block b
# constructor: Z = B4(101,[0 0; 0 1; 1 1; 1 2])
function B4(bg,A::Array{Int,2}) # - fills in centered offsets for tetromino
new(bg, A .- sum.(extrema(A,dims=1)).>>1)
end end
# print tetromino on playfield
function draw(b::B4,r::Integer,c::Integer,clr::Integer=-1)
print("\e[$(clr & b.bg)m") # set color. (0 = default colors)
for i=1:4 print("\e[$(r+b.d[i,1]);$(c+2b.d[i,2])H ") end
end
# hit other B4s or border?
function hit(B::B4,r::Integer,c::Integer)::Bool
for i=1:4 BD[r+B.d[i,1],c>>1+B.d[i,2]+2]>0 && return true end
return false
end
# move tetrominos left/right/down, if no hit
function mov(B::B4,r::Integer,c::Integer,x::Integer,y::Integer)
hit(B,r+x,c+y) || (draw(B,r,c,0);draw(B,r+=x,c+=y))
global tmr = Timer(tm); return (r,c)
end
# rotate tetrominos left/right, if no hit
function rot(B::B4,r::Integer,c::Integer,rigt=0::Integer)
A = deepcopy(B)
for i=1:4 A.d[i,:]=rigt>0 ? [A.d[i,2],3-A.d[i,1]] : [3-A.d[i,2],A.d[i,1]] end
A.d .-= sum.(extrema(A.d,dims=1)).>>1 # centralize
global tmr = Timer(tm)
for j = c.+(0,+2,-2) # try shifted positions
hit(A,r,j) || (draw(B,r,c,0); draw(A,r,j); return (A,j))
end
return (B,c) # cannot rotate: all 3 positions hit
end
# record-place,clear-full-lines,drop-above,score
function mark(B::B4,r::Integer,c::Integer)
global lines, score, level; ln = 0
for i=1:4 BD[r+B.d[i,1],c>>1+B.d[i,2]+2]=B.bg end # record stuck B4
for i in r.+sort(unique(B.d[:,1])) # in board: empty full rows; drop part above
if all(BD[i,3:12].>0) ln += 1
for j = i-1:-1:1 BD[j+1,3:12] = BD[j,3:12] end
print("\e[0m\e[$i;2H$s20"); sleep(0.3)
end end # update display from board data ->
for i=1:22,j=3:12 print("\e[$(BD[i,j])m\e[$i;$(2j-4)H ") end
ln > 0 && (lines+=ln; score += (level+1)*(100,300,500,800)[ln])
level=isqrt(lines>>3) # updates lines, score, level
end
# Setup nonblocking, non-echoed keyboard input
ccall(:jl_tty_set_mode,Cint,(Ptr{Cvoid},Cint),stdin.handle,1)==0 ||
throw("Terminal cannot enter raw mode.") # raw terminal mode to catch keystrokes
const chnl = Channel{Array{UInt8,1}}(0) # short channel for key codes
@async while true put!(chnl,readavailable(stdin)) end # task catching keystrokes
 
I = B4(106,[0 0; 0 1; 0 2; 0 3]) # define the 7 tetrominos
T = B4(105,[0 1; 1 0; 1 1; 1 2]); O = B4(103,[0 0; 0 1; 1 0; 1 1])
S = B4(102,[0 1; 0 2; 1 0; 1 1]); Z = B4(101,[0 0; 0 1; 1 1; 1 2])
J = B4(104,[0 0; 1 0; 1 1; 1 2]); L = B4(107,[0 2; 1 0; 1 1; 1 2])
 
begin @label RESTART # @label - @goto: require begin..end
global lines,score,level,s20 = 0,0,0," "^20
BD=fill(0,24,15); for j=3:12 BD[23,j]=BD[24,j]=1 end
for i=1:24,j=(1,2,13,14,15) BD[i,j]=1 end # Board border. screen_C = 2j-4
 
print("\e[0m\e[2J\e[?25l") # default colors/clear screen/hide cursor
for i=1:22 print("\e[$i;1H▐$(s20)▌") end# BORDER ->
print("\e[23;1H▝$("▀"^20)▘") # ROWS=1:22, COLS=2:2:20, Center=10,11
print("\n\n$s20\n$s20"); X0 = (I,T,O,S,Z,J,L)[rand(1:7)]
 
while true # random B4, timer to drop, act on keystrokes
global lines,score,level,tm,tmr
draw(X0,24,10,0)
global X0,X,r,c = (I,T,O,S,Z,J,L)[rand(1:7)],X0,2,10
draw(X0,24,10)
print("\e[0m\e[27;1H Level =\t$level\n Lines filled =\t$lines\n Score =\t$score")
tm=(.8-level*.007)^level; tmr=Timer(0.5) # fixed 0.5s first delay
hit(X,r,c) && (println("\n\n Game Over!...press a key for restart");
take!(chnl); @goto RESTART )
while isready(chnl) take!(chnl) end # flush keystrokes
while true
global X,r,c,tm,tmr
if !isopen(tmr) # time to drop tetromino by a line
hit(X,r+1,c) && (mark(X,r,c); break)
draw(X,r,c,0); draw(X,r+=1,c); tmr=Timer(tm)
end
while isready(chnl) # are there queued keystrokes?
global X,r,c,score
ch = take!(chnl) # take keys
if ch==[0x1b,0x5b,0x41] X,c=rot(X,r,c) # UP
elseif ch==[0x1b,0x5b,0x42] r,c=mov(X,r,c,1, 0);score+=1# DOWN
elseif ch==[0x1b,0x5b,0x43] r,c=mov(X,r,c,0, 2) # RIGHT
elseif ch==[0x1b,0x5b,0x44] r,c=mov(X,r,c,0,-2) # LEFT
elseif ch==[0x61] X,c=rot(X,r,c) # a
elseif ch==[0x64] X,c=rot(X,r,c,1) # d
elseif ch==[0x20] r0=r; draw(X,r,c,0); tmr=Timer(tm) # SPACE
while !hit(X,r+=1,c) end; draw(X,r-=1,c);score+=2r-2r0; continue
elseif ch==[0x1b,0x5b,0x31,0x7e] # HOME
println("\e[0m\e[?25h\e[31;1H RESTARTING...press a key")
take!(chnl); @goto RESTART
elseif ch==[0x1b,0x5b,0x34,0x7e] # END
println("\e[0m\e[?25h\e[31;1H EXITING...press a key")
take!(chnl); return
end end
sleep(0.01) # not to take all CPU core time
end end end</lang>
 
=={{header|Mathematica}}==