C语言彩色版贪吃蛇——图形界面Easyx的简单使用
大一上大概12月份学完了C语言,基本语法与知识已经基本具备,可以用C语言写出基本的贪吃蛇游戏,但是基础C语言的可视化与交互功能实在是太弱了,为了写出有色彩的游戏,需要在网上安装一个Easyx的插件,具体Easyx如何使用参见https://zhuanlan.zhihu.com/p/24826034点击打开链接
然后编程软件我用的是VS 2017(因为Dev C++不支持Easyx) VS安装入口:点击打开链接
程序实现了用户登陆与注册,用户数据保存到文件,高分榜等较为简单的功能,整个代码不算注释大概三百五十行。
游戏效果大概是这样:
*****************************************************我是分割线************************************************************
****************************************************************************************************************************
咳咳,在后台收到了一些同学的评论,现在作为一条在大学已经摸爬滚打快一年的资深咸鱼决定在这里集中更新一下,什么觉得time flies,什么回顾以前的代码觉得很菜的口水话我就不说了,进入正题:
1.有同学说在VS上运行我的代码出现了 debug assertion failed的错误;这个错误一般是因为访问了不该访问的文件或内存地址。首先看代码知道我创建了两个文本文件,scores.txt与Users1.txt分别用来储存用户的得分与用户的账号和密码,而这两个文件是既要读出,又要写入的,而且我在代码中是调用了两个文件的内容的,所以:你必须要事先创建scores.txt与Users.txt两个文本文件,不然代码中调用了文件指针fp,而它却指向了空的内容,就会出现debug assertion failed(指针越界)的错误。
emmmm,具体如何添加文本文件如下图所示:在实用工具的文本文件中把文件名修改为scores.txt与Users.txt,(你也可以改成别的,但代码中调用的文件名也要相应改动)
整个项目的布局应该是这样的:如下图所示
当我们注册了账号名为123,密码名为123的用户时,并且用它玩出了3分的高分时,再打开下图的这两个文本文件,就会发现它已经出现了改动(原本都是空的)。如下图所示:
这次更新就到这里,谢谢各位小老板的观看!
不定期更新,欢迎留言讨论,哈哈。
//代码如下:
#include <graphics.h> // 引用图形库头文件
#include <conio.h>
#include <stdio.h>
#include <windows.h>
#include <time.h>
#include <conio.h>
#include<stdlib.h>
#define frame_height 30 //define map size
#define frame_width 30
#define UP 'w' //define operate key
#define DOWN 's'
#define LEFT 'a'
#define RIGHT 'd'
#define SIZE 16
#define N 4
FILE *fp;
int i, j, k, m, n, s[N];
char s1[5], s2[5];
char ch = UP; //initial direction
int grow = 0; //flag: if snake grow
struct Food {
int x;
int y;
}food;
struct Snake {
int x[50];
int y[50];
int len;
int speed;
}snake; //snake[0] is head
typedef struct The_users //用于储存用户账号密码
{
char id[11];//ID
char pwd[20];//password
}users;
users a, b;//成员变量,用来登陆与注册
void init_map(void);
void update_food(void);
void move_snake(void);
int is_alive(void);
void get_speed(void);
void gotoxy(int x, int y);
void redraw_map(void);
void menu();
void registers();
void Login();
//void Create_File();
void score();
int compInc(const void *a, const void *b);
int compDec(const void *a, const void *b);
int main()
{
initgraph(640, 480);//创建绘图窗口
menu();
score();
return 0;
}
void redraw_map(void)
{
//initial bar
for (j = 0; j<frame_width; j++)
{
moveto(j*SIZE, 0);
setfillcolor(BLUE);
fillrectangle(j*SIZE, 0, j*SIZE + SIZE, SIZE);
moveto(j*SIZE, (frame_height - 1)*SIZE);
setfillcolor(BLUE);
fillrectangle(j*SIZE, (frame_height - 1)*SIZE, j*SIZE + SIZE, (frame_height - 1)*SIZE + SIZE);
}
for (i = 1; i<frame_height - 1;)
{
moveto(0, i*SIZE);
setfillcolor(BLUE);
fillrectangle(0, i*SIZE, 0 + SIZE, i*SIZE + SIZE);
moveto((frame_width - 1)*SIZE, i*SIZE);
setfillcolor(BLUE);
fillrectangle((frame_width - 1)*SIZE, i*SIZE, (frame_width - 1)*SIZE + SIZE, i*SIZE + SIZE);
i = i + 1;
}
}
void init_map(void)
{
//initial food
srand((unsigned int)time(NULL));
food.x = rand() % (frame_height - 2) + 1;
food.y = rand() % (frame_width - 2) + 1;
moveto(food.y*SIZE, food.x*SIZE);
setfillcolor(RED);
fillcircle(food.y *SIZE + SIZE / 2, food.x*SIZE + SIZE / 2, SIZE / 2);
//initial snake
snake.x[0] = (frame_height) / 2;
snake.y[0] = (frame_width) / 2;
moveto(snake.y[0] * SIZE, snake.x[0] * SIZE);
setfillcolor(GREEN);
fillcircle(snake.y[0] * SIZE + SIZE / 2, snake.x[0] * SIZE + SIZE / 2, SIZE / 2);
snake.len = 3;
snake.speed = 200;
for (k = 1; k<snake.len; k++)
{
snake.x[k] = snake.x[k - 1] + 1;
snake.y[k] = snake.y[k - 1];
moveto(snake.y[k] * SIZE, snake.x[k] * SIZE);
setfillcolor(GREEN);
fillcircle(snake.y[k] * SIZE + SIZE / 2, snake.x[k] * SIZE + SIZE / 2, SIZE / 2);
}
//initial bar
for (j = 0; j<frame_width; j++)
{
moveto(j*SIZE, 0);
setfillcolor(BLUE);
fillrectangle(j*SIZE, 0, j*SIZE + SIZE, SIZE);
moveto(j*SIZE, (frame_height - 1)*SIZE);
setfillcolor(BLUE);
fillrectangle(j*SIZE, (frame_height - 1)*SIZE, j*SIZE + SIZE, (frame_height - 1)*SIZE + SIZE);
}
for (i = 1; i<frame_height - 1;)
{
moveto(0, i*SIZE);
setfillcolor(BLUE);
fillrectangle(0, i*SIZE, 0 + SIZE, i*SIZE + SIZE);
moveto((frame_width - 1)*SIZE, i*SIZE);
setfillcolor(BLUE);
fillrectangle((frame_width - 1)*SIZE, i*SIZE, (frame_width - 1)*SIZE + SIZE, i*SIZE + SIZE);
i = i + 1;
}
}
//generate food
void update_food()
{
if (snake.x[0] == food.x&&snake.y[0] == food.y)
{
food.x = rand() % (frame_height - 2) + 1;
food.y = rand() % (frame_width - 2) + 1;
for (k = 1; k<snake.len; k++)
{
if (snake.x[k] == food.x&&snake.y[k] == food.y)
{
food.x = rand() % (frame_height - 2) + 1;
food.y = rand() % (frame_width - 2) + 1;
}
}
moveto(food.y*SIZE, food.x*SIZE);
setfillcolor(RED);
fillcircle(food.y*SIZE + SIZE / 2, food.x*SIZE + SIZE / 2, SIZE / 2);
snake.len++;
grow = 1;
}
}
//move snake
void move_snake()
{
if (_kbhit())
ch = _getch();
if (!grow)
{
moveto(snake.y[snake.len - 1] * SIZE, snake.x[snake.len - 1] * SIZE);
setfillcolor(BLACK);
solidrectangle(snake.y[snake.len - 1] * SIZE, snake.x[snake.len - 1] * SIZE, snake.y[snake.len - 1] * SIZE + SIZE, snake.x[snake.len - 1] * SIZE + SIZE);
}
for (k = snake.len - 1; k>0; k--)
{
snake.x[k] = snake.x[k - 1];
snake.y[k] = snake.y[k - 1];
}
switch (ch)
{
case UP: snake.x[0]--; break;
case DOWN: snake.x[0]++; break;
case LEFT: snake.y[0]--; break;
case RIGHT: snake.y[0]++; break;
default: break;
}
moveto(snake.y[0] * SIZE, snake.x[0] * SIZE);
setfillcolor(GREEN);
fillcircle(snake.y[0] * SIZE + SIZE / 2, snake.x[0] * SIZE + SIZE / 2, SIZE / 2);
grow = 0;
}
//is alive
int is_alive(void)
{
if (snake.x[0] == 0 || snake.x[0] == frame_height - 1 || snake.y[0] == frame_width - 1 || snake.y[0] == 0)
return 0;
for (k = 1; k<snake.len; k++)
if (snake.x[k] == snake.x[0] && snake.y[k] == snake.y[0])
return 0;
return 1;
}
//speed up
void get_speed(void)
{
if (snake.len <= 6)
snake.speed = 200;
else if (snake.len <= 10)
snake.speed = 100;
else if (snake.len <= 20)
snake.speed = 50;
else if (snake.len <= 30)
snake.speed = 30;
else snake.speed = 20;
}
//move cursor
void gotoxy(int x, int y)
{
HANDLE hout;
COORD cor;
hout = GetStdHandle(STD_OUTPUT_HANDLE);
cor.X = y;
cor.Y = x;
SetConsoleCursorPosition(hout, cor);
}
void menu()
{
InputBox(s1, 5, "请输入数字:1.开始游戏2.高分榜3.退出游戏");
int x, y[3];
sscanf_s(s1, "%d", &x);//将用户输入转化为数字
if (x == 1)
{
InputBox(s2, 5, "请输入数字:1.注册2.登陆");
sscanf_s(s2, "%d", &x);
if (x == 1) {
registers();
Login();
}
else if (x == 2) {
Login();
}
init_map(); //初始化地图
while (1)
{
update_food();
//是否产生食物
get_speed(); //获取速度
move_snake(); //移动蛇身
redraw_map();//重绘地图
Sleep(snake.speed);
//移动速度
if (!(is_alive()))
//蛇的死活(撞墙或自食)
break;
}
closegraph();//关闭绘图窗口
printf("Game Over!\n");
printf("你的得分:%d", snake.len - 3);
_getch();
}
else if (x == 2)
{
closegraph();
printf(" 排行榜\n");
fopen_s(&fp, "scores.txt", "r");
for (x = 0; x < N - 1; x++) {
fscanf_s(fp, "%d", &y[x]);
printf("%d\n", y[x]);
}
fclose(fp);
_getch();
}
else
{
closegraph();
}
}
void registers()//注册账号密码
{
fopen_s(&fp, "Users1.txt", "r");
fscanf_s(fp, "%s%s", b.id, sizeof(b.id), b.pwd, sizeof(b.pwd));
InputBox(a.id, 11, "请输入账号");
while (1)
{
if (strcmp(a.id, b.id) != 0)//如果两串字符串不相等
{
if (!feof(fp))//如果未至文件末尾
{
fscanf_s(fp, "%s%s", b.id, sizeof(b.id), b.pwd, sizeof(b.pwd));
}
else break;
}
else
{
outtextxy(220, 200, "此用户名已被注册");
fclose(fp);
_getch();
exit(0);
}
}
fclose(fp);
InputBox(a.pwd, 10, "请输入密码");
fopen_s(&fp, "Users1.txt", "a");
fprintf_s(fp, "%s %s\n", a.id, a.pwd);
outtextxy(220, 200, "账号注册成功!");
fclose(fp);
}
void Login()//登陆账号密码
{
fopen_s(&fp, "Users1.txt", "r");
fscanf_s(fp, "%s%s", b.id, sizeof(b.id), b.pwd, sizeof(b.pwd));
InputBox(a.id, 11, "请输入账号");
while (1)
{
if (strcmp(a.id, b.id) == 0) break;//如果找到了这个用户名
else
{
if (!feof(fp))//如果文件未读完
fscanf_s(fp, "%s%s", b.id, sizeof(b.id), b.pwd, sizeof(b.pwd));
else
{
outtextxy(220, 200, "此用户名不存在!");
fclose(fp);
_getch();
exit(0);
}
}
}
InputBox(a.pwd, 20, "请输入密码");
if (strcmp(a.pwd, b.pwd) == 0)//如果密码匹配
{
fclose(fp);
outtextxy(250, 200, "登陆成功!");
initgraph(640, 480);
}
else
{
outtextxy(220, 200, "密码不正确");
_getch();
exit(0);
}
}
void score()
{
fopen_s(&fp, "scores.txt", "r");
for (n = 0; n < N - 1; n++)
{
fscanf_s(fp, "%d", &m);
s[n] = m;
}
s[N - 1] = snake.len - 3;
qsort(s, N, sizeof(s[0]), compDec);
fclose(fp);
fopen_s(&fp, "scores.txt", "w");
for (n = 0; n < N - 1; n++)
{
fprintf_s(fp, "%d\n", s[n]);
}
fclose(fp);
}
int compInc(const void *a, const void *b)
{
return *(int *)a - *(int *)b;
}//升序排序
int compDec(const void *a, const void *b) {
return *(int *)b - *(int *)a;
}//降序排序
上一篇: 环形队列,任意长度入队和出队
下一篇: 循环数组实现队列