| 1 |
module snake; |
|---|
| 2 |
import qd, tools.base, tools.mersenne; |
|---|
| 3 |
|
|---|
| 4 |
struct pt { int x, y; } |
|---|
| 5 |
struct Snake { pt[] fields; } |
|---|
| 6 |
|
|---|
| 7 |
import tools.log; |
|---|
| 8 |
class Field { |
|---|
| 9 |
enum State { empty, apple, snake } |
|---|
| 10 |
State[] board; |
|---|
| 11 |
int width, height; |
|---|
| 12 |
mixin This!("width, height; #board.length=width*height; #snake.fields ~= pt(width/2, height/2); "); |
|---|
| 13 |
State getState(pt p) { return board[p.y*width+p.x]; } |
|---|
| 14 |
void setState(pt p, State s) { board[p.y*width+p.x] = s; } |
|---|
| 15 |
void updateState() { |
|---|
| 16 |
foreach (ref entry; board) if (entry != State.apple) entry = State.empty; |
|---|
| 17 |
foreach (part; snake.fields) setState(part, State.snake); |
|---|
| 18 |
} |
|---|
| 19 |
enum Direction { up, left, down, right } |
|---|
| 20 |
Direction dir; |
|---|
| 21 |
Snake snake; |
|---|
| 22 |
bool outside(pt p) { return p.x < 0 || p.y < 0 || p.x !< width || p.y !< height; } |
|---|
| 23 |
void spawnApple() { |
|---|
| 24 |
pt rp; |
|---|
| 25 |
do { rp = pt(rand % width, rand % height); } while (getState(rp) != State.empty); |
|---|
| 26 |
setState(rp, State.apple); |
|---|
| 27 |
} |
|---|
| 28 |
void step() { |
|---|
| 29 |
scope(exit) updateState; |
|---|
| 30 |
pt next = snake.fields[$-1]; |
|---|
| 31 |
[{next.y --; }, {next.x --; }, {next.y ++; }, {next.x ++; }][dir](); |
|---|
| 32 |
if (outside(next)) throw new Exception("You have left the board!"); |
|---|
| 33 |
if (getState(next) == State.snake) throw new Exception("You have lost!"); |
|---|
| 34 |
snake.fields ~= next; |
|---|
| 35 |
if (getState(next) != State.apple) with (snake) fields = fields[1 .. $]; |
|---|
| 36 |
else spawnApple; |
|---|
| 37 |
} |
|---|
| 38 |
void draw() { |
|---|
| 39 |
line(10, 10, 10+width*16, 10+height*16, Box=White); |
|---|
| 40 |
for (int x = 0; x < width; ++x) |
|---|
| 41 |
for (int y = 0; y < height; ++y) |
|---|
| 42 |
switch (getState(pt(x, y))) { |
|---|
| 43 |
case State.apple: circle(10+x*16+8, 10+y*16+8, 7.5, Fill=Red); break; |
|---|
| 44 |
case State.snake: circle(10+x*16+8, 10+y*16+8, 7.5, Fill=Green); break; |
|---|
| 45 |
default: break; |
|---|
| 46 |
} |
|---|
| 47 |
} |
|---|
| 48 |
} |
|---|
| 49 |
|
|---|
| 50 |
import tools.time; |
|---|
| 51 |
void main() { |
|---|
| 52 |
screen(640, 480); |
|---|
| 53 |
auto field = new Field(39, 29); |
|---|
| 54 |
for (int i = 0; i < 8; ++i) field.spawnApple; |
|---|
| 55 |
while (true) { |
|---|
| 56 |
cls; |
|---|
| 57 |
events; |
|---|
| 58 |
foreach (i, k; [SDLKey.Up, SDLKey.Left, SDLKey.Down, SDLKey.Right]) |
|---|
| 59 |
if (key.pressed(k)) field.dir = cast(Field.Direction) i; |
|---|
| 60 |
field.step; field.draw; |
|---|
| 61 |
flip; |
|---|
| 62 |
sleep(0.3); |
|---|
| 63 |
} |
|---|
| 64 |
} |
|---|