source: libcaca/trunk/examples/conio-snake.cpp @ 4369

Last change on this file since 4369 was 4369, checked in by Sam Hocevar, 12 years ago

Add the copyright unit test and update copyright information everywhere.

  • Property svn:keywords set to Id
File size: 6.8 KB
Line 
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
20#include <stdlib.h>
21#include <stdio.h>
22#include <caca_conio.h>
23
24/* prototypes */
25void draw_line(int col, int row);
26void show_score();
27void add_segment();
28void setup_level();
29
30/* constants */
31const int maxrow=15, maxcol=77;
32const int snake_start_col=33,snake_start_row=7;
33const char up_key='a', down_key='z', left_key='o', right_key='p';
34const int pause_length=500000;
35
36/* global variables */
37int score, snake_length, speed, obstacles, level, firstpress, high_score=0;
38char screen_grid[maxrow][maxcol];
39char direction = right_key;
40struct snake_segment {
41  int row,col;
42} snake[100];
43
44int main()
45{
46
47  /* Variable declarations within main() only */
48  char keypress=0;
49
50  do /* restart game loop */
51  {
52    obstacles=4; level=1; score=0; speed=14;
53
54    //randomize(); /* Ensure random seed initiated */
55
56    setup_level();
57
58    /* main loop */
59    do
60    {
61      delay(speed * pause_length / 50000); /*pause*/
62
63      /* If key has been hit, then check it is a direction key - if so,
64         change direction */
65      if (kbhit())
66      {
67        keypress=(char)getch();
68        if((keypress==right_key)||(keypress==left_key)||
69           (keypress==up_key)||(keypress==down_key))
70          direction = keypress;
71      }
72
73      /* Add a segment to the end of the snake */
74      add_segment();
75
76      /* Blank last segment of snake */
77      gotoxy(snake[0].col,snake[0].row);
78      cprintf(" ");
79      /* ... and remove it from the array */
80        for (int i=1;i<=snake_length;i++)
81          snake[i-1]=snake[i];
82      /* Display snake in yellow */
83      textcolor(YELLOW);
84      for (int i=0;i<=snake_length;i++)
85      {
86        gotoxy(snake[i].col,snake[i].row);
87        cprintf("O");
88      }
89      /* keeps cursor flashing in one place instead of following snake */
90      gotoxy(1,1);
91
92      /* If first press on each level, pause until a key is pressed */
93      if (firstpress) { while(!kbhit()); firstpress = 0; }
94
95      /* Collision detection - walls (bad!) */
96      if ((snake[snake_length-1].row>maxrow+1)||(snake[snake_length-1].row<=1)||
97          (snake[snake_length-1].col>maxcol+1)||(snake[snake_length-1].col<=1)||
98      /* Collision detection - obstacles (bad!) */
99          (screen_grid[snake[snake_length-1].row-2][snake[snake_length-1].col-2]=='x'))
100        keypress='x'; /* i.e. exit loop - game over */
101      /* Collision detection - snake (bad!) */
102      for (int i=0;i<snake_length-1;i++)
103        if ( (snake[snake_length-1].row)==(snake[i].row) &&
104             (snake[snake_length-1].col)==(snake[i].col))
105        {
106          keypress='x'; /* i.e. exit loop - game over */
107          break; /* no need to check any more segments */
108        }
109      /* Collision detection - food (good!) */
110      if (screen_grid[snake[snake_length-1].row-2][snake[snake_length-1].col-2]=='.')
111      {
112        /* increase score and length of snake */
113        score+=snake_length*obstacles; show_score(); snake_length++; add_segment();
114        /* if length of snake reaches certain size, onto next level */
115        if (snake_length==(level+3)*2)
116        {
117          score+=level*1000; obstacles+=2; level++;  /* add to obstacles */
118          if ((level%5==0)&&(speed>1)) speed--; /* increase speed every 5 levels */
119          setup_level(); /* display next level */
120        }
121      }
122    } while (keypress!='x');
123
124    /* game over message */
125    if (score > high_score) high_score = score;
126    show_score();
127    gotoxy(30,6); textcolor(LIGHTRED); cprintf("G A M E   O V E R");
128    gotoxy(30,9); textcolor(YELLOW); cprintf("Another Game (y/n)? ");
129    do keypress=getch(); while((keypress!='y')&&(keypress!='n'));
130
131  } while (keypress=='y');
132}
133
134void setup_level()
135{
136
137 /* variables local to setup_level() */
138 int row,col;
139
140  /* Set up global variables for new level */
141  snake_length=level+4; direction = right_key;
142  firstpress = 1;
143 /* Fill grid with blanks */
144  for(row=0;row<maxrow;row++)
145    for(col=0;col<maxcol;col++)
146     screen_grid[row][col]= ' ';
147
148  /* Fill grid with Xs and food */
149  for(int i=0;i<obstacles*2;i++)
150  {
151   row= rand()%maxrow;
152   col= rand()%maxcol;
153   if(i<obstacles)
154     screen_grid[row][col]='x';
155   else
156     screen_grid[row][col]='.';
157  }
158
159  /* Create snake array of length snake_length */
160  for(int i=0;i<snake_length;i++)
161  {
162    snake[i].row=snake_start_row;
163    snake[i].col=snake_start_col+i;
164  }
165
166  /* Draw playing board */
167  draw_line(1,1);
168  for(row=0;row<maxrow;row++)
169  {
170    gotoxy(1,row+2);
171    textcolor(LIGHTBLUE); cprintf("|");
172    textcolor(WHITE);
173    for(col=0;col<maxcol;col++)
174      cprintf("%c",screen_grid[row][col]);
175    textcolor(LIGHTBLUE);
176    cprintf("|");
177  }
178  draw_line(1,maxrow+2);
179
180  show_score();
181  gotoxy(2,maxrow+5);
182  textcolor(LIGHTRED);
183  cprintf("~~ SNAKE GAME~~ Left: %c, Right: %c, Up: %c, Down: %c, Exit: x. Any key to start.",
184          left_key,right_key,up_key,down_key);
185}
186
187void draw_line(int col, int row)
188{
189  gotoxy(col,row); textcolor(LIGHTBLUE);
190  for (col=0;col<maxcol+2;col++) cprintf("=");
191}
192
193void show_score()
194{
195  textcolor(LIGHTCYAN);
196  gotoxy(2,maxrow+3);
197  cprintf("Level: %05d",level);
198  gotoxy(40,maxrow+3);
199  textcolor(LIGHTGREEN);
200  cprintf("Score: %05d",score);
201  gotoxy(60,maxrow+3);
202  textcolor(LIGHTMAGENTA);
203  cprintf("High Score: %05d",high_score);
204}
205void add_segment()
206{
207  switch(direction)
208  {
209    case(right_key): snake[snake_length].row=snake[snake_length-1].row;
210                     snake[snake_length].col=snake[snake_length-1].col+1;
211                     break;
212    case(left_key) : snake[snake_length].row=snake[snake_length-1].row;
213                     snake[snake_length].col=snake[snake_length-1].col-1;
214                     break;
215    case(up_key)   : snake[snake_length].row=snake[snake_length-1].row-1;
216                     snake[snake_length].col=snake[snake_length-1].col;
217                     break;
218    case(down_key) : snake[snake_length].row=snake[snake_length-1].row+1;
219                     snake[snake_length].col=snake[snake_length-1].col;
220  }
221}
222
Note: See TracBrowser for help on using the repository browser.