Task: Snake

C: 








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();



#ifdef __linux__
#define _POSIX_C_SOURCE 200809L
#include <time.h> 
#include <ncurses.h> 
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);
	
}
void update_screen() { refresh(); }
void init_screen() {
	initscr();
	noecho();
	cbreak();
	nodelay(stdscr, TRUE);
}
void close_screen() { endwin(); }
#endif


#ifdef _WIN32
#error "not implemented"
#endif


#include <time.h> 
#include <stdlib.h> 

#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 };



void age() {
        int i;
	for(i = 0; i < w * h; ++i)
		if(board[i] < 0)
			++board[i];
}


void plant() {
	int r;
	do
		r = rand() % (w * h);
	while(board[r] != SPACE);
	board[r] = FOOD;
}


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; 
	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; 
			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); 
		
	}
	while(!quit);
	millisecond_sleep(999);
	close_screen();
	return 0;
}











Ada: 



with Ada.Containers; use Ada.Containers;
with Ada.Containers.Vectors;

package Snake is
   
   
   
   type directions is (Up, Down, Right, Left, Quit, Restart, Invalid);
   
   
   function Get_Immediate return Character;

   Arrow_Prefix : constant Character := Character'Val(224); 

   function Get_Keystroke return directions;
   
   
   
   type gameBoard is array (Natural range <>, Natural range <>) of Character;
   
   
   procedure init;
   
   
   procedure run;  
   
   
   procedure Display_Board;
   
   procedure ClearBoard;
   
   
   type coord is tagged record
      X,Y : Integer;
   end record;

   
   package snakeBody is new Ada.Containers.Vectors (Natural, coord);
   use snakeBody;
   
   
   function moveSnake return Boolean;
   
   
   procedure generateFood;
   
   
   procedure addDataToBoard;
   
   
   function getRandomInteger(upperBound : Integer) return Integer;
   
private
   
   width, height : Positive := 10;
   board : gameBoard := (0 .. (width+1) => (0 .. (height+1) => ' '));
   snake : Vector := (1,1) & (2,1) & (3,1);
   snakeDirection : directions := Right;
   
   food : coord := (5,5);

end Snake;




with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Discrete_Random;

package body Snake is
   
   
   
   function Get_Immediate return Character is
   begin
      return Answer : Character do Ada.Text_IO.Get_Immediate(Answer);
      end return;
   end Get_Immediate;

   
   
   function Get_Keystroke return directions is
     (case Get_Immediate is
         when 'Q' | 'q' => Quit,
         when 'R' | 'r' => Restart,
         when 'W' | 'w' => Left,
         when 'A' | 'a' => Up,
         when 'S' | 's' => Down,
         when 'D' | 'd' => Right,
         
         when Arrow_Prefix => (case Character'Pos(Get_Immediate) is
                                  when 72 => Up,
                                  when 75 => Left,
                                  when 77 => Right,
                                  when 80 => Down,
                                  when others => Invalid),
         
         when ASCII.ESC => (case Get_Immediate is
                               when '[' => (case Get_Immediate is
                                               when 'A' => Up,
                                               when 'B' => Down,
                                               when 'C' => Right,
                                               when 'D' => Left,
                                               when others => Invalid),
                               when others => Invalid),
         when others => Invalid);
   
   
   procedure init is
   begin
      
      for Row in 0 .. width+1 loop
         for Column in 0 .. height+1 loop
            
            if Row = 0 or Row = width+1 then
               board(Row,Column) := '#';
               
            else
               if Column = 0 or Column = height+1 then
                  board(Row,Column) := '#';
                  
               else
                  board(Row,Column) := ' ';
                  
               end if;
            end if;
            
         end loop;
      end loop;  
   end;

   
   procedure run is
      
      task T;
      task body T is
      begin
         loop
            snakeDirection := Get_Keystroke;
         end loop;
      end T;
      
   begin
      
      init;
      loop
         exit when snakeDirection = Quit;
      
         if moveSnake = False then
            Put_Line("GAME OVER!!!");
            Put_Line("Your score is:" & Length(snake)'Image);
            exit;
         end if;
      
      
         Display_Board;
         delay 0.7;
         
      end loop;
   end run;
   
   
   procedure Display_Board is
   begin
      
      for Row in 0 .. width+1 loop
         for Column in 0 .. height+1 loop
            Put(board(Row, Column));
         end loop;
         New_Line;
      end loop; 
      
   end Display_Board;
   
   
   procedure ClearBoard is
   begin
      
      for Row in 1 .. width loop
         for Column in 1 .. height loop
            board(Row, Column) := ' ';
         end loop;
      end loop; 
      
   end ClearBoard;
   
   
   function moveSnake return Boolean is
      colision : Boolean := False;
      headCoord : coord := Snake.First_Element;
      addSnakePart : Boolean := False;
   begin
      
      case snakeDirection is
         when Up => headCoord.X := headCoord.X - 1;
         when Down => headCoord.X := headCoord.X + 1;
         when Right => headCoord.Y := headCoord.Y + 1;
         when Left => headCoord.Y := headCoord.Y - 1;
         when others => null;
      end case;
      
      if headCoord.Y = height+1 then
         return False;
      end if;
      
      if headCoord.Y = 0 then
         return False;
      end if;
      
      if headCoord.X = width+1 then
         return False;
      end if;
      
      if headCoord.X = 0 then
         return False;
      end if;
      
      for index in snake.Iterate loop
         if headCoord = snake(To_Index(index)) then
            return False;
         end if;
      end loop;

      snake.Prepend(headCoord);
      
      if headCoord /= food then
         snake.Delete_Last;
      else
         food := (0,0);
         generateFood;
      end if;
      
      addDataToBoard;

      return True;
   end moveSnake;
   
   
   procedure generateFood is
   begin
      if food.X = 0 or food.Y = 0 then
         food := (getRandomInteger(width), getRandomInteger(height));
      end if;
   end generateFood;
   
   
   procedure addDataToBoard is
   begin
      ClearBoard;
      
      board(food.X, food.Y) := '*';
      
      for index in snake.Iterate loop
         board(snake(To_Index(index)).X, snake(To_Index(index)).Y) := 'o';
      end loop;
      
   end addDataToBoard;

   
   function getRandomInteger(upperBound : Integer) return Integer is

      subtype Random_Range is Integer range 1 .. upperBound;

      package R is new
        Ada.Numerics.Discrete_Random (Random_Range);
      use R;

      G : Generator;
   begin
      Reset (G);
      return Random (G);
   end getRandomInteger;

end Snake;




with Snake;

procedure Main is
begin
   Snake.run;
end;