Tetris: Difference between revisions
No edit summary |
|||
Line 24: | Line 24: | ||
See [[Tetris/Java]]. |
See [[Tetris/Java]]. |
||
=={{header| |
=={{header|Julia}}== |
||
See [[Tetris/ |
See [[Tetris/Julia]]. |
||
{{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}}== |
=={{header|Mathematica}}== |
Revision as of 23:04, 23 October 2018
- Task
Create a playable Tetris game.
- Requirements
- a left / right key
- a hard drop key (the current piece will be dropped and locked at once)
- a rotation key
- a preview piece
- full set of 7 kinds of shapes (ITOSZJL)
Applesoft BASIC
Bash
See Tetris/BASH.
Java
See Tetris/Java.
Julia
See Tetris/Julia.
<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>
Mathematica
See Tetris/Mathematica.