RosettaCodeData/Task/Snake/Phix/snake.phix

82 lines
2.3 KiB
Plaintext

constant W = 60, H = 30, MAX_LEN = 600
enum NORTH, EAST, SOUTH, WEST
sequence board, snake
bool alive
integer tailIdx, headIdx, hdX, hdY, d, points
procedure createField()
clear_screen()
board = repeat("+"&repeat(' ',W-2)&'+',H)
for x=1 to W do
board[1,x] = '+'
end for
board[H] = board[1]
board[1+rand(H-2),1+rand(W-2)] = '@';
snake = repeat(0,MAX_LEN)
board[3,4] = '#'; tailIdx = 1; headIdx = 5;
for c=tailIdx to headIdx do
snake[c] = {3,3+c}
end for
{hdY,hdX} = snake[headIdx-1]; d = EAST; points = 0;
end procedure
procedure drawField()
for y=1 to H do
for x=1 to W do
integer t = board[y,x]
if t!=' ' then
position(y,x)
if x=hdX and y=hdY then
text_color(14); puts(1,'O');
else
text_color({10,9,12}[find(t,"#+@")]); puts(1,t);
end if
end if
end for
end for
position(H+1,1); text_color(7); printf(1,"Points: %d",points)
end procedure
procedure readKey()
integer k = find(get_key(),{333,331,328,336})
if k then d = {EAST,WEST,NORTH,SOUTH}[k] end if
end procedure
procedure moveSnake()
integer x,y
switch d do
case NORTH: hdY -= 1
case EAST: hdX += 1
case SOUTH: hdY += 1
case WEST: hdX -= 1
end switch
integer t = board[hdY,hdX];
if t!=' ' and t!='@' then alive = false; return; end if
board[hdY,hdX] = '#'; snake[headIdx] = {hdY,hdX};
headIdx += 1; if headIdx>MAX_LEN then headIdx = 1 end if
if t=='@' then
points += 1
while 1 do
x = 1+rand(W-2); y = 1+rand(H-2);
if board[y,x]=' ' then
board[y,x] = '@'
return
end if
end while
end if
{y,x} = snake[tailIdx]; position(y,x); puts(1,' '); board[y,x] = ' ';
tailIdx += 1; if tailIdx>MAX_LEN then tailIdx = 1 end if
end procedure
procedure play()
while true do
createField(); alive = true; cursor(NO_CURSOR)
while alive do drawField(); readKey(); moveSnake(); sleep(0.05) end while
cursor(BLOCK_CURSOR); position(H+2,1); bk_color(0); text_color(11);
puts(1,"Play again [Y/N]? ")
if upper(wait_key())!='Y' then return end if
end while
end procedure
play()