效果展示
蛇的颜色是用的随机色,但因本人不太会用这个博哥功能无法上传视频,所以呈现的是截屏截到的颜色,贪吃蛇切换界面时的鼠标点击也没呈现
遇到的问题
1.最开始写的时候,蛇的移动都出现了问题,我是直接让蛇的每节身体都往当前状态移动,运行时发现我的蛇基本是平行移动,猛地醒悟,蛇的移动是蛇头向状态方向移动,其余的向前补位就可以了。
2.鼠标点击切换界面时灵时不灵,最开始是直接用的一个监听鼠标是否点击的循环来操作,也就是
while(!MouseHit())
后来在真正的操作时,发现大多数情况下鼠标还没点,游戏就跑了起来,改了很多遍,最后直接用了一个死循环
while(1){
if (MouseHit()) {
m = GetMouseMsg();
switch (m.uMsg) {
case WM_LBUTTONDOWN:
if (m.x >= 250 && m.x <= 350 && m.y >= 150 && m.y <= 200) {
flag = 1;
closegraph();
Difficulty();
}
else if (m.x >= 250 && m.x <= 350 && m.y >= 290 && m.y <= 320) {
flag = 1;
closegraph();
Rank();
}
break;
}
}
if (flag)
break;
}
3.撞石头的判断
int Gameover() {
//撞墙
if (snake.coor[0].x <= 0 || snake.coor[0].x >= 640 || snake.coor[0].y <= 0 || snake.coor[0].y >= 480) {
return 1;
}
//撞到自己
for (int i = snake.n - 1; i > 0; i--) {
if ((snake.coor[0].x == snake.coor[i].x) && (snake.coor[0].y == snake.coor[i].y)) {
return 1;
}
}
//撞到石头
for (int i = 0; i < stone.n; i++) {
if (snake.coor[0].x == stone.coor[i].x && snake.coor[0].y == stone.coor[i].y) {
return 1;
}
}
}
乍一看好像没啥问题,但当我运行的时候,当第一块石头生成,游戏就莫名的结束了,改了一上午,硬是没找出来,最后还是组内的学长帮我改了出来,最后少了个return 0;
注意:不同编译器默认的返回值不同,有的是返回return 1;
就像我的那个编译器。
4.outtextxy()函数的使用
void far outtextxy(int x, int y, char *textstring);
它所打印在窗口的东西只能是字符串,如果想把得分等打印上去需要用到sprintf()函数
int sprintf(char *string, char *format [,argument,...]);
再用outtextxy打印字符串时需要在字符串前加L或者_T
outtextxy(250, 326, L"hello");
我是在属性中把字符集的格式改了
代码
1.主页面
#include<iostream>
#include<conio.h>
#include<graphics.h>
#pragma warning(disable:4996)
using namespace std;
void Thestart(); //开始界面
void Difficulty(); //选择难度
int Diff();//将选择的难度返回至主页面
void Gamestart(); //初始化
void Printsnake(); //打印蛇
void Snakemove(); //蛇的移动
void Userscanf(); //敲键盘
void Creatfood(); //食物生成
int foodis();//判断食物是否被吃
void Eatfood();//吃
void Stone();//生成石头
int Gameover(); //蛇撞墙
void Theend();//结束界面
void Rank();//排行榜
int main()
{
Thestart();
Gamestart();
while(1){
while (!kbhit()) {
if(foodis()==0)
Creatfood();
Snakemove();
Sleep(Diff());
Printsnake();
Stone();
Eatfood();
if (Gameover() == 1) {
break;
}
}
if (Gameover()==1) {
break;
}
Userscanf();
}
Theend();
closegraph();
return 0;
}
2.函数
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>
#include<graphics.h>
#include<windows.h>
#pragma warning(disable:4996)
#define N 100
#define SIZE 10
//控制方向
enum CH { up = 80, down = 72, left = 75, right = 77 };
//坐标
struct COOR {
int x;
int y;
};
//蛇
struct Snake {
int n; //蛇当前长度
CH ch; //方向
struct COOR coor[N]; //每个点的坐标
}snake;
//食物
struct food {
struct COOR coor; //食物坐标
int flag = 0; //标记是否被吃
int steps = 0; //食物产生后蛇移动步数
}food;
struct stone {
int steps = 0; //步数
int n=0;//石头数量
struct COOR coor[N];
}stone;
//食物生成
void Creatfood() {
int flag = 0; //判断食物是否出现在蛇的身上
food.coor.x = ((rand() % 62)+1)* 10; //与蛇在同一线上
food.coor.y = ((rand() % 46)+1) * 10;
while (1) {
flag = 0;
for (int i = 0; i < snake.n; i++) {
if (food.coor.x == snake.coor[i].x && food.coor.y == snake.coor[i].y) {
flag = 1;
break;
}
}
if (flag)
continue;
else {
food.flag = 1;//食物成功生成
break;
}
}
}
//生成石头
void Stone() {
if (stone.steps == 200) {
stone.steps = 0;
int flag = 0;
stone.coor[stone.n].x = rand() % 64 * 10;
stone.coor[stone.n].y = rand() % 48 * 10;
while (1) {
flag = 0;
for (int i = 0; i < snake.n; i++) {
if (stone.coor[stone.n].x == snake.coor[i].x && stone.coor[stone.n].y == snake.coor[i].y) {
flag = 1;
break;
}
}
if (flag)
continue;
else {
stone.n++;
break;
}
}
}
}
//初始化
void Gamestart() {
initgraph(640, 480);//初始化窗口
//setbkcolor(WHITE);
srand((int)time(NULL)); //获取随机数种子
//初始化蛇
snake.n = 3;
snake.ch = right;
snake.coor[0].x = 100;
snake.coor[0].y = 100;
snake.coor[1].x = 90;
snake.coor[1].y = 100;
snake.coor[2].x = 80;
snake.coor[2].y = 100;
}
//打印蛇
void Printsnake() {
system("cls");//清除控制台
cleardevice();//刷新图形界面
setfillcolor(RGB(rand()%225,rand()%225,rand()%225));//设置填充色
//setfillcolor(BLACK);
for (int i = 0; i < snake.n; i++) {
//打印每节蛇
fillrectangle(snake.coor[i].x, snake.coor[i].y, snake.coor[i].x+SIZE,snake.coor[i].y+SIZE);//创造蛇身
}
//打印食物
fillrectangle(food.coor.x, food.coor.y, food.coor.x + SIZE, food.coor.y + SIZE);
//打印石头
setfillcolor(RED);
for (int i = 0; i < stone.n; i++)
fillrectangle(stone.coor[i].x, stone.coor[i].y, stone.coor[i].x+SIZE, stone.coor[i].y+SIZE);
char score[100] = "";
//settextcolor(BLACK);
sprintf(score, "分数=%d", (snake.n - 3) * 10);
//打印分数
outtextxy(580, 10, score);
setbkmode(TRANSPARENT);
}
//蛇的移动
void Snakemove() {
stone.steps++;
for (int i = snake.n - 1; i > 0; i--) {
snake.coor[i].x = snake.coor[i - 1].x;
snake.coor[i].y = snake.coor[i - 1].y;
}
switch (snake.ch) {
case up:snake.coor[0].y += SIZE;break; //上
case down:snake.coor[0].y -= SIZE;break; //下
case left:snake.coor[0].x -= SIZE;break; //左
case right:snake.coor[0].x += SIZE;break; //右
}
}
//改变方向
void Userscanf() {
char key;
key = getch(); //从键盘中敲值
switch (key) {
case up:
if (snake.ch != down)
snake.ch = up;
break;
case down:
if (snake.ch != up)
snake.ch = down;
break;
case left:
if (snake.ch != right)
snake.ch = left;
break;
case right:
if (snake.ch != left)
snake.ch = right;
break;
}
}
//吃食物
void Eatfood() {
if (snake.coor[0].x == food.coor.x && snake.coor[0].y == food.coor.y) {
snake.n++;
food.flag = 0;
}
}
//判断食物
int foodis() {
if (food.flag == 1)
return 1;
else if (food.flag == 0)
return 0;
}
//判断撞墙
int Gameover() {
//撞墙
if (snake.coor[0].x <= 0 || snake.coor[0].x >= 640 || snake.coor[0].y <= 0 || snake.coor[0].y >= 480) {
return 1;
}
//撞到自己
for (int i = snake.n - 1; i > 0; i--) {
if ((snake.coor[0].x == snake.coor[i].x) && (snake.coor[0].y == snake.coor[i].y)) {
return 1;
}
}
//撞到石头
for (int i = 0; i < stone.n; i++) {
if (snake.coor[0].x == stone.coor[i].x && snake.coor[0].y == stone.coor[i].y) {
return 1;
}
}
return 0;
}
3.界面
#include<stdio.h>
#include<graphics.h>
#include<Windows.h>
#include<string.h>
#include<conio.h>
#pragma warning(disable:4996)
#define SIZE 10
int degree=0;
//结束界面
void Theend() {
initgraph(640, 480,SHOWCONSOLE);
outtextxy(280, 80, "游戏结束");
outtextxy(120, 200, "看着榜单那些成绩,你一定会有许多感慨,请留你的吐槽");
outtextxy(270, 300, ".键退出");
system("mode con cols=60 lines=25");
int ch = 0;
FILE* fp;
fp = fopen("snakerank.txt", "a+");
ch = getc(fp);
while (ch != EOF) {
putchar(ch);
ch = getc(fp);
}
fprintf(stderr, "\n");
fprintf(fp,"\n");
char c=0;
while (c != '.') {
c = getch();
fprintf(fp,"%c",c);
putchar(c);
}
closegraph();
}
//难度设置
void Difficulty() {
degree = 0;
initgraph(640, 480);
outtextxy(250, 60, "请选择你的难度");
outtextxy(270, 150, "困难模式");
outtextxy(270, 240, "普通模式");
outtextxy(270, 330, "简单模式");
MOUSEMSG m;
int flag = 0;
while (1) {
if (MouseHit()) {
m = GetMouseMsg();
switch (m.uMsg) {
case WM_LBUTTONDOWN:
if (m.x >= 260 && m.x <= 350 && m.y >= 100 && m.y <= 140) {
degree = 1;
flag = 1;
}
else if (m.x >= 260 && m.x <= 350 && m.y >= 160 && m.y <= 200) {
degree = 10;
flag = 1;
}
else if (m.x >= 260 && m.x <= 350 && m.y >= 220 && m.y <= 260) {
degree = 20;
flag = 1;
}
break;
}
}
if (flag)
break;
}
closegraph();
}
//返回函数
int Diff() {
return degree;
}
//排行榜
void Rank() {
//initgraph(640, 480);
/*outtextxy(280, 60, "排行榜");
int ch=0;
int i = 0, j = 0;
FILE* fp;
fp = fopen("snakerank.txt", "r");
ch = getc(fp);
while (ch != EOF) {
outtextxy(250+i*SIZE, 90+j*SIZE*2, ch);
ch = getc(fp);
i++;
if (ch == '\n') {
i = -1;
j++;
}
}
outtextxy(270, 400, "选择难度");*/
system("mode con cols=60 lines=25");
int ch = 0;
FILE* fp;
fp = fopen("snakerank.txt", "r");
ch = getc(fp);
while (ch != EOF) {
putchar(ch);
ch = getc(fp);
}
if (fclose(fp) != 0) {
fprintf(stderr, "Error in closing files\n");
}
/*MOUSEMSG m;
int flag = 0;
while (1) {
if (MouseHit()) {
m = GetMouseMsg();
switch (m.uMsg) {
case WM_LBUTTONDOWN:
if (m.x >= 0 && m.x <= 60 && m.y >= 0 && m.y <= 25) {
flag = 1;
closegraph();
Difficulty();
}
break;
}
}
if (flag)
break;
}*/
getchar();
Difficulty();
}
//开始界面
void Thestart() {
MessageBox(NULL, "制作不易,不喜勿喷", "警告", MB_OK);
initgraph(640, 480);
outtextxy(240, 60, "欢迎来到贪吃蛇");
outtextxy(260, 180, "开始游戏");
outtextxy(270, 300, "排行榜");
MOUSEMSG m;
int flag = 0;
while(1){
if (MouseHit()) {
m = GetMouseMsg();
switch (m.uMsg) {
case WM_LBUTTONDOWN:
if (m.x >= 250 && m.x <= 350 && m.y >= 150 && m.y <= 200) {
flag = 1;
closegraph();
Difficulty();
}
else if (m.x >= 250 && m.x <= 350 && m.y >= 290 && m.y <= 320) {
flag = 1;
closegraph();
Rank();
}
break;
}
}
if (flag)
break;
}
closegraph();
}
涉及到的知识点
1.easyx的基本使用
2.随机数的生成
3.c以及c++的部分内容(文件)
双人副本
1.写这个扩充副本,主要是因为工作室其它大佬写的太好了,感觉我的有点简陋,就写了这样一个新的项目。
2.效果展示
3.代码
1.界面
#include<iostream>
#include<conio.h>
#include<graphics.h>
#pragma warning(disable:4996)
using namespace std;
void Thestart(); //开始界面
void Gamestart(); //初始化
void Printsnake(); //打印蛇
void Snakemove(); //蛇的移动
void Userscanf(); //敲键盘
void Creatfood(); //食物生成
int foodis();//判断食物是否被吃
void Eatfood();//吃
void Stone();//生成石头
int Gameover1(); //蛇撞墙
int Gameover2(); //蛇撞墙
int Gameover3();//游戏结束
void Die();//死亡判断
void Theend();//退出显示
int main()
{
Thestart();
Gamestart();
while (1) {
while (!kbhit()) {
if (foodis() == 0)
Creatfood();
Snakemove();
Sleep(20);
Printsnake();
Stone();
Eatfood();
Die();
if (Gameover3() == 1) {
break;
}
}
if (Gameover3() == 1) {
break;
}
Userscanf();
}
closegraph();
Theend();
return 0;
}
2.函数
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>
#include<graphics.h>
#include<windows.h>
#define N 100
#define SIZE 10
#pragma warning(disable:4996)
//控制方向
enum CH { up = 80, down = 72, left = 75, right = 77 };
enum BH { up2 = 83, down2 = 87, left2 = 65, right2 = 68 };
//坐标
struct COOR {
int x;
int y;
};
//蛇
struct Snake {
int flag = 0;//蛇是否存活
int n; //蛇当前长度
int num;
CH ch; //方向
struct COOR coor[N]; //每个点的坐标
}snake;
struct data {
int flag = 0;
int n;
int num;
BH ch;
struct COOR coor[N];
}snake2;
//食物
struct food {
struct COOR coor; //食物坐标
int flag = 0; //标记是否被吃
int steps = 0; //食物产生后蛇移动步数
}food;
struct stone {
int steps = 0; //步数
int n = 0;//石头数量
struct COOR coor[N];
}stone;
//食物生成
void Creatfood() {
int flag = 0; //判断食物是否出现在蛇的身上
food.coor.x = ((rand() % 62) + 1) * 10; //与蛇在同一线上
food.coor.y = ((rand() % 46) + 1) * 10;
while (1) {
flag = 0;
for (int i = 0; i < snake.n; i++) {
if (food.coor.x == snake.coor[i].x && food.coor.y == snake.coor[i].y) {
flag = 1;
break;
}
}
if (flag)
continue;
else {
food.flag = 1;//食物成功生成
break;
}
}
}
//生成石头
void Stone() {
if (stone.steps == 200) {
stone.steps = 0;
int flag = 0;
stone.coor[stone.n].x = rand() % 64 * 10;
stone.coor[stone.n].y = rand() % 48 * 10;
while (1) {
flag = 0;
for (int i = 0; i < snake.n; i++) {
if (stone.coor[stone.n].x == snake.coor[i].x && stone.coor[stone.n].y == snake.coor[i].y) {
flag = 1;
break;
}
}
if (flag)
continue;
else {
stone.n++;
break;
}
}
}
}
//初始化
void Gamestart() {
initgraph(640, 480);//初始化窗口
//setbkcolor(WHITE);
srand((int)time(NULL)); //获取随机数种子
//初始化蛇
snake.n = 3;
snake.num = 3;
snake.ch = right;
snake.coor[0].x = 100;
snake.coor[0].y = 100;
snake.coor[1].x = 90;
snake.coor[1].y = 100;
snake.coor[2].x = 80;
snake.coor[2].y = 100;
snake2.n = 3;
snake2.num = 3;
snake2.ch = left2;
snake2.coor[0].x = 280;
snake2.coor[0].y = 160;
snake2.coor[1].x = 290;
snake2.coor[1].y = 160;
snake2.coor[2].x = 300;
snake2.coor[2].y = 160;
}
//打印蛇
void Printsnake() {
system("cls");//清除控制台
cleardevice();//刷新图形界面
setfillcolor(RED);
if(!snake.flag)
for (int i = 0; i < snake.n; i++) {
//打印每节蛇
fillrectangle(snake.coor[i].x, snake.coor[i].y, snake.coor[i].x + SIZE, snake.coor[i].y + SIZE);//创造蛇身
}
setfillcolor(BLUE);
if(!snake2.flag)
for (int i = 0; i < snake2.n; i++) {
//打印每节蛇
fillrectangle(snake2.coor[i].x, snake2.coor[i].y, snake2.coor[i].x + SIZE, snake2.coor[i].y + SIZE);//创造蛇身
}
//打印食物
setfillcolor(RGB(rand() % 225, rand() % 225, rand() % 225));//设置填充色
fillrectangle(food.coor.x, food.coor.y, food.coor.x + SIZE, food.coor.y + SIZE);
//打印石头
setfillcolor(YELLOW);
for (int i = 0; i < stone.n; i++)
fillrectangle(stone.coor[i].x, stone.coor[i].y, stone.coor[i].x + SIZE, stone.coor[i].y + SIZE);
char score[100] = "";
char score2[100] = "";
char score3[100] = "";
char score4[100] = "";
//settextcolor(BLACK);
sprintf(score, "玩家二分数:%d", (snake.n - 3) * 10);
sprintf(score2, "玩家一分数:%d", (snake2.n - 3) * 10);
sprintf(score3, "最终得分:%d", (snake.num - 3) * 10);
sprintf(score4, "最终得分:%d", (snake2.num - 3) * 10);
//打印分数
if (!snake.flag) {
outtextxy(510, 10, score);
}
else if (snake.flag == 1)
outtextxy(510, 10, score3);
if (!snake2.flag)
outtextxy(10, 10, score2);
else if (snake2.flag == 1)
outtextxy(10, 10, score4);
setbkmode(TRANSPARENT);
}
//蛇的移动
void Snakemove() {
stone.steps++;
for (int i = snake.n - 1; i > 0; i--) {
snake.coor[i].x = snake.coor[i - 1].x;
snake.coor[i].y = snake.coor[i - 1].y;
}
switch (snake.ch) {
case up:snake.coor[0].y += SIZE; break; //上
case down:snake.coor[0].y -= SIZE; break; //下
case left:snake.coor[0].x -= SIZE; break; //左
case right:snake.coor[0].x += SIZE; break; //右
}
for (int i = snake2.n - 1; i > 0; i--) {
snake2.coor[i].x = snake2.coor[i - 1].x;
snake2.coor[i].y = snake2.coor[i - 1].y;
}
switch (snake2.ch) {
case up2:snake2.coor[0].y += SIZE; break; //上
case down2:snake2.coor[0].y -= SIZE; break; //下
case left2:snake2.coor[0].x -= SIZE; break; //左
case right2:snake2.coor[0].x += SIZE; break; //右
}
}
//改变方向
void Userscanf() {
char key;
key = getch(); //从键盘中敲值
switch (key) {
case up:
if (snake.ch != down)
snake.ch = up;
break;
case down:
if (snake.ch != up)
snake.ch = down;
break;
case left:
if (snake.ch != right)
snake.ch = left;
break;
case right:
if (snake.ch != left)
snake.ch = right;
break;
case up2:
if (snake2.ch != down2)
snake2.ch = up2;
break;
case down2:
if (snake2.ch != up2)
snake2.ch = down2;
break;
case left2:
if (snake2.ch != right2)
snake2.ch = left2;
break;
case right2:
if (snake2.ch != left2)
snake2.ch = right2;
break;
}
}
//吃食物
void Eatfood() {
if (snake.coor[0].x == food.coor.x && snake.coor[0].y == food.coor.y) {
snake.n++;
snake.num++;
food.flag = 0;
}
if(snake2.coor[0].x == food.coor.x && snake2.coor[0].y == food.coor.y) {
snake2.n++;
snake2.num++;
food.flag = 0;
}
}
//判断食物
int foodis() {
if (food.flag == 1)
return 1;
else if (food.flag == 0)
return 0;
}
//判断撞墙
int Gameover1() {
//撞墙
if (snake.coor[0].x <= 0 || snake.coor[0].x >= 640 || snake.coor[0].y <= 0 || snake.coor[0].y >= 480) {
return 1;
}
//撞到自己
for (int i = snake.n - 1; i > 0; i--) {
if ((snake.coor[0].x == snake.coor[i].x) && (snake.coor[0].y == snake.coor[i].y)) {
return 1;
}
}
//撞到他蛇
if(!snake2.flag)
for (int i = 0; i < snake2.num; i++) {
if ((snake.coor[0].x == snake2.coor[i].x) && (snake.coor[0].y == snake2.coor[i].y)) {
return 1;
}
}
//撞到石头
for (int i = 0; i < stone.n; i++) {
if (snake.coor[0].x == stone.coor[i].x && snake.coor[0].y == stone.coor[i].y) {
return 1;
}
}
return 0;
}
int Gameover2() {
//撞墙
if (snake2.coor[0].x <= 0 || snake2.coor[0].x >= 640 || snake2.coor[0].y <= 0 || snake2.coor[0].y >= 480) {
return 1;
}
//撞到自己
for (int i = snake2.n - 1; i > 0; i--) {
if ((snake2.coor[0].x == snake2.coor[i].x) && (snake2.coor[0].y == snake2.coor[i].y)) {
return 1;
}
}
//撞到他蛇
if(!snake.flag)
for (int i = 0; i < snake.num; i++) {
if ((snake2.coor[0].x == snake.coor[i].x) && (snake2.coor[0].y == snake.coor[i].y)) {
return 1;
}
}
//撞到石头
for (int i = 0; i < stone.n; i++) {
if (snake2.coor[0].x == stone.coor[i].x && snake2.coor[0].y == stone.coor[i].y) {
return 1;
}
}
return 0;
}
int Gameover3()
{
if (Gameover1() + Gameover2() == 2)
return 1;
return 0;
}
void Die()
{
if (Gameover1() == 1 && Gameover2() != 1) {
snake.n = 0;
snake.flag = 1;
}
if (Gameover1() != 1 && Gameover2() == 1) {
snake2.n = 0;
snake2.flag = 1;
}
}
void Theend() {
initgraph(640, 480);
if (snake.num > snake2.num)
outtextxy(300, 180, "玩家二胜");
else if (snake.num < snake2.num)
outtextxy(300, 180, "玩家一胜");
else
outtextxy(300, 180, "平局");
getchar();
closegraph();
}
修复了蛇死后脏数据处理问题
项目下载链接
链接:https://pan.baidu.com/s/1xeNlMMygGuDwj3VR2D9usw
提取码:yi0m