Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
143
Task/Snake/C/snake.c
Normal file
143
Task/Snake/C/snake.c
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
// Snake
|
||||
|
||||
// The problem with implementing this task in C is, the language standard
|
||||
// does not cover some details essential for interactive games:
|
||||
// a nonblocking keyboard input, a positional console output,
|
||||
// a and millisecond-precision timer: these things are all system-dependent.
|
||||
|
||||
// Therefore the program is split in two pieces, a system-independent
|
||||
// game logic, and a system-dependent UI, separated by a tiny API:
|
||||
char nonblocking_getch();
|
||||
void positional_putch(int x, int y, char ch);
|
||||
void millisecond_sleep(int n);
|
||||
void init_screen();
|
||||
void update_screen();
|
||||
void close_screen();
|
||||
|
||||
// The implementation of a system-dependent part.
|
||||
// Requires POSIX IEEE 1003.1-2008 compliant system and ncurses library.
|
||||
#ifdef __linux__
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <time.h> // nanosleep
|
||||
#include <ncurses.h> // getch, mvaddch, and others
|
||||
char nonblocking_getch() { return getch(); }
|
||||
void positional_putch(int x, int y, char ch) { mvaddch(x, y, ch); }
|
||||
void millisecond_sleep(int n) {
|
||||
struct timespec t = { 0, n * 1000000 };
|
||||
nanosleep(&t, 0);
|
||||
// for older POSIX standards, consider usleep()
|
||||
}
|
||||
void update_screen() { refresh(); }
|
||||
void init_screen() {
|
||||
initscr();
|
||||
noecho();
|
||||
cbreak();
|
||||
nodelay(stdscr, TRUE);
|
||||
}
|
||||
void close_screen() { endwin(); }
|
||||
#endif
|
||||
|
||||
// An implementation for some other system...
|
||||
#ifdef _WIN32
|
||||
#error "not implemented"
|
||||
#endif
|
||||
|
||||
// The game logic, system-independent
|
||||
#include <time.h> // time
|
||||
#include <stdlib.h> // rand, srand
|
||||
|
||||
#define w 80
|
||||
#define h 40
|
||||
|
||||
int board[w * h];
|
||||
int head;
|
||||
enum Dir { N, E, S, W } dir;
|
||||
int quit;
|
||||
|
||||
enum State { SPACE=0, FOOD=1, BORDER=2 };
|
||||
// negative values denote the snake (a negated time-to-live in given cell)
|
||||
|
||||
// reduce a time-to-live, effectively erasing the tail
|
||||
void age() {
|
||||
int i;
|
||||
for(i = 0; i < w * h; ++i)
|
||||
if(board[i] < 0)
|
||||
++board[i];
|
||||
}
|
||||
|
||||
// put a piece of food at random empty position
|
||||
void plant() {
|
||||
int r;
|
||||
do
|
||||
r = rand() % (w * h);
|
||||
while(board[r] != SPACE);
|
||||
board[r] = FOOD;
|
||||
}
|
||||
|
||||
// initialize the board, plant a very first food item
|
||||
void start(void) {
|
||||
int i;
|
||||
for(i = 0; i < w; ++i)
|
||||
board[i] = board[i + (h - 1) * w] = BORDER;
|
||||
for(i = 0; i < h; ++i)
|
||||
board[i * w] = board[i * w + w - 1] = BORDER;
|
||||
head = w * (h - 1 - h % 2) / 2; // screen center for any h
|
||||
board[head] = -5;
|
||||
dir = N;
|
||||
quit = 0;
|
||||
srand(time(0));
|
||||
plant();
|
||||
}
|
||||
|
||||
void step() {
|
||||
int len = board[head];
|
||||
switch(dir) {
|
||||
case N: head -= w; break;
|
||||
case S: head += w; break;
|
||||
case W: --head; break;
|
||||
case E: ++head; break;
|
||||
}
|
||||
switch(board[head]) {
|
||||
case SPACE:
|
||||
board[head] = len - 1; // keep in mind len is negative
|
||||
age();
|
||||
break;
|
||||
case FOOD:
|
||||
board[head] = len - 1;
|
||||
plant();
|
||||
break;
|
||||
default:
|
||||
quit = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void show() {
|
||||
const char * symbol = " @.";
|
||||
int i;
|
||||
for(i = 0; i < w * h; ++i)
|
||||
positional_putch(i / w, i % w,
|
||||
board[i] < 0 ? '#' : symbol[board[i]]);
|
||||
update_screen();
|
||||
}
|
||||
|
||||
int main (int argc, char * argv[]) {
|
||||
init_screen();
|
||||
start();
|
||||
do {
|
||||
show();
|
||||
switch(nonblocking_getch()) {
|
||||
case 'i': dir = N; break;
|
||||
case 'j': dir = W; break;
|
||||
case 'k': dir = S; break;
|
||||
case 'l': dir = E; break;
|
||||
case 'q': quit = 1; break;
|
||||
}
|
||||
step();
|
||||
millisecond_sleep(100); // beware, this approach
|
||||
// is not suitable for anything but toy projects like this
|
||||
}
|
||||
while(!quit);
|
||||
millisecond_sleep(999);
|
||||
close_screen();
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue