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

Last change on this file since 3598 was 3598, checked in by sam, 5 years ago

Add a simple snake program using the <conio.h> interface.

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