最近整理下电脑,看到了自己在上个学期打的贪吃蛇游戏的c代码,觉得真的是略微有点冗长,但是实现起来应该也算是比较好理解,于是把自己的代码搬上来,网络上写贪吃蛇的c语言的文章很多,我这篇也仅是给大家作为一个参考而已。
我的代码是在Windows下运行的,因为需要用到windows.h这个库。
然后也做了一个简单的ai模式,这在没有障碍物的情况下前期还是蛮不错的,但是到了后期蛇变长了之后就会有bug了。
好了,直接上代码吧:
1)头文件和宏定义
1
2
3
4
5
6
7
8
9
10
11
12
|
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>
#include<windows.h>
#define SNAKE_MAX_LENGTH 20
#define SNAKE_HEAD 'H'
#define SNAKE_BODY 'X'
#define BLANK_CELL ''
#define SNAKE_FOOD '$'
#define WALL_CELL '*'
|
2)各种实现函数的声明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/*snake stepping: dy = -1(up) 1(dowm) 0(no move); dx = -1(left), 1(right), 0(no move)*/
void snakemove( int , int );
//to write dowm the current location of the snake
void put_money( void );
void output( void );
// to put the current map on the screen
void initial_the_game( void );
void put_accelerate( void );
// @ is a special food which can speed up your snake.
int judge( int , int );
/* when it comes to ai, it is used to judge whether the next step is movable. */
int dis( int , int );
// when it coomes to ai, it is used to calculate the current distence //between the snake head and the food.
void welcome( void ); // the game introduction.
void gameover( void );
void edition_handed( void );
// the edition in which you can play by yourself.
void edition_presentation( void );
// the edition in which the snake can go automatically.
|
3)各种全局变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// define vars for snake,notice name of vars in c
int snakeX[SNAKE_MAX_LENGTH] = {1, 2, 3, 4, 5};
int snakeY[SNAKE_MAX_LENGTH] = {1, 1, 1, 1, 1};
int snakeLength = 5;
int gamestate = 1;
int current_speed = 600;
int score = 0;
char edition_choose; // for player to choose the edition.
int con = 1; // to judge the initial state of the game;
int energy = 0; // write down the condition to accelerate by eating $.
//the following part is to realize the simple ai .
const char movable[4] = { 'a' , 'd' , 's' , 'w' };
int distance[4] = {9999, 9999, 9999, 9999};
int fx = 6, fy = 6; // the coordinate of the food $
|
4)地图
1
2
3
4
5
6
7
8
9
10
11
12
13
|
char map[12][12] =
{ "************" ,
"*XXXXH *" ,
"* *" ,
"* *" ,
"* *" ,
"* *" ,
"* $ *" ,
"* *" ,
"* @ *" ,
"* *" ,
"* *" ,
"************" };
|
5)主函数(可选模式)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
int main() {
while (con) {
welcome();
int flag = 1;
while (flag) {
edition_choose = getch(); //choose the edition
if (edition_choose == 'h' ) {
edition_handed();
flag = 0;
}
else if (edition_choose == 'p' ) {
edition_presentation();
flag = 0;
}
else {
printf ( "Please press the correct bottom -,- ...\n" );
}
}
gameover();
}
return 0;
}
|
6)手动模式实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
void edition_handed( void ) {
system ( "cls" );
output();
char ch = 'd' ;
while (gamestate) {
switch (ch) {
case 'a' : // go left
while (1) {
snakemove(-1, 0);
Sleep(current_speed);
if (gamestate == 0) // to break the loop if the snake hit the wall or itself.
break ;
if (kbhit() != 0) { // to change the direction
ch = getch();
if (ch == 's' || ch == 'w' )
break ;
else
ch = 'a' ;
}
}
break ;
case 'd' : // go right
while (1) {
snakemove(1, 0);
Sleep(current_speed);
if (gamestate == 0)
break ;
if (kbhit() != 0)
ch = getch();
if (ch == 's' || ch == 'w' )
break ;
else
ch = 'd' ;
}
break ;
case 's' : // go down
while (1) {
snakemove(0, 1);
Sleep(current_speed);
if (gamestate == 0)
break ;
if (kbhit() != 0)
ch = getch();
if (ch == 'a' || ch == 'd' )
break ;
else
ch = 's' ;
}
break ;
case 'w' : // go up
while (1) {
snakemove(0, -1);
Sleep(current_speed);
if (gamestate == 0)
break ;
if (kbhit() != 0)
ch = getch();
if (ch == 'a' || ch == 'd' )
break ;
else
ch = 'w' ;
}
break ;
}
if (gamestate == 0)
break ;
}
return ;
}
|
7)自动模式实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
void edition_presentation( void ) { // for ai
system ( "cls" );
int i, min = 10000;
output();
char ch;
char quit = 'o' ;
int k;
while (gamestate) { // find the shortest way;
min = 10000;
if (judge(-1, 0)) distance[0] = dis(-1, 0);
if (judge(1, 0)) distance[1] = dis(1, 0);
if (judge(0, 1)) distance[2] = dis(0, 1);
if (judge(0, -1)) distance[3] = dis(0, -1);
for (i = 0; i < 4; i++) {
if (min >= distance[i]) {
min = distance[i];
k = i;
}
}
Sleep(current_speed);
switch (movable[k]) {
case 'a' : // go left
snakemove(-1, 0);
break ;
case 'd' : // go right
snakemove(1, 0);
break ;
case 's' : // go down
snakemove(0, 1);
break ;
case 'w' : // go up
snakemove(0, -1);
break ;
}
if (gamestate == 0)
break ;
system ( "cls" );
output();
}
return ;
}
|
8)其他辅助函数
欢迎界面
1
2
3
4
5
6
7
8
9
10
11
12
13
|
void welcome( void ) { // just for some introduction
printf ( "WELCOME TO THE SNAKE'S WORLD !!!!\n" );
printf ( "\n" );
printf ( "\n" );
printf ( "Please choose the edition you want.\n" );
printf ( "\n" );
printf ( "\n" );
printf ( "The 'h' is for the hand-operated and the 'p' is for the simple presentation\n" );
printf ( "\n" );
printf ( "\n" );
printf ( "Attention: the presentation still has a liitle bug, while it can be moving right for a period of time...\n " );
return ;
}
|
游戏结束界面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
void gameover( void ) { // give you some introduction when you lose the game.
system ( "cls" );
printf ( "Game over!!!\n" );
printf ( "Do you want to continue? y or n\n" );
char start; // in order to judge whether you still want to play the game.
while (1) {
start = getch();
if (start == 'y' ) {
system ( "cls" );
initial_the_game();
break ;
} else if (start == 'n' ) {
system ( "cls" );
con = 0; // in order to let the game end.
printf ( "See you next time! ^-^\n" );
break ;
} else {
printf ( "Please press the correct buttom.\n" );
}
}
}
|
图像实现方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
void output( void ) { // put the cuttent game map.
printf ( "THE INTERESTING SNAKE GAME CREATED BY LONGJ =,=\n" );
printf ( "use w~s~a~d to control the snake's movement\n" );
printf ( "ATTENTION: the @ can speed up your lovely snake~~\n" );
int i, j;
for (i = 0; i < 12; i++) {
for (j = 0; j < 12; j++) {
printf ( "%c" , map[i][j]);
if (j == 11)
printf ( "\n" );
}
}
printf ( "Your current_speed is %d\n" , current_speed);
printf ( "The number of your food undigested is %d (when it comes to 5, your speed will be accelerated!) \n" , energy);
printf ( "SCORE = %d\n" , score);
return ;
}
|
蛇的行走实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
void snakemove( int dx, int dy) { // all the conditions are comparing the head and the next position.
int i;
if (snakeY[snakeLength - 1] + dy == snakeY[snakeLength - 2] && snakeX[snakeLength - 1] + dx == snakeX[snakeLength - 2])
return ; // to prevent it go to itslef.
if (map[snakeY[snakeLength - 1] + dy][snakeX[snakeLength - 1] + dx] == 'X' ) {
gamestate = 0;
return ;
}
if (map[snakeY[snakeLength - 1] + dy][snakeX[snakeLength - 1] + dx] == '*' ) {
gamestate = 0;
return ;
}
if (map[snakeY[snakeLength - 1] + dy][snakeX[snakeLength - 1] + dx] == ' '
|| map[snakeY[snakeLength - 1] + dy][snakeX[snakeLength - 1] + dx] == '@' ) {
map[snakeY[0]][snakeX[0]] = ' ' ; // clear the former_tail
if (map[snakeY[snakeLength - 1] + dy][snakeX[snakeLength - 1] + dx] == '@'
&& current_speed > 100) { // what will happen when your snake eats the @
current_speed -= 100;
put_accelerate();
}
for (i = 0; i < snakeLength - 1; ++i) {
snakeX[i] = snakeX[i + 1];
snakeY[i] = snakeY[i + 1];
}
snakeX[snakeLength - 1] += dx;
snakeY[snakeLength - 1] += dy;
for (i = 0; i < snakeLength - 1; i++) // write down the current snake location
map[snakeY[i]][snakeX[i]] = 'X' ;
map[snakeY[snakeLength - 1]][snakeX[snakeLength - 1]] = 'H' ;
}
if (map[snakeY[snakeLength - 1] + dy][snakeX[snakeLength - 1] + dx] == '$' ) {
map[snakeY[snakeLength - 1]][snakeX[snakeLength - 1]] = 'X' ;
snakeLength++;
snakeX[snakeLength - 1] = snakeX[snakeLength - 2] + dx;
snakeY[snakeLength - 1] = snakeY[snakeLength - 2] + dy;
map[snakeY[snakeLength - 1]][snakeX[snakeLength - 1]] = 'H' ;
score++;
energy++;
if (energy == 5 && current_speed > 50) {
current_speed -= 50;
energy = 0;
}
put_money();
}
system ( "cls" );
output();
return ;
}
|
食物放置的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
void put_money( void ) { /// ai will change the code
int flag = 1;
while (flag) {
srand ( time (NULL));
fx = rand () % 12;
fy = rand () % 12;
if (map[fy][fx] == ' ' ) {
map[fy][fx] = '$' ;
flag = 0;
}
if (edition_choose == 'p' ) {
int i;
for (i = 0; i< 4; i++)
distance[i] = 9999;
}
}
return ;
}
void put_accelerate( void ) {
int x, y, flag = 1;
while (flag) {
srand ( time (NULL));
x = rand () % 12;
y = rand () % 12;
if (map[x][y] == ' ' ) {
map[x][y] = '@' ;
flag = 0;
}
}
return ;
}
|
ai辅助函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
int dis( int dx, int dy) {
return abs (fx - snakeX[snakeLength - 1] - dx) + abs (fy - snakeY[snakeLength - 1] - dy);
}
int judge( int dx, int dy) {
if (map[snakeY[snakeLength - 1] + dy][snakeX[snakeLength - 1] + dx] == ' ' )
return 1;
else if (map[snakeY[snakeLength - 1] + dy][snakeX[snakeLength - 1] + dx] == '$' )
return 1;
else if (map[snakeY[snakeLength - 1] + dy][snakeX[snakeLength - 1] + dx] == '@' )
return 1;
else
return 0;
}
|
游戏over后的初始化函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
void initial_the_game( void ) {
int i, j, count = 1;
snakeLength = 5;
gamestate = 1;
fx = fy = 6;
current_speed = 600;
for (i = 0; i < 5; i++)
snakeY[i] = 1;
for (i = 0; i < 5; i++) {
snakeX[i] = count++;
}
for (j = 0; j < 12; j++) {
map[0][j] = '*' ;
map[11][j] = '*' ;
}
for (i = 1; i < 11; i++) {
map[i][0] = map[i][11] = '*' ;
for (j = 1; j < 11; j++)
map[i][j] = ' ' ;
}
map[fy][fx] = '$' ;
map[8][4] = '@' ;
for (i = 0; i< 4; i++) {
distance[i] = 9999;
}
for (i = 0; i < 4; i++)
map[snakeY[i]][snakeX[i]] = 'X' ;
map[snakeY[4]][snakeX[4]] = 'H' ;
return ;
}
|
小结:
不难看出,c语言代码比较冗长,而且初始化的函数实现起来十分麻烦,稍有不慎就会全部出错,导致游戏无法持续玩下去,博主当初写的时候就是被坑了很久=_=
因而现在在学c++,希望以后把类的概念之类的东西都弄得更加熟练之后,可以去把这个冗长的c代码改成更加简洁,阅读性更强的c++代码。
(好的,已经更新了,写出了一个比较简单的C++贪吃蛇,的确是思路清晰很多,代码的可读性更高。)
这篇博客给那些想要用c来写贪吃蛇的同学一些参考,运行起来是没有问题的,可以选择性看:)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://blog.csdn.net/luojj26/article/details/50799620