C语言300行代码实现贪吃蛇
程序员文章站
2024-03-18 19:54:28
...
完整代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
#include <time.h>
#define ARRAY_SIZE 20 // 区域大小
int AreaArray[ARRAY_SIZE][ARRAY_SIZE]; // 数组
#define WALL 0 // 墙壁
#define VALID 1 // 可走区域
#define SELF 2 // 蛇身
#define NEWP 3 // 果实
#define HEAD 4 // 蛇头
const char *Shape[] = {
"■", // 墙壁图案
" ", // 可走区域图案ww
"◎", // 蛇身图案
"⊙" , // 果实图案
"●" // 蛇头图案
};
// 记录分数
int score = 0;
int high_score = 0;
// 蛇的所有坐标
int xy[(ARRAY_SIZE - 2)*(ARRAY_SIZE - 2) + 1][2] = {0};
// 方向状态
enum {
LEFT,
TOP,
RIGHT,
BOTTOM
} Direction;
// 保存最高记录
void GameSaveHighScore()
{
FILE *fp = fopen("high_score.txt", "w");
if (fp == NULL)
{
printf("open file error.\n");
return;
}
fprintf(fp, "%d", high_score);
fclose(fp);
}
// 载入最高记录
void GameLoadHighScore()
{
FILE *fp = fopen("high_score.txt", "r");
if (fp == NULL)
{
printf("open file error.\n");
return;
}
fscanf(fp, "%d", &high_score);
fclose(fp);
}
// 生成特定区域内随机数
int GetRand(int start, int end)
{
static unsigned long count;
srand((unsigned int)time(0)+ count--);
return rand() % (end - start + 1) + start;
}
// 刷新果实坐标
void GameUpdateNewp()
{
static int x, y;
int i, j, z;
// 计算蛇长度
for (i = 0; xy[i][0] || xy[i][1]; i++);
// 添加上新吃的果实
i++;
// 生成随机数
i = GetRand(0, (ARRAY_SIZE - 2)*(ARRAY_SIZE - 2) - i - 1);
// 计算新果实坐标
for (j = 1;i && j < ARRAY_SIZE - 1; j++)
{
for (z = 1;i && z < ARRAY_SIZE - 1; z++)
{
if (AreaArray[j][z] == VALID)
i--;
if (!i) break;
}
if (!i) break;
}
// 加入新果实
AreaArray[j][z] = NEWP;
// 去掉之前的果实
if (x || y)
AreaArray[y][x] = VALID;
//
x = z;
y = j;
}
// 根据用户操作更新游戏, 返回新状态
int GameUpdate()
{
int x = 0, y = 0, i;
// 根据方向检测碰撞
switch (Direction)
{
case LEFT:
x--;
break;
case TOP:
y--;
break;
case RIGHT:
x++;
break;
case BOTTOM:
y++;
break;
}
// 计算蛇长度
for (i = 0; xy[i][0] || xy[i][1]; i++);
// 判断下一个位置是否与蛇头碰撞
switch (AreaArray[xy[0][1] + y][xy[0][0] + x])
{
case SELF:
case WALL:
return 0; // 撞自己或者撞墙了
case NEWP:
score++;
i++; // 吃到果实, 长度加1
xy[i][0] = 0; // 加结束标志
xy[i][1] = 0; // 加结束标志
GameUpdateNewp();// 刷新果实坐标
case VALID:
i--;
// 移动蛇
while (i>0)
{
xy[i][0] = xy[i-1][0];
xy[i][1] = xy[i-1][1];
i--;
}
// 蛇头坐标
xy[0][0] += x;
xy[0][1] += y;
break;
}
return 1;
}
// 刷新显示
void GameFresh()
{
int i, j;
// 去掉显示数组上蛇身旧状态的痕迹
for (i = 1; i < ARRAY_SIZE - 1; i++)
for (j = 1; j < ARRAY_SIZE - 1; j++)
if(AreaArray[i][j]== SELF || AreaArray[i][j] == HEAD)
AreaArray[i][j] = VALID;
// 把蛇的坐标更新到显示数组
// 蛇头
AreaArray[xy[0][1]][xy[0][0]] = HEAD;
// 蛇身
for (i = 1; xy[i][0] || xy[i][1]; i++)
AreaArray[xy[i][1]][xy[i][0]] = SELF;
// 清屏
system("cls");
// 显示
for (i = 0; i < ARRAY_SIZE; i++)
{
for (j = 0; j < ARRAY_SIZE; j++)
printf("%s", Shape[AreaArray[i][j]]);
printf("\n");
}
printf("current score: %d\n", score);
printf("high score: %d\n", high_score);
}
// 游戏初始化
void GameInit()
{
int i, j;
// 初始化显示数组整个区域
for (i = 0; i < ARRAY_SIZE; i++)
for (j = 0; j < ARRAY_SIZE; j++)
if (i && j && (i != ARRAY_SIZE - 1) && (j != ARRAY_SIZE - 1))
AreaArray[i][j] = VALID; // 可行走区域
else
AreaArray[i][j] = WALL; // 墙壁
// 随机生成蛇头坐标
xy[0][0] = GetRand(2, ARRAY_SIZE - 3);
xy[0][1] = GetRand(2, ARRAY_SIZE - 3);
// 根据蛇头坐标生成蛇身坐标
if (GetRand(0, 1))
{
if (xy[0][0] > ARRAY_SIZE / 2)
{
i = xy[0][0] + 1;
Direction = LEFT;
}
else
{
i = xy[0][0] - 1;
Direction = RIGHT;
}
j = xy[0][1];
}
else
{
i = xy[0][0];
if (xy[0][1] > ARRAY_SIZE / 2)
{
j = xy[0][1] + 1;
Direction = TOP;
}
else
{
j = xy[0][1] - 1;
Direction = BOTTOM;
}
}
xy[1][0] = i;
xy[1][1] = j;
// 蛇身结束标志
xy[2][0] = 0;
xy[2][1] = 0;
// 更新
GameUpdate();
GameUpdateNewp();
GameFresh();
}
void GameStart()
{
int state = 1;
int time = 100;
system("cls");
printf("================= Game rule ==============\n");
printf("\tContinue key : \tany\n");
printf("\tQuit key : \tQ\n");
printf("\tUp key : \tW\n");
printf("\tDown key : \tS\n");
printf("\tLeft key : \tA\n");
printf("\tRight key : \tD\n");
printf("==========================================\n");
score = 0;
GameLoadHighScore();
getch();
GameInit();
while (state)
{
// 检测有输入
if(kbhit())
switch (getch())
{
case 'q':
case 'Q':
state = 0; // 结束游戏
break;
case 'w':
case 'W':
if(Direction != BOTTOM)
Direction = TOP;
break;
case 's':
case 'S':
if (Direction != TOP)
Direction = BOTTOM;
break;
case 'a':
case 'A':
if (Direction != RIGHT)
Direction = LEFT;
break;
case 'd':
case 'D':
if (Direction != LEFT)
Direction = RIGHT;
break;
default:;
}
state = GameUpdate(); // 更新
GameFresh(); // 刷新显示
Sleep(time);
}
printf("######### Game over #########\n");
// 最高记录
if (score > high_score) high_score = score;
GameSaveHighScore();
getch();
}
int main()
{
while(1) GameStart();
return 0;
}
运行截图: