You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

223 line
6.8 KiB

  1. /*
  2. * conio-snake snake game using the <conio.h> API
  3. * Copyright (c) 2003-2004 Simon Huggins <webmaster#simonhuggins.com>
  4. * 2009-2010 Sam Hocevar <sam@hocevar.net>
  5. * All Rights Reserved
  6. *
  7. * Permission to use, copy, modify, and/or distribute this software for any
  8. * purpose with or without fee is hereby granted, provided that the above
  9. * copyright notice and this permission notice appear in all copies.
  10. *
  11. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  12. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  13. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  14. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  15. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  16. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  17. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  18. */
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <caca_conio.h>
  22. /* prototypes */
  23. void draw_line(int col, int row);
  24. void show_score();
  25. void add_segment();
  26. void setup_level();
  27. /* constants */
  28. const int maxrow=15, maxcol=77;
  29. const int snake_start_col=33,snake_start_row=7;
  30. const char up_key='a', down_key='z', left_key='o', right_key='p';
  31. const int pause_length=500000;
  32. /* global variables */
  33. int score, snake_length, speed, obstacles, level, firstpress, high_score=0;
  34. char screen_grid[maxrow][maxcol];
  35. char direction = right_key;
  36. struct snake_segment {
  37. int row,col;
  38. } snake[100];
  39. int main()
  40. {
  41. /* Variable declarations within main() only */
  42. char keypress=0;
  43. do /* restart game loop */
  44. {
  45. obstacles=4; level=1; score=0; speed=14;
  46. //randomize(); /* Ensure random seed initiated */
  47. setup_level();
  48. /* main loop */
  49. do
  50. {
  51. delay(speed * pause_length / 50000); /*pause*/
  52. /* If key has been hit, then check it is a direction key - if so,
  53. change direction */
  54. if (kbhit())
  55. {
  56. keypress=(char)getch();
  57. if((keypress==right_key)||(keypress==left_key)||
  58. (keypress==up_key)||(keypress==down_key))
  59. direction = keypress;
  60. }
  61. /* Add a segment to the end of the snake */
  62. add_segment();
  63. /* Blank last segment of snake */
  64. gotoxy(snake[0].col,snake[0].row);
  65. cprintf(" ");
  66. /* ... and remove it from the array */
  67. for (int i=1;i<=snake_length;i++)
  68. snake[i-1]=snake[i];
  69. /* Display snake in yellow */
  70. textcolor(YELLOW);
  71. for (int i=0;i<=snake_length;i++)
  72. {
  73. gotoxy(snake[i].col,snake[i].row);
  74. cprintf("O");
  75. }
  76. /* keeps cursor flashing in one place instead of following snake */
  77. gotoxy(1,1);
  78. /* If first press on each level, pause until a key is pressed */
  79. if (firstpress) { while(!kbhit()); firstpress = 0; }
  80. /* Collision detection - walls (bad!) */
  81. if ((snake[snake_length-1].row>maxrow+1)||(snake[snake_length-1].row<=1)||
  82. (snake[snake_length-1].col>maxcol+1)||(snake[snake_length-1].col<=1)||
  83. /* Collision detection - obstacles (bad!) */
  84. (screen_grid[snake[snake_length-1].row-2][snake[snake_length-1].col-2]=='x'))
  85. keypress='x'; /* i.e. exit loop - game over */
  86. /* Collision detection - snake (bad!) */
  87. for (int i=0;i<snake_length-1;i++)
  88. if ( (snake[snake_length-1].row)==(snake[i].row) &&
  89. (snake[snake_length-1].col)==(snake[i].col))
  90. {
  91. keypress='x'; /* i.e. exit loop - game over */
  92. break; /* no need to check any more segments */
  93. }
  94. /* Collision detection - food (good!) */
  95. if (screen_grid[snake[snake_length-1].row-2][snake[snake_length-1].col-2]=='.')
  96. {
  97. /* increase score and length of snake */
  98. score+=snake_length*obstacles; show_score(); snake_length++; add_segment();
  99. /* if length of snake reaches certain size, onto next level */
  100. if (snake_length==(level+3)*2)
  101. {
  102. score+=level*1000; obstacles+=2; level++; /* add to obstacles */
  103. if ((level%5==0)&&(speed>1)) speed--; /* increase speed every 5 levels */
  104. setup_level(); /* display next level */
  105. }
  106. }
  107. } while (keypress!='x');
  108. /* game over message */
  109. if (score > high_score) high_score = score;
  110. show_score();
  111. gotoxy(30,6); textcolor(LIGHTRED); cprintf("G A M E O V E R");
  112. gotoxy(30,9); textcolor(YELLOW); cprintf("Another Game (y/n)? ");
  113. do keypress=getch(); while((keypress!='y')&&(keypress!='n'));
  114. } while (keypress=='y');
  115. }
  116. void setup_level()
  117. {
  118. /* variables local to setup_level() */
  119. int row,col;
  120. /* Set up global variables for new level */
  121. snake_length=level+4; direction = right_key;
  122. firstpress = 1;
  123. /* Fill grid with blanks */
  124. for(row=0;row<maxrow;row++)
  125. for(col=0;col<maxcol;col++)
  126. screen_grid[row][col]= ' ';
  127. /* Fill grid with Xs and food */
  128. for(int i=0;i<obstacles*2;i++)
  129. {
  130. row= rand()%maxrow;
  131. col= rand()%maxcol;
  132. if(i<obstacles)
  133. screen_grid[row][col]='x';
  134. else
  135. screen_grid[row][col]='.';
  136. }
  137. /* Create snake array of length snake_length */
  138. for(int i=0;i<snake_length;i++)
  139. {
  140. snake[i].row=snake_start_row;
  141. snake[i].col=snake_start_col+i;
  142. }
  143. /* Draw playing board */
  144. draw_line(1,1);
  145. for(row=0;row<maxrow;row++)
  146. {
  147. gotoxy(1,row+2);
  148. textcolor(LIGHTBLUE); cprintf("|");
  149. textcolor(WHITE);
  150. for(col=0;col<maxcol;col++)
  151. cprintf("%c",screen_grid[row][col]);
  152. textcolor(LIGHTBLUE);
  153. cprintf("|");
  154. }
  155. draw_line(1,maxrow+2);
  156. show_score();
  157. gotoxy(2,maxrow+5);
  158. textcolor(LIGHTRED);
  159. cprintf("~~ SNAKE GAME~~ Left: %c, Right: %c, Up: %c, Down: %c, Exit: x. Any key to start.",
  160. left_key,right_key,up_key,down_key);
  161. }
  162. void draw_line(int col, int row)
  163. {
  164. gotoxy(col,row); textcolor(LIGHTBLUE);
  165. for (col=0;col<maxcol+2;col++) cprintf("=");
  166. }
  167. void show_score()
  168. {
  169. textcolor(LIGHTCYAN);
  170. gotoxy(2,maxrow+3);
  171. cprintf("Level: %05d",level);
  172. gotoxy(40,maxrow+3);
  173. textcolor(LIGHTGREEN);
  174. cprintf("Score: %05d",score);
  175. gotoxy(60,maxrow+3);
  176. textcolor(LIGHTMAGENTA);
  177. cprintf("High Score: %05d",high_score);
  178. }
  179. void add_segment()
  180. {
  181. switch(direction)
  182. {
  183. case(right_key): snake[snake_length].row=snake[snake_length-1].row;
  184. snake[snake_length].col=snake[snake_length-1].col+1;
  185. break;
  186. case(left_key) : snake[snake_length].row=snake[snake_length-1].row;
  187. snake[snake_length].col=snake[snake_length-1].col-1;
  188. break;
  189. case(up_key) : snake[snake_length].row=snake[snake_length-1].row-1;
  190. snake[snake_length].col=snake[snake_length-1].col;
  191. break;
  192. case(down_key) : snake[snake_length].row=snake[snake_length-1].row+1;
  193. snake[snake_length].col=snake[snake_length-1].col;
  194. }
  195. }