效果图
- 此代码使用了背景音乐,需提前调试编译器
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#include<conio.h>
#include<Mmsystem.h>
#pragma comment(lib, "winmm.lib")
#define SIDE 24//正方形区域边长
#define LEN 50//通关游戏长度
#define MY_CENTER_BORDER_COLOR 0xf0
#define MY_CENTER_CENTTER_COLOR 0x80
#define MY_SCORE_CENTER 0xa1
#define MY_SCORE_COLOR 0xf9
#define MY_INFORMATION_COLOR 0x8f
#include <windows.h>
#define MY_GAME_BACK_COLOR 0x30
HANDLE handle;
int SPEED = 400;//移动一格的时间 ,毫秒
clock_t time1, time2;
int SCORE = 0;
// #define MY_GAME_BACK_COLOR 0xdf
void printStart(int x, int y);
char printEnd(int x, int y);
void dispDrawscore();
void cube(int x, int y);
void gotoxy(int x, int y);
void cubefood(int x, int y);
void clear(int x, int y);
void boards(int x);
void dispDrawScore(int score);
void headmove(int *x, int *y, char s);
void linemove(int *x, int *y, int z);
void food(int *x, int *y, time_t t);
void startGame();
void initHandle();
void setTitle(char title[40]);
void setPosition(int x, int y);
void setColor(int color);
void setCursorVisible(int flag);
void setWindowSize(int w, int h);
void dispDrawGameBackground();
void dispDrawInformation();
void sPeed();
void dispDrawRect(int x, int y, int width, int height, int borderColor, int centerColor);
void hang(int x, int y, int width);
void lie(int x, int y, int height);
void dispDrawintroduce(int x);
int main() {
initHandle();
setWindowSize(100, 30);
setCursorVisible(0);
setTitle("贪吃蛇 v2.0 pro plus");
srand((unsigned) time(NULL));
time1 = clock();
int x = 5,y = 5;
printStart(x, y);
again:PlaySound(TEXT(".\\海绵宝宝.wav"), NULL, SND_FILENAME | SND_ASYNC);
dispDrawGameBackground();
dispDrawRect(12, 2, 26, 26, MY_CENTER_BORDER_COLOR, MY_CENTER_CENTTER_COLOR);
dispDrawRect(39, 2, 10, 26, MY_CENTER_BORDER_COLOR, MY_CENTER_CENTTER_COLOR);
dispDrawRect(1, 2, 10, 14, MY_CENTER_BORDER_COLOR, MY_CENTER_CENTTER_COLOR);
dispDrawRect(1, 17, 10, 11, MY_CENTER_BORDER_COLOR, MY_CENTER_CENTTER_COLOR);
dispDrawInformation();
dispDrawintroduce(1);
dispDrawScore(SCORE);
sPeed();
startGame();
char s = printEnd(x, y);
if (s == '1') {
system("cls");
goto again;
}
return 0;
}
void printStart(int x, int y) {
while (1) {
//1、设置时间间隔
time2 = clock();
if (time2 - time1 > 400) {
//2、输出游戏logo
{
int color = rand() % 0x10;
if (color == 0x00) {
color = 0x01;
} else if (color == 0x07) {
color = 0x0d;
} else if (color == 0x08) {
color = 0x09;//颜色转换
}
//绘制图案
setColor(color);
setPosition(x, y);//设置光标位置
float n, m, a;
for (m = 1.5f; m > -1.5f; m -= 0.1f) {
for (n = -1.5f; n < 1.5f; n += 0.05f) {
a = n * n + m * m - 1;
putchar(a * a * a - n * n * m * m * m <= 0.0f ? '*' : ' ');
}
putchar('\n');//打印心形
}
setPosition(x + 8, y + 10);
printf("我爱贪吃蛇!");
setPosition(x + 8, y + 11);
printf("我爱贪吃蛇!");
setPosition(x + 8, y + 12);
printf("我爱贪吃蛇!");
setPosition(x + 5, y + 17);
printf("请摁下回车键开始游戏!");
}
time1 = time2;
}
if (kbhit()) {
system("cls");
//if(kbhit())
break;//进入游戏
}
}
}
//system("pause");
//system("cls");
//char s;
//if((s=getchar())=="1")
char printEnd(int x, int y) {
char s = 0;
while (1) {
//1、设置时间间隔
time2 = clock();
if (time2 - time1 > 400) {
//2、输出游戏logo
int color = rand() % 0x10;
if (color == 0x00) {
color = 0x01;
} else if (color == 0x07) {
color = 0x0d;
} else if (color == 0x08) {
color = 0x09;//颜色转换
}
//绘制图案
setColor(color);
setPosition(x + 2, y);//设置光标
printf("■■■■■■ ■■■ ■■ ■■ ■■■■■■■");
setPosition(x + 1, y + 1);
printf("■■ ■■ ■■ ■■■ ■■■ ■■");
setPosition(x, y + 2);
printf("■■ ■■ ■■ ■■■■ ■■■■ ■■");
setPosition(x, y + 3);
printf("■■ ■■ ■■ ■■■■■■■■■■ ■■");
setPosition(x, y + 4);
printf("■■ ■■■ ■■ ■■ ■■ ■■■■ ■■ ■■■■■■■");
setPosition(x, y + 5);
printf("■■ ■■ ■■■■■■■■ ■■ ■■ ■■ ■■");
setPosition(x + 1, y + 6);
printf("■■ ■■ ■■ ■■ ■■ ■■ ■■");
setPosition(x + 2, y + 7);
printf("■■■■■■ ■■ ■■ ■■ ■■ ■■■■■■■");
setPosition(x + 1, y + 10);
printf("■■■■■■ ■■ ■■ ■■■■■■■ ■■■■■■");
setPosition(x, y + 11);
printf("■■ ■■ ■■ ■■ ■■ ■■ ■■");
setPosition(x, y + 12);
printf("■■ ■■ ■■ ■■ ■■ ■■ ■■");
setPosition(x, y + 13);
printf("■■ ■■ ■■ ■■ ■■ ■■ ■■■");
setPosition(x, y + 14);
printf("■■ ■■ ■■■ ■■■ ■■■■■■■ ■■■■■■");
setPosition(x, y + 15);
printf("■■ ■■ ■■ ■■ ■■ ■■ ■■");
setPosition(x, y + 16);
printf("■■ ■■ ■■■■ ■■ ■■ ■■");
setPosition(x + 1, y + 17);
printf("■■■■■■ ■■ ■■■■■■■ ■■ ■■");
setPosition(x + 6, y + 18);
printf("不服气?按1再来一次!");
time1 = time2;
}
fflush(stdin);
//s = 0;
if (kbhit())//kbhit()非阻塞函数
{
s = getch();
if (s == '1')//getch()阻塞函数//夏昕睿这个王八蛋,空格写的双引号" "??!!让我改了1个小时才发现!!!!
{
system("cls");
//if(kbhit())
break;//进入游戏
} else
exit(0);
// fflush(stdin);
}
}
//s=getch();
return s;
}
void dispDrawscore() {
setColor(0X8f);
setPosition(5, 9);
printf("%d", SCORE);
}
// int flag = 0;
void gotoxy(int x, int y) {
COORD coord = {2 * x + 26, y + 3}; //坐标句柄 //GetStdHandle(STD_OUTPUT_HANDLE)实例化句柄
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}//这个句柄可以把数转换为坐标
void setcolor(int fore, int ground) {
// HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(handle, fore % 16 | ground % 16 * 16);
//只有这样做才能分开控制前景色和背景色,但这样做之后不完全遵守十进制颜色对照表了,背景色遵循前景色对照方式
} //设置颜色
void cube(int x, int y) {
gotoxy(x, y);
printf("■");
}//打出除了食物外其他的
void cubefood(int x, int y) {
gotoxy(x, y);
printf("●");
}//打印食物
void clear(int x, int y) {
gotoxy(x, y);
printf(" ");
}//清除
void boards(int x) {
int i;
cube(-1, -1);
for (i = 0; i <= x; i++) {
cube(-1, i);
cube(i, -1);
cube(x, i);
cube(i, x);
}
}//打印边框
void dispDrawScore(int score) {
//1.绘制矩形
//dispDrawRect(1,2,10,14,MY_CENTER_BORDER_COLOR,MY_SCORE_CENTER_COLOR);
//2.写 "分数"
setColor(MY_SCORE_COLOR);
setPosition(5, 2);
printf("分数");
}
void headmove(int *x, int *y, char s) {
if (s == 'w')y[0]--;
if (s == 's')y[0]++;
if (s == 'a')x[0]--;
if (s == 'd')x[0]++;
}//蛇头的转向和前进
void linemove(int *x, int *y, int z)//z=len蛇长
{
int i;
for (i = z - 1; i > 0; i--)
x[i] = x[i - 1], y[i] = y[i - 1];//不断把前面的地址向后传递(实际上xy数组并非指针,而是蛇身节点的位置),即向前运动后上一状态情况的蛇的第1234个节点所在的坐标位置变为了当前状态第2345个节点(第五个被clear()清除,第一个节点通过headmove()前进,cube()打印)从而实现了蛇的移动
}//蛇的移动
void food(int *x, int *y, time_t t) {
// setcolor(6,8);
srand(t); // rand()和srand()要一起使用,其中srand()用来初始化随机数种子,rand()用来产生随机数。
time_t t1 = clock();
srand(t1);
int Rand = rand() % 16;
if (Rand != 8 && Rand != 10)
setcolor(Rand, 8);
*x = rand() % SIDE, *y = rand() % SIDE;//%SIDE保证了食物一定生成在方框区域内
cubefood(*x, *y);
setcolor(10, 8);
}//食物的颜色设置及打印
void startGame() {
// initHandle();
// setCursorVisible(0);
setcolor(9, 1);
boards(SIDE);
setcolor(10, 8);
int x[100] = {}, y[100] = {};
*x = 11, *y = 11;
int a = *x, b = *y, e = 1, p = 1, i, len = 4, r = 0, pp = 3;//len蛇长//e=1有食物反之则无//a,b是食物地址//r是输赢的判断
SCORE = 0;
for (int i = 0; i < len; i++) {
cube(*x + i, *y); //初始蛇头
}
while (a == *x && b == *y) //可以保证第一个食物不与蛇头重合
{ //?????????????????
food(&a, &b, clock());
} //生成第一个食物
gotoxy(SIDE, SIDE); //光标回到方框角落
char dua0 = getch(), dua = 0;
while (!r) {
dispDrawscore();
Sleep(SPEED); //速度
if (!e) {
p = 1;
while (p) {
food(&a, &b, clock()); //生成一个食物
for (i = 0; i < len; i++) //判断食物是否在蛇身体上
if (a == x[i] && b == y[i])
p = 2; //p = 2让其打印一个新的food
p--;
}
} //生成食物
if (kbhit()) {
dua0 = getch(); //??????????//检查当前是否有键盘输入,若有则返回一个非0值,否则返回0。
if (dua0 != 'a' && dua0 != 'w' && dua0 != 's' && dua0 != 'd') //此循环实现了空格键暂停
{
while (1) {
dua0 = getch();
if (dua0 == 'a' || dua0 == 'w' || dua0 == 's' || dua0 == 'd')
break;
}
}
// Sleep(20000);
}
if (dua + dua0 != 'a' + 'd' && dua + dua0 != 'w' + 's')//如果扭头方向和当前方向相反,方向不变
dua = dua0; //方向不相反,蛇扭头
if (e) {//有食物就删蛇尾,没食物(因为迟到了食物)就不删,从而实现了吃食物加蛇长len
setcolor(10, 8);
clear(x[len - 1], y[len - 1]); //删除蛇尾
linemove(x, y, len);
} else //else不加也可以,反正意思就是每次循环都要把e置1,因为食物一直存在(除了被刚吃掉的半个循环内e=0,这会让food()函数重新打印一个新的食物)
e = 1; //保证了食物在下一次被吃掉之前只打印一给个
headmove(x, y, dua); //扭头&&蛇头的不断前进
if (x[0] == -1 || y[0] == -1 || x[0] == SIDE || y[0] == SIDE) {
r = 1;
// break;//加上后撞墙头消失
} //判断蛇是否碰壁
for (i = 1; i < len; i++) {
if (x[0] == x[i] && y[0] == y[i])
r = 1;
} //判断蛇是否撞上自己
time_t t1 = clock();
srand(t1);
int Rand = rand() % 16; //使蛇身变幻颜色
if (Rand != 8) //使蛇身不与背景颜色重合
setcolor(Rand, 8);
// printf("%d",Rand);
cube(x[0], y[0]); //打印蛇头
// gotoxy(SIDE,SIDE);//光标
if (x[0] == a && y[0] == b) {
len++; //吃上食物蛇长+1
e = 0;
linemove(x, y, len);
SPEED -= 10;
SCORE += 10;
}
if (len == LEN)
r = 2;
if (pp > 0) {
clear(11 + pp, 11);
pp--;
}
}
setcolor(3, 8);//设置游戏结束的文本颜色
SPEED = 400;
// gotoxy(20,5);
if (r == 1)printf("\n GAME OVER!!!\n");
if (r == 2)printf("\n YOU WIN!!!\n ");
setcolor(0, 0);
system("cls");
// system("pause");
// fflush(stdin); //清空输入流
// printf(" 不服输?\n按“1”再来一局!!!");
}
//1.初始化句柄
void initHandle() {
handle = GetStdHandle(STD_OUTPUT_HANDLE);
}
//2.设置标题
void setTitle(char title[40]) {
SetConsoleTitleA(title);
}
//3.设置位置
void setPosition(int x, int y) {
COORD coord = {x * 2, y};
SetConsoleCursorPosition(handle, coord);
}
//4.设置颜色
void setColor(int color) {
SetConsoleTextAttribute(handle, color);
}
//5.设置光标是否可见
void setCursorVisible(int flag) {
CONSOLE_CURSOR_INFO info;
info.bVisible = flag;
info.dwSize = 100;
SetConsoleCursorInfo(handle, &info);
}
//6.设置窗口大小
void setWindowSize(int w, int h) {
COORD coord = {w, h};
SetConsoleScreenBufferSize(handle, coord);
SMALL_RECT rect = {0, 0, w - 1, h - 1};
SetConsoleWindowInfo(handle, 1, &rect);
}
//绘制整个窗体背景色 30行 100列
void dispDrawGameBackground() {
//设置背景色
setColor(MY_GAME_BACK_COLOR);
for (int i = 0; i < 30; i++) {
//输出前调整光标位置
setPosition(0, i);
printf("%100s", "");
}
}
//绘制信息提示区域
void dispDrawInformation() {
//dispDrawRect(39,2,10,26,MY_CENTER_BORDER_COLOR,0xf9);
setColor(MY_SCORE_COLOR);
setPosition(43, 2);
printf("说明");
setColor(MY_INFORMATION_COLOR);
setPosition(42, 4);
printf("游戏说明");
setColor(MY_INFORMATION_COLOR);
setPosition(42, 6);
printf("【游戏】");
setColor(MY_INFORMATION_COLOR);
setPosition(41, 7);
printf("W w:向上移动");
setColor(MY_INFORMATION_COLOR);
setPosition(41, 8);
printf("S s:向下移动");
setColor(MY_INFORMATION_COLOR);
setPosition(41, 9);
printf("A a:向左移动");
setColor(MY_INFORMATION_COLOR);
setPosition(41, 10);
printf("D d:向右移动");
setColor(MY_INFORMATION_COLOR);
setPosition(41, 11);
printf("Q q:退出游戏");
setColor(MY_INFORMATION_COLOR);
setPosition(42, 13);
printf("【控制】");
setColor(MY_INFORMATION_COLOR);
setPosition(41, 14);
printf("空格:开始游戏");
setColor(MY_INFORMATION_COLOR);
setPosition(41, 15);
printf("↑:增加难度");
setColor(MY_INFORMATION_COLOR);
setPosition(41, 17);
printf("↓:降低难度");
setColor(MY_INFORMATION_COLOR);
setPosition(41, 18);
printf("空格键:暂停");
}
void sPeed() {
int DEGREE;
while (1) {
int s = getch();
if (s == 72)
SPEED -= 50;
else if (s == 80)
SPEED += 50;
else if (s == ' ') //getch无法通过判断'\n'的方式结束输入,
return;
switch (SPEED) {
case 400:
DEGREE = 1;
break;
case 350:
DEGREE = 2;
break;
case 300:
DEGREE = 3;
break;
case 250:
DEGREE = 4;
break;
case 200:
DEGREE = 5;
break;
case 150:
DEGREE = 6;
break;
case 100:
DEGREE = 7;
break;
case 50:
DEGREE = 8;
break;
case 0:
DEGREE = 9;
break;
}
dispDrawintroduce(DEGREE);
}
}
void dispDrawRect(int x, int y, int width, int height, int borderColor, int centerColor) {
setColor(borderColor);
setPosition(x, y);
for (int i = 0; i < width; i++) {
printf("%2s", "");
}
setPosition(x, y + height - 1);
for (int i = 0; i < width; i++) {
printf("%2s", "");
}
for (int i = 0; i < height; i++) {
setPosition(x, y + i);
printf("%2s", "");
}
for (int i = 0; i < height; i++) {
setPosition(x + width - 1, y + i);
printf("%2s", "");
}
setColor(centerColor);
for (int i = 0; i < height - 2; i++) {
setPosition(x + 1, y + 1 + i);
for (int j = 0; j < width - 2; j++) {
printf("%2s", "");
}
}
}
void hang(int x, int y, int width) {
setPosition(x, y);
for (int i = 0; i < width; i++) {
printf("%2s", "");
}
}
void lie(int x, int y, int height) {
for (int i = 0; i < height; i++) {
setPosition(x, y + i);
printf("%2s", "");
}
}
void dispDrawintroduce(int x) {
setColor(MY_CENTER_CENTTER_COLOR);
for (int i = 0; i < 9; i++) {
setPosition(2, 18 + i);
for (int j = 0; j < 8; j++) {
printf("%2s", "");
}
}
setColor(MY_SCORE_COLOR);
setPosition(5, 17);
printf("等级");
setColor(MY_CENTER_BORDER_COLOR);
if (x == 0) {
hang(4, 19, 4);
hang(4, 25, 4);
lie(4, 19, 7);
lie(7, 19, 7);
} else if (x == 1) {
lie(6, 19, 7);
} else if (x == 2) {
hang(4, 19, 4);
hang(4, 22, 4);
hang(4, 25, 4);
lie(4, 22, 3);
lie(7, 19, 3);
} else if (x == 3) {
hang(4, 19, 4);
hang(4, 22, 4);
hang(4, 25, 4);
lie(7, 19, 7);
} else if (x == 4) {
hang(4, 22, 5);
lie(4, 19, 3);
lie(7, 19, 7);
} else if (x == 5) {
hang(4, 19, 4);
hang(4, 22, 4);
hang(4, 25, 4);
lie(4, 19, 3);
lie(7, 22, 3);
} else if (x == 6) {
hang(4, 19, 4);
hang(4, 22, 4);
hang(4, 25, 4);
lie(4, 19, 7);
lie(7, 22, 3);
} else if (x == 7) {
hang(4, 19, 4);
lie(7, 19, 7);
} else if (x == 8) {
hang(4, 19, 4);
hang(4, 22, 4);
hang(4, 25, 4);
lie(4, 19, 7);
lie(7, 19, 7);
} else if (x == 9) {
hang(4, 19, 4);
hang(4, 22, 4);
hang(4, 25, 4);
lie(4, 19, 3);
lie(7, 19, 7);
}
}