贪吃蛇模拟小程序注意点:
1. 蛇不能出界。
2. 食物不能出界,也不能出现在蛇身上。
1. 单头蛇的模拟: //蛇不能直接后退
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#define SIZE 21
#define AREA SIZE-1
#define MAXLEN 100
#define SNAKE_MAX_LEN 100
#define ESC 0x1b
#define LEFT_ARROW_KEY 75
#define UP_ARROW_KEY 72
#define RIGHT_ARROW_KEY 77
#define DOWN_ARROW_KEY 80
volatile int food_count = 0;
typedef enum direction{up, down, left, right, logout, none} direction_t;
typedef enum ctlcmd{restart, end} ctlcmd_t;
typedef struct point {
int x;
int y;
} point_t;
static point_t food = {-1,-1};
typedef struct snake {
point_t points[MAXLEN];
int max_len;
int cur_len;
direction_t dir;
} snake_t;
void clearScreen() {
system("cls");
}
void initSnake(snake_t *snake) {
int i;
int x = SIZE >> 1;
int y = SIZE >> 1;
snake->cur_len = 3;
snake->max_len = MAXLEN;
snake->points[0].x = x;
snake->points[0].y = y;
snake->points[1].x = x;
snake->points[1].y = y+1;
snake->points[2].x = x;
snake->points[2].y = y+2;
for(i=3; i<snake->max_len; i++){
snake->points[i].x = -1;
snake->points[i].y = -1;
}
snake->dir = up;
}
void initMatrix(char matrix[SIZE][SIZE]) {
int i=0;
int j=0;
for(i=0; i<SIZE; i++) {
for(j=0; j<SIZE; j++) {
matrix[i][j] = ' ';
if(i==0) matrix[i][j] = '-'; //上边界
if(j==AREA) matrix[i][j]='|'; //右边界
if(i==AREA) matrix[i][j]='-'; //下边界
if(j==0) matrix[i][j] = '|'; //左边界
}
printf("\n");
}
}
void getRandomFood(char matrix[SIZE][SIZE], snake_t *snake) {
int i;
int x;
int y;
int max = AREA - 1;
srand((unsigned)time(NULL));
if(food_count == 0)
{
do {
x = rand() % max + 1;
y = rand() % max + 1;
for(i=0; i<snake->cur_len; i++) {
if(x==snake->points[i].x && y==snake->points[i].y) break;
}
if(i!=snake->cur_len) continue;
} while(0);
food.x = x;
food.y = y;
matrix[x][y] = 'X';
food_count++;
}
}
void drawSnakeToMatrix(char matrix[SIZE][SIZE], snake_t *snake) {
int i;
for(i=0; i<snake->cur_len; i++) {
matrix[snake->points[i].x][snake->points[i].y]= 'o';
}
}
void drawMatrix(char matrix[SIZE][SIZE]) {
int i;
int j;
clearScreen();
for(i=0; i<SIZE; i++) {
for(j=0; j<SIZE; j++) {
printf("%c ", matrix[i][j]);
}
printf("\n");
}
printf("******Game Rules****** \n");
printf(" 方向: left: a; up: w; right: d; down: s; 或者使用方向键;\n");
printf("O表示蛇,X表示食物,当没有食物时,说明你胜利了,请按ESC键退出 \n");
}
direction_t changeDirection() {
char c;
direction_t dir;
while(!kbhit());
c = getch();
switch (c) {
case 'a':
case LEFT_ARROW_KEY:
dir = left;
break;
case 'w':
case UP_ARROW_KEY:
dir = up;
break;
case 'd':
case RIGHT_ARROW_KEY:
dir = right;
break;
case 's':
case DOWN_ARROW_KEY:
dir = down;
break;
case ESC:
dir = logout;
break;
default:
dir = none;
}
return dir;
}
void moveSnake(char matrix[SIZE][SIZE], snake_t *snake, direction_t dir) {
point_t next_point;
int tag = 1;
int last;
int i;
if(dir == none) return;
switch(dir) {
case left:
if(snake->dir == right) {
tag = 0;
} else {
snake->dir = left;
next_point.y = snake->points[0].y-1;
next_point.x = snake->points[0].x;
if(next_point.y == 0) next_point.y = AREA-1;
}
break;
case right:
if(snake->dir == left) {
tag = 0;
}else {
snake->dir = right;
next_point.y = snake->points[0].y+1;
next_point.x = snake->points[0].x;
if(next_point.y == AREA) next_point.y = 1;
}
break;
case up:
if(snake->dir == down) {
tag = 0;
}else {
snake->dir = up;
next_point.y = snake->points[0].y;
next_point.x = snake->points[0].x-1;
if(next_point.x == 0) next_point.x = AREA-1;
}
break;
case down:
if(snake->dir == up) {
tag = 0;
}else {
snake->dir = down;
next_point.y = snake->points[0].y;
next_point.x = snake->points[0].x+1;
if(next_point.x==AREA) next_point.x = 1;
}
break;
}
if(tag){
last = snake->cur_len - 1;
if(next_point.x==food.x && next_point.y==food.y) {
snake->cur_len++;
last++;
food_count--;
matrix[food.x][food.y] = ' ';
getRandomFood(matrix, snake);
}else {
matrix[snake->points[last].x][snake->points[last].y] = ' ';
}
for(i=last; i>0; i--) {
snake->points[i].x = snake->points[i-1].x;
snake->points[i].y = snake->points[i-1].y;
}
snake->points[0].x = next_point.x;
snake->points[0].y = next_point.y;
}
}
void sankeGame() {
char matrix[SIZE][SIZE];
snake_t snake;
direction_t dir;
initSnake(&snake);
initMatrix(matrix);
while(1) {
getRandomFood(matrix, &snake);
drawSnakeToMatrix(matrix, &snake);
drawMatrix(matrix);
dir = changeDirection();
if(dir == logout) break;
moveSnake(matrix, &snake, dir);
}
}
int main(int argc, char *argv[], char *env[])
{
sankeGame();
clearScreen();
printf("\n\n\t\t********SNAKE GAME OVER ******* \n\n\n");
printf("\n\n\n press any key to exit this window!\n\n\n");
getch();
return 0;
}
2.双头蛇的模拟: 蛇可以后退。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#define SIZE 21
#define AREA SIZE-1
#define MAXLEN 100
#define SNAKE_MAX_LEN 100
#define ESC 0x1b
#define LEFT_ARROW_KEY 75
#define UP_ARROW_KEY 72
#define RIGHT_ARROW_KEY 77
#define DOWN_ARROW_KEY 80
volatile int food_count = 0;
typedef enum direction{up, down, left, right, logout, none} direction_t;
typedef struct point {
int x;
int y;
} point_t;
static point_t food = {-1,-1};
typedef struct snake {
point_t points[MAXLEN];
int max_len;
int cur_len;
direction_t dir;
} snake_t;
void swap(point_t *p, point_t *q) {
point_t tmp = *p;
*p = *q;
*q = tmp;
}
void reverseArray(point_t *array, int start, int end) {
for( ; start<end; start++, end--){
swap(array+start, array+end);
}
}
void clearScreen() {
system("cls");
}
void initSnake(snake_t *snake) {
int i;
int x = SIZE >> 1;
int y = SIZE >> 1;
snake->cur_len = 3;
snake->max_len = MAXLEN;
snake->points[0].x = x;
snake->points[0].y = y;
snake->points[1].x = x;
snake->points[1].y = y+1;
snake->points[2].x = x;
snake->points[2].y = y+2;
for(i=3; i<snake->max_len; i++){
snake->points[i].x = -1;
snake->points[i].y = -1;
}
snake->dir = up;
}
void initMatrix(char matrix[SIZE][SIZE]) {
int i=0;
int j=0;
for(i=0; i<SIZE; i++) {
for(j=0; j<SIZE; j++) {
matrix[i][j] = ' ';
if(i==0) matrix[i][j] = '-'; //上边界
if(j==AREA) matrix[i][j]='|'; //右边界
if(i==AREA) matrix[i][j]='-'; //下边界
if(j==0) matrix[i][j] = '|'; //左边界
}
printf("\n");
}
}
void getRandomFood(char matrix[SIZE][SIZE], snake_t *snake) {
int i;
int x;
int y;
int max = AREA - 1;
srand((unsigned)time(NULL));
if(food_count == 0)
{
do {
x = rand() % max + 1;
y = rand() % max + 1;
for(i=0; i<snake->cur_len; i++) {
if(x==snake->points[i].x && y==snake->points[i].y) break;
}
if(i!=snake->cur_len) continue;
} while(0);
food.x = x;
food.y = y;
matrix[x][y] = 'X';
food_count++;
}
}
void drawSnakeToMatrix(char matrix[SIZE][SIZE], snake_t *snake) {
int i;
for(i=0; i<snake->cur_len; i++) {
matrix[snake->points[i].x][snake->points[i].y]= 'o';
}
}
void drawMatrix(char matrix[SIZE][SIZE]) {
int i;
int j;
clearScreen();
for(i=0; i<SIZE; i++) {
for(j=0; j<SIZE; j++) {
printf("%c ", matrix[i][j]);
}
printf("\n");
}
printf("******Game Rules****** \n");
printf(" 方向: left: a; up: w; right: d; down: s; 或者使用方向键;\n");
printf("O表示蛇,X表示食物,当没有食物时,说明你胜利了,请按ESC键退出 \n");
}
direction_t changeDirection() {
char c;
direction_t dir;
while(!kbhit());
c = getch();
switch (c) {
case 'a':
case LEFT_ARROW_KEY:
dir = left;
break;
case 'w':
case UP_ARROW_KEY:
dir = up;
break;
case 'd':
case RIGHT_ARROW_KEY:
dir = right;
break;
case 's':
case DOWN_ARROW_KEY:
dir = down;
break;
case ESC:
dir = logout;
break;
default:
dir = none;
}
return dir;
}
void reverseSnake(snake_t *snake) {
reverseArray(snake->points, 0, snake->cur_len - 1 );
}
void moveSnake(char matrix[SIZE][SIZE], snake_t *snake, direction_t dir) {
point_t next_point;
int tag = 1;
int last;
int i;
if(dir == none) return;
switch(dir) {
case left:
if(snake->dir == right) {
reverseSnake(snake);
}
snake->dir = left;
next_point.y = snake->points[0].y-1;
next_point.x = snake->points[0].x;
if(next_point.y == 0) next_point.y = AREA-1;
break;
case right:
if(snake->dir == left) {
reverseSnake(snake);
}
snake->dir = right;
next_point.y = snake->points[0].y+1;
next_point.x = snake->points[0].x;
if(next_point.y == AREA) next_point.y = 1;
break;
case up:
if(snake->dir == down) {
reverseSnake(snake);
}
snake->dir = up;
next_point.y = snake->points[0].y;
next_point.x = snake->points[0].x-1;
if(next_point.x == 0) next_point.x = AREA-1;
break;
case down:
if(snake->dir == up) {
reverseSnake(snake);
}
snake->dir = down;
next_point.y = snake->points[0].y;
next_point.x = snake->points[0].x+1;
if(next_point.x==AREA) next_point.x = 1;
break;
}
if(tag){
last = snake->cur_len - 1;
if(next_point.x==food.x && next_point.y==food.y) {
snake->cur_len++;
last++;
food_count--;
matrix[food.x][food.y] = ' ';
getRandomFood(matrix, snake);
}else {
matrix[snake->points[last].x][snake->points[last].y] = ' ';
}
for(i=last; i>0; i--) {
snake->points[i].x = snake->points[i-1].x;
snake->points[i].y = snake->points[i-1].y;
}
snake->points[0].x = next_point.x;
snake->points[0].y = next_point.y;
}
}
void sankeGame() {
char matrix[SIZE][SIZE];
snake_t snake;
direction_t dir;
initSnake(&snake);
initMatrix(matrix);
while(1) {
getRandomFood(matrix, &snake);
drawSnakeToMatrix(matrix, &snake);
drawMatrix(matrix);
dir = changeDirection();
if(dir == logout) break;
moveSnake(matrix, &snake, dir);
}
}
int main(int argc, char *argv[], char *env[])
{
sankeGame();
clearScreen();
printf("\n\n\t\t********SNAKE GAME OVER ******* \n\n\n");
printf("\n\n\n press any key to exit this window!\n\n\n");
getch();
return 0;
}
总结: 每次的重绘,没有做好,好像有抖动,其次是否能用多线程使程序的并发性更好!
其他获取按键的ASCII码的方法:
void printCharKeyASCII() {
int ch;
ch = getch();
printf("%c : %d\n", ch, ch);
}
void testKeyASCII() {
int ch;
while((ch=getch()) != 0X1B) { //按ESC退出
printf("%c : %d\n", ch, ch);
}
}