分析:
想要写出贪吃蛇,就要知道里面的规则,规则很简单就是移动的蛇吃到食物蛇身增加1,撞到墙或撞到自己(也可以设置成可以通过蛇身)失败。
1.首先要在屏幕上显示蛇框,蛇框中包含蛇身、果实,代码如下(这里是使用颜色显示):
void map(int maps[20][20], int looks[4], int move[20][20])
{
int i;
int j;
int x;
int y;
for(i = 0; i <= 16; i++)
{
for(j = 0; j <= 16; j++)
{
if(i == 0 || i == 16 || j == 0 || j == 16)
{
maps[i][j] = 1;
}else
{
maps[i][j] = 0;
}
move[i][j] = 0;
}
}
maps[8][8] = 3;
move[8][8] = 1;
move[0][0] = 1;
x = rand() % 15 + 1;//范围是1-15
y = rand() % 15 + 1;
maps[x][y] = 2;//有果实
looks[0] = 1;//表示朝向,向上
looks[1] = 1;//长度
looks[2] = 0;//分数
looks[3] = 0;//1失败
for(i = 0; i <= 16; i++)
{
for(j = 0; j <= 16; j++)
{
gotoxy(i * 2, j);
switch (maps[i][j]) {
case 0:
BackGround(0, 0);
break;//如果没有东西打印黑色
case 1:
BackGround(0, 1);
break;//墙打印蓝色
case 2:
BackGround(0, 2);
break;//果实打印绿色
case 3:
BackGround(0, 3);
break;//蛇打印湖蓝色
default:
break;
}
printf(" ");
}
}
gotoxy(35, 0);
BackGround(7, 0);
}
其中已经包含初始化,不使用颜色来显示是可以的,只需要将有关颜色部分换成你设定的东西。0黑色 1蓝色 2 绿色 3湖蓝色
这里要强调一下:上面的look[4]数组,其中的元素实际上是状态,比如look[3] = 0,0就表示成功,当在这种状态时会执行相应的事件,第一次写的时候使用的是标记,但这种写法有点混乱,使用状态的写法让代码更简便。
2.规则和移动,代码如下:
void rule(int maps[20][20], int looks[4], int xy[2], int move[20][20])
{
int ctr;
int x;
int y;
int i;
int j;
x = y = 0;
if(kbhit())
{
ctr = getch();
if(ctr == 224)
{
ctr = getch();
}
if(ctr == 72 && looks[0] != 2)
{
looks[0] = 1;
}
if(ctr == 80 && looks[0] != 1)
{
looks[0] = 2;
}
if(ctr == 75 && looks[0] != 4)
{
looks[0] = 3;
}
if(ctr == 77 && looks[0] != 3)
{
looks[0] = 4;
}
}
switch(looks[0])
{
case 1:
xy[1]--;
break;
case 2:
xy[1]++;
break;
case 3:
xy[0]--;
break;
case 4:
xy[0]++;
break;
}
move[0][0]++;
move[xy[0]][xy[1]] = move[0][0];
gotoxy(35, 2);
BackGround(7, 0);
gotoxy(xy[0] * 2, xy[1]);//这里蛇头就往前移动了
BackGround(0, 3);//与蛇体一个颜色
printf(" ");
if(maps[xy[0]][xy[1]] == 2)
{
looks[2]++;
looks[1]++;
gotoxy(35, 0);
BackGround(7, 0);
printf("现在得分是:%d", looks[2]);
while (maps[x][y] != 0) {
x = rand() % 15 + 1;
y = rand() % 15 + 1;
}
maps[x][y] = 2;//将这个地方变为果实
gotoxy(x * 2, y);
BackGround(0, 2);
printf(" ");
}
if(maps[xy[0]][xy[1]] == 1 || maps[xy[0]][xy[1]] == 3)
{
looks[3] = 1;
gotoxy(0, 24);
BackGround(7, 0);
printf("游戏结束,最后得分:%d", looks[2]);
return;
}
maps[xy[0]][xy[1]] = 3;
for(i = 0;i <= 16; i++)
{
for ( j = 0; j <= 16; j++)
{
if (move[i][j] == move[xy[0]][xy[1]] - looks[1])
{
maps[i][j] = 0;
gotoxy(i * 2, j);
BackGround(0, 0);
printf(" ");
gotoxy(47,0);
break;
}
}
}
}
这里需要注意,方向键的ASCLL值:上72,左75,右77,下80,1表示状态上,2表示状态下,3表示状态左,4表示状态右。
xy[1]表示行坐标,xy[0]表示列坐标,这里的i*2是在屏幕上打印一个矩形的颜色,maps[20][20]表示地图信息,move[20][20]表示蛇移动的信息,蛇移动一次,其中move[0][0]步数就加1,并把步数赋给当前的蛇头,以便判断蛇为,蛇尾的判断方法是用步数减蛇身。
3.逻辑规则(代码如下):
int main()
{
int maps[20][20];
int looks[4];
int move[20][20];
int xy[2];
int i;
int j;
xy[0] = xy[1] = 8;
srand((unsigned) time(NULL));
system("pause");
map(maps, looks, move);
while(looks[3] == 0)
{
Sleep(300);
rule(maps, looks, xy, move);
}
system("pause");
gotoxy(0,25);
printf("游戏结束,任意键退出!");
return 0;
}
look[3]中保存的就是失败和成功的状态。
总结:写贪吃蛇,首先要知道其规则,接下来分析,将问题拆分,每个问题采用合适的方法解决,我这种方式只是一种,还会有更简练的算法。
全部代码:
#include <stdio.h>
#include <windows.h>
#include <time.h>
#include <conio.h>
#include <stdlib.h>
//方向键的ASCLL值:上72,左75,右77,下80
//背景颜色的代码: 0=黑色 1蓝色 2 绿色 3湖蓝色 7白色
void BackGround(unsigned int ForeColor , unsigned int BackGroundColor );
void BackGround(unsigned int ForeColor , unsigned int BackGroundColor ) {
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台的句柄
SetConsoleTextAttribute(handle, ForeColor + BackGroundColor * 0x10);//改变当前光标的背景和字体颜色
}
void gotoxy(int x, int y);
void gotoxy(int x, int y)
{
HANDLE handle;
COORD coord;
coord.X = x;
coord.Y = y;
handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(handle, coord);
}
void map(int maps[20][20], int looks[4], int move[20][20]);
void rule(int maps[20][20], int looks[4], int xy[2], int move[20][20]);
void map(int maps[20][20], int looks[4], int move[20][20])
{
int i;
int j;
int x;
int y;
for(i = 0; i <= 16; i++)
{
for(j = 0; j <= 16; j++)
{
if(i == 0 || i == 16 || j == 0 || j == 16)
{
maps[i][j] = 1;
}else
{
maps[i][j] = 0;
}
move[i][j] = 0;
}
}
maps[8][8] = 3;
move[8][8] = 1;
move[0][0] = 1;
x = rand() % 15 + 1;//范围是1-15
y = rand() % 15 + 1;
maps[x][y] = 2;//有果实
looks[0] = 1;//表示朝向,向上
looks[1] = 1;//长度
looks[2] = 0;//分数
looks[3] = 0;//1失败
for(i = 0; i <= 16; i++)
{
for(j = 0; j <= 16; j++)
{
gotoxy(i * 2, j);
switch (maps[i][j]) {
case 0:
BackGround(0, 0);
break;//如果没有东西打印黑色
case 1:
BackGround(0, 1);
break;//墙打印蓝色
case 2:
BackGround(0, 2);
break;//果实打印绿色
case 3:
BackGround(0, 3);
break;//蛇打印湖蓝色
default:
break;
}
printf(" ");//地图中直接就是涂空格符
}
}
gotoxy(35, 0);
BackGround(7, 0);
}
void rule(int maps[20][20], int looks[4], int xy[2], int move[20][20])
{
int ctr;
int x;
int y;
int i;
int j;
x = y = 0;
if(kbhit())
{
ctr = getch();
if(ctr == 224)
{
ctr = getch();
}
if(ctr == 72 && looks[0] != 2)
{
looks[0] = 1;
}
if(ctr == 80 && looks[0] != 1)
{
looks[0] = 2;
}
if(ctr == 75 && looks[0] != 4)
{
looks[0] = 3;
}
if(ctr == 77 && looks[0] != 3)
{
looks[0] = 4;
}
}
switch(looks[0])
{
case 1:
xy[1]--;
break;
case 2:
xy[1]++;
break;
case 3:
xy[0]--;
break;
case 4:
xy[0]++;
break;
}
move[0][0]++;
move[xy[0]][xy[1]] = move[0][0];
gotoxy(35, 2);
BackGround(7, 0);
gotoxy(xy[0] * 2, xy[1]);//这里蛇头就往前移动了
BackGround(0, 3);//与蛇体一个颜色
printf(" ");
if(maps[xy[0]][xy[1]] == 2)
{
looks[2]++;
looks[1]++;
gotoxy(35, 0);
BackGround(7, 0);
printf("现在得分是:%d", looks[2]);
while (maps[x][y] != 0) {
x = rand() % 15 + 1;
y = rand() % 15 + 1;
}
maps[x][y] = 2;//将这个地方变为果实
gotoxy(x * 2, y);
BackGround(0, 2);
printf(" ");
}
if(maps[xy[0]][xy[1]] == 1 || maps[xy[0]][xy[1]] == 3)
{
looks[3] = 1;
gotoxy(0, 24);
BackGround(7, 0);
printf("你输了,最后得分:%d", looks[2]);
return;
}
maps[xy[0]][xy[1]] = 3;
for(i = 0;i <= 16; i++)
{
for ( j = 0; j <= 16; j++)
{
if (move[i][j] == move[xy[0]][xy[1]] - looks[1])
{
maps[i][j] = 0;
gotoxy(i * 2, j);
BackGround(0, 0);
printf(" ");
gotoxy(47,0);
break;
}
}
}
}
int main()
{
int maps[20][20];
int looks[4];
int move[20][20];
int xy[2];
int i;
int j;
xy[0] = xy[1] = 8;
srand((unsigned) time(NULL));
system("pause");
map(maps, looks, move);
while(looks[3] == 0)
{
Sleep(300);
rule(maps, looks, xy, move);
}
system("pause");
gotoxy(0,25);
printf("游戏结束,按任意键退出!");
return 0;
}
其中使用光标定位和背景颜色函数,这2个函数也是参考别人的,这里就不做讲解。