适合刚入门C语言的编程学习小白的十个练手项目,每个都很经典且实用,让你学完C语言不再迷茫!

一、多关卡推箱子

主要考察知识点:数组

开发工具:Visual Studio2019、EasyX图形库

效果图:

完整代码:

/*
--------------------------------------
■   墙壁                               1
☆  目的地                              3
★  箱子                                4
○   箱子到达目的地                     3+4=7
♀   人                              5
    人到达目的地                     8
空格 路                              0
1.设计关卡(定义关卡,判断关卡
2.找素材,用贴图的办法做一个可视化的推箱子游戏

*/
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <graphics.h>
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")  //静态库资源

//用三维数组特定的数字描绘出这个地图
int cas = 0;
int map[4][8][8] =
{
	1,1,1,1,1,1,1,1,
	1,3,4,0,0,4,3,1,
	1,0,1,3,0,1,0,1,
	1,0,1,4,0,1,0,1,
	1,0,0,5,0,0,0,1,
	1,0,1,0,0,1,0,1,
	1,3,4,0,0,4,3,1,
	1,1,1,1,1,1,1,1,

	1,1,1,1,1,1,1,1,
	1,3,4,0,0,4,3,1,
	1,0,1,3,0,1,0,1,
	1,0,1,4,0,1,0,1,
	1,3,4,5,0,0,0,1,
	1,0,1,0,0,1,0,1,
	1,3,4,0,0,4,3,1,
	1,1,1,1,1,1,1,1,

	1,1,1,1,1,1,1,1,
	1,3,4,0,0,4,3,1,
	1,0,1,3,0,1,0,1,
	1,0,1,4,0,1,0,1,
	1,3,4,0,0,4,3,1,
	1,0,1,0,0,1,0,1,
	1,3,4,5,0,4,3,1,
	1,1,1,1,1,1,1,1,

	1,1,1,1,1,1,1,1,
	1,3,4,0,0,4,3,1,
	1,0,1,3,0,1,3,1,
	1,3,1,4,0,1,4,1,
	1,4,0,0,0,5,0,1,
	1,0,0,0,0,1,0,1,
	1,3,4,0,0,4,3,1,
	1,1,1,1,1,1,1,1,

};
IMAGE img[6];		//6张图片,6个名字
void loadResource()
{
	loadimage(img + 0, "0.bmp", 50, 50);
	loadimage(img + 1, "1.bmp", 50, 50);
	loadimage(img + 2, "3.bmp", 50, 50);
	loadimage(img + 3, "4.bmp", 50, 50);
	loadimage(img + 4, "5.bmp", 50, 50);
	loadimage(img + 5, "7.bmp", 50, 50);
}


//绘制地图
void  drawGraph()
{
	for (int i = 0; i < 8; i++)
	{
		for (int j = 0; j < 8; j++)
		{
			//算贴图的坐标
			int x = 50 * j;
			int y = 50 * i;
			switch (map[cas][i][j])
			{
			case 0:
				//一个汉字符号占用两个位置
				//printf("  ");
				putimage(x, y, img + 0);
				break;
			case 1:
				putimage(x, y, img + 1);
				//printf("■");
				break;
			case 3:
				putimage(x, y, img + 2);
				//printf("☆");
				break;
			case 4:
				putimage(x, y, img + 3);
				//printf("★");
				break;
			case 5:
			case 8:
				putimage(x, y, img + 4);
				//printf("人");
				break;
			case 7:
				putimage(x, y, img + 5);
				//printf("●");
				break;
			}
		}
		//printf("\n");
	}
}
//玩游戏
void keyDown()
{
	int userKey = _getch();	//不可见输入
	//定位:找到人的位置
	int i = 0;
	int j = 0;
	for (i = 1; i < 8; i++)
	{
		for (j = 1; j < 8; j++)
		{
			if (map[cas][i][j] == 5 || map[cas][i][j] == 8)
			{
				goto NEXT;
			}
		}
	}
NEXT:

	//我们这个游戏用什么按键去玩
	switch (userKey)
	{
	case 'W':
	case 'w':
	case 72:
		if (map[cas][i - 1][j] == 0 || map[cas][i - 1][j] == 3)
		{
			map[cas][i][j] -= 5;
			map[cas][i - 1][j] += 5;
		}
		if (map[cas][i - 1][j] == 4 || map[cas][i - 1][j] == 7)
		{
			if (map[cas][i - 2][j] == 0 || map[cas][i - 2][j] == 3)
			{
				map[cas][i][j] -= 5;
				map[cas][i - 1][j] += 1;
				map[cas][i - 2][j] += 4;
			}
		}
		break;
	case 's':
	case 'S':
	case 80:
		if (map[cas][i + 1][j] == 0 || map[cas][i + 1][j] == 3)
		{
			map[cas][i][j] -= 5;
			map[cas][i + 1][j] += 5;
		}
		if (map[cas][i + 1][j] == 4 || map[cas][i + 1][j] == 7)
		{
			if (map[cas][i + 2][j] == 0 || map[cas][i + 2][j] == 3)
			{
				map[cas][i][j] -= 5;
				map[cas][i + 1][j] += 1;
				map[cas][i + 2][j] += 4;
			}
		}
		break;
	case 'a':
	case 'A':
	case 75:
		if (map[cas][i][j - 1] == 0 || map[cas][i][j - 1] == 3)
		{
			//a+=1  a=a+1 复合赋值运算符
			map[cas][i][j] -= 5;
			map[cas][i][j - 1] += 5;
		}
		if (map[cas][i][j - 1] == 4 || map[cas][i][j - 1] == 7)
		{
			if (map[cas][i][j - 2] == 0 || map[cas][i][j - 2] == 3)
			{
				map[cas][i][j] -= 5;
				map[cas][i][j - 1] += 1;
				map[cas][i][j - 2] += 4;
			}
		}
		break;
	case 'd':
	case 'D':
	case 77:
		if (map[cas][i][j + 1] == 0 || map[cas][i][j + 1] == 3)
		{
			map[cas][i][j] -= 5;
			map[cas][i][j + 1] += 5;
		}
		if (map[cas][i][j + 1] == 4 || map[cas][i][j + 1] == 7)
		{
			if (map[cas][i][j + 2] == 0 || map[cas][i][j + 2] == 3)
			{
				map[cas][i][j] -= 5;
				map[cas][i][j + 1] += 1;
				map[cas][i][j + 2] += 4;
			}
		}
		break;
	}
}
//胜负的判断:
int gameOver()
{
	//地图上没有箱子就可以结束
	for (int i = 0; i < 8; i++)
	{
		for (int j = 0; j < 8; j++)
		{
			if (map[cas][i][j] == 4)
			{
				return 0;
			}
		}
	}
	return 1;
}

int main()
{
	loadResource();//定义加载资源函数
	mciSendString("open 1.mp3", 0, 0, 0);//加载音乐
	mciSendString("play 1.mp3 repeat", 0, 0, 0);//循环播放音乐资源
	initgraph(50 * 8, 50 * 8);
	while (1)
	{
		drawGraph();
		if (gameOver())
		{
			cas++;			//变换关卡
			if (cas == 4)
				break;
		}
		keyDown();//循环按下按键
		//system("cls");
	}
	closegraph();//关闭窗口
	return 0;
}

二、扫雷

主要考察知识点:数组

开发工具:Visual Studio2019、EasyX图形库

效果图:

完整代码:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<easyx.h>

#include<mmsystem.h>
#pragma comment(lib, "winmm.lib")

#define ROW 10	//定义行列的常量
#define COL	10 
#define MineNum 10	//雷的数量
#define ImgSize	40	//图片的尺寸

//定义图片资源
IMAGE imgs[12];
void loadResource()
{
	for (int i = 0; i < 12; i++)
	{
		char imgPath[50] = { 0 };
		sprintf_s(imgPath, "./images/%d.jpg", i);
		loadimage(&imgs[i], imgPath, ImgSize, ImgSize);
	}
}

bool isfirst = true;	//是不是第一次进来

//函数声明
void show(int map[][COL]);
void init(int map[][COL]);
void draw(int map[][COL]);
void mouseMsg(ExMessage* msg, int map[][COL]);
void boomBlank(int map[][COL], int row, int col);
int judge(int map[][COL], int row, int col);
int main()
{
	//创建窗口
	initgraph(400, 400/*,EW_SHOWCONSOLE*/);
	//播放开始音乐
	mciSendString("open ./images/start.mp3 alias bgm", NULL, 0, NULL);
	mciSendString("play bgm", NULL, 0, NULL);

	//扫雷地图
	int map[ROW][COL] = {0};
	init(map);

	//游戏主循环
	while (true)
	{
		//处理消息
		ExMessage msg;
		while (peekmessage(&msg, EM_MOUSE))
		{
			switch (msg.message)
			{
			case WM_LBUTTONDOWN:	//鼠标左键和右键点击
			case WM_RBUTTONDOWN:
				mouseMsg(&msg, map);
				int ret = judge(map,msg.y/ImgSize, msg.x / ImgSize);		//点击之后判断
				if (ret == -1)
				{

					draw(map);
					int select = MessageBox(GetHWnd(), "你这么牛,怎么输了呢?敢再来一把吗?", "low B!", MB_OKCANCEL);
					if (select == IDOK)	//再来一把
					{
						//重新初始化
						init(map);
					}
					else  //退出
					{
						exit(0);
					}

				}
				else if(ret == 1)
				{

				}
				system("cls");
				printf("judege:%d\n", ret);
				show(map);
				break;
			}
		}
		draw(map);		
	}

	//show(map);
	getchar();
	return 0;
}

void show(int map[][COL])
{
	for (int i = 0; i < ROW; i++)
	{
		for (int k = 0; k < COL; k++)
		{
			printf("%2d ", map[i][k]);
		}
		printf("\n");
	}
}
//初始化数据
void init(int map[][COL])
{
	loadResource();
	//设置随机数种子
	srand((unsigned)time(NULL));

	//把map全部初始化为0
	memset(map, 0, sizeof(int) * ROW * COL);

	//随机设置十个雷 用-1表示
	for (int i = 0; i < MineNum; )
	{
		//数组的有效下标 [0,9]
		int r = rand() % ROW;
		int c = rand() % COL;
		if (map[r][c] == 0)
		{
			map[r][c] = -1;
			//只有执行了这里的代码,才成功设置了雷 -1
			i++;
		}
	}

	//把以雷为中心的九宫格数据都+1,雷除外
	for (int i = 0; i < ROW; i++)
	{
		for (int k = 0; k < COL; k++)
		{
			//找到雷,并遍历雷所在的九宫格
			if (map[i][k] == -1)
			{
				for (int r = i-1; r <= i+1; r++)
				{
					for (int c = k-1; c <= k+1; c++)
					{
						//对周围的数据加1,会有一个bug
						if ((r >= 0 && r < ROW && c >= 0 && c < COL) && map[r][c] != -1)
						{
							++map[r][c];
						}
					}
				}
			}
		}
	}

	//加密格子
	for (int i = 0; i < ROW; i++)
	{
		for (int k = 0; k < COL; k++)
		{
			map[i][k] += 20;
		}
	}
}
//绘制
void draw(int map[][COL])
{
	//贴图,根据map里面的数据,贴对应的图片
	for (int i = 0; i < ROW; i++)
	{
		for (int k = 0; k < COL; k++)
		{
			if (map[i][k]>=0 && map[i][k]<=8)	//[0,8]
			{
				int index = map[i][k];	//0 1 2 3 4 5 6 7 8
				putimage(k * ImgSize, i * ImgSize, &imgs[index]);	//
			}
			else if (map[i][k] == -1)
			{
				putimage(k * ImgSize, i * ImgSize, &imgs[9]);
			}
			else if (map[i][k] >= 19 && map[i][k] <= 28)
			{
				putimage(k * ImgSize, i * ImgSize, &imgs[10]);
			}
			else if(map[i][k] >= 39)	//-1 + 20 +20
			{
				putimage(k * ImgSize, i * ImgSize, &imgs[11]);
			}
		}
	}
}
//鼠标操作数据
void mouseMsg(ExMessage* msg,int map[][COL])
{
	//先根据鼠标点击的坐标求出对应的数组的下标
	int r = msg->y / ImgSize;
	int c = msg->x / ImgSize;
	//左键打开格子
	if (msg->message == WM_LBUTTONDOWN)
	{
		//什么时候能够打开,没有打开的时候就打开
		if (map[r][c]>=19 && map[r][c]<=28)
		{
			//这个函数只能播放wav格式
			PlaySound("./images/click.wav", NULL, SND_ASYNC | SND_FILENAME);
			map[r][c] -= 20;
			boomBlank(map, r, c);	//检测一下是不是空白格子,是,炸开
			isfirst = true;
		}	
	}
	//右键标记格子
	else if (msg->message == WM_RBUTTONDOWN)
	{
		PlaySound("./images/rightClick.wav", NULL, SND_ASYNC | SND_FILENAME);
		//是否能够标记:如果没有打开就能标记
		if (map[r][c] >= 19 && map[r][c] <= 28)
		{
			map[r][c] += 20;
		}
		else if(map[r][c]>=39)
		{
			map[r][c] -= 20;
		}
	}
}
//点击空白格子,连环爆开周围的所有空白格子还有数字  row col 是当前点击的格子
void boomBlank(int map[][COL],int row,int col)
{	
	//判断row col位置是不是空白格子
	if (map[row][col] == 0)
	{
		for (int r = row-1; r <= row+1; r++)
		{
			for (int c = col-1; c <= col+1; c++)
			{
				if ((r>=0&&r<ROW&&c>=0&&c<COL)			//没越界
					&& map[r][c]>=19 && map[r][c]<=28)	//没有打开
				{
					//每一次调用都会播放一下
					if (isfirst)
					{
						PlaySound("./images/search.wav", NULL, SND_ASYNC | SND_FILENAME);
						isfirst = false;
					}

					map[r][c] -= 20;
					boomBlank(map, r, c);
				}
			}
		}
	}
	return;
}
//游戏结束条件 输了返回-1  没结束返回0 赢了返回 1
int judge(int map[][COL],int row ,int col)
{
	//点到了雷,结束	输了
	if (map[row][col] == -1 || map[row][col] == 19)
	{
		return -1;
	}

	//点完了格子,结束 赢了 点开了100 - 10 = 90 个格子
	int cnt = 0;
	for (int i = 0; i < ROW; i++)
	{
		for (int k = 0; k < COL; k++)
		{
			//统计打开的格子的数量
			if (map[i][k] >= 0 && map[i][k] <= 8)
			{
				++cnt;
			}
		}
	}
	if (ROW*COL - MineNum == cnt)
	{
		return 1;
	}

	return 0;
}

三、贪吃蛇

主要考察知识点:结构体

开发工具:Visual Studio2019、EasyX图形库

效果图:

完整代码:

 

#include<stdio.h>
#include<graphics.h>
#include<stdlib.h>
#include<conio.h>
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")
/*
	课程内容:贪吃蛇
	解析:1,创建界面,绘图,矩形表示 的圣体~
		 2,绘制蛇
		 3,蛇的移动
		 4,产生食物
		 5,吃食物
		 6,游戏输赢判断
		 7,分数,穿墙。。。。
	蛇的属性:长度,坐标,方向,速度,是否死亡,分数
*/
#define WIDTH 800 //窗口的宽高
#define HEIGHT 600
#define SNAKE_NUM 500//蛇的最大节数
enum DIR//蛇的方向
{
	UP,		//上
	DOWN,
	LEFT,
	RIGHT,
};
struct Snake //蛇的结构
{
	int size; //有多少节
	POINT coor[SNAKE_NUM];//每一节蛇的坐标数组
	int dir;//蛇的方向
	int speed;//速度
	int score;//分数
}snake;
struct Food//食物
{
	int x;
	int y;
	int r;
	int flag;//是否被吃掉
	COLORREF color;
}food;
//初始化数据
void GameInit()
{
	//播放背景音乐
	mciSendString(L"open ./ress/snake_bgm.mp3 alias BGM", 0, 0, 0);
	mciSendString(L"play BGM repeat", 0, 0, 0);
	//设置随机数种子
	srand(GetTickCount());
	//初始化蛇
	snake.dir = DIR::RIGHT;//思考:怎么表示蛇的方向?  ::域运算符
	snake.score = 0;
	snake.size = 3;
	snake.speed = 10;
	snake.coor[2].x = 10;
	snake.coor[2].y = 10;
	snake.coor[1].x = 20;
	snake.coor[1].y = 10;
	snake.coor[0].x = 30;
	snake.coor[0].y = 10;
	//初始化食物
	food.color = RGB(rand() % 256, rand() % 256, rand() % 256);
	food.flag = 1;
	food.r = rand() % 10 + 5;
	food.x = rand() % WIDTH;
	food.y = rand() % HEIGHT;
}
void GameDraw()
{
	BeginBatchDraw();//防止闪屏
	//设置背景颜色
	setbkcolor(RGB(151, 203, 208));
	cleardevice();
	//绘制蛇
	for (int i = 0; i < snake.size; i++)
	{
		setfillcolor(BLACK);
		solidcircle(snake.coor[i].x, snake.coor[i].y, 5);
	}
	//绘制食物
	if (food.flag)
	{
		setfillcolor(food.color);
		solidcircle(food.x, food.y, food.r);
	}
	
	EndBatchDraw();
}
//蛇的移动
void SnakeMove()
{
	//移动蛇身体,每一节蛇(处舌头外),都等于前一节的上一次坐标
	for (int i = snake.size - 1; i>0; i--)//从蛇尾遍历到蛇头
	{
		snake.coor[i] = snake.coor[i - 1];//结构体可以直接赋值
		//snake.coor[i].x = snake.coor[i - 1].x;
		//snake.coor[i].y = snake.coor[i - 1].y;
	}

	//移动蛇头
	switch (snake.dir)
	{
	case UP:
		snake.coor[0].y -= snake.speed;
		if (snake.coor[0].y <= 0)
		{
			snake.coor[0].y = HEIGHT;
		}
		break;
	case DOWN:
		snake.coor[0].y += snake.speed;
		if (snake.coor[0].y >= HEIGHT)
		{
			snake.coor[0].y = 0;
		}
		break;
	case LEFT:
		snake.coor[0].x -= snake.speed;
		if (snake.coor[0].x <= 0)
		{
			snake.coor[0].x = WIDTH;
		}
		break;
	case RIGHT:
		snake.coor[0].x += snake.speed;
		if (snake.coor[0].x >= WIDTH)
		{
			snake.coor[0].x = 0;
		}
		break;
	}
}
//改变蛇的方向
void keyControl()
{
	if ((GetAsyncKeyState('W') || GetAsyncKeyState(VK_UP)) && snake.dir!=DOWN)
	{
		snake.dir = UP;
	} 
	if ((GetAsyncKeyState('S') || GetAsyncKeyState(VK_DOWN)) && snake.dir != UP)
	{
		snake.dir = DOWN;
	}
	if ((GetAsyncKeyState('A') || GetAsyncKeyState(VK_LEFT)) && snake.dir != RIGHT)
	{
		snake.dir = LEFT;
	}
	if ((GetAsyncKeyState('D') || GetAsyncKeyState(VK_RIGHT)) && snake.dir != LEFT)
	{
		snake.dir = RIGHT;
	}
}
void EatFood()
{
	if (snake.coor[0].x >= food.x - food.r && snake.coor[0].x <= food.x + food.r &&
		snake.coor[0].y >= food.y - food.r && snake.coor[0].y <= food.y + food.r &&
		food.flag)
	{
		mciSendString(L"close eat", 0, 0, 0);
		mciSendString(L"open ./ress/eatfood.mp3 alias eat", 0, 0, 0);
		mciSendString(L"play eat", 0, 0, 0);
		snake.size++;
		food.flag = 0;
	}
	//如果食物被吃了,就重新生成一个食物
	if (!food.flag)
	{
		food.color = RGB(rand() % 256, rand() % 256, rand() % 256);
		food.flag = 1;
		food.r = rand() % 10 + 5;
		food.x = rand() % WIDTH;
		food.y = rand() % HEIGHT;
	}
}
//使程序暂停
void stop()
{
	if (_kbhit())//检测是否有按键
	{
		if (_getch() == ' ')
		{
			while (_getch() != ' ');
		}
	}
}
void die()
{
	for (int i = 4; i < snake.size; i++)
	{
		if (snake.coor[0].x == snake.coor[i].x && snake.coor[0].y == snake.coor[i].y)
		{
			MessageBox(GetHWnd(), L"you die!low B!", L"warnning~",MB_OK);
			exit(666);
		}
	}
}
int main()
{
	initgraph(WIDTH, HEIGHT);
	GameInit();
	DWORD t1, t2;//typedef unsigned long   DWORD;
	t1 = t2 = GetTickCount();//获取系统开机到现在,所经过的毫秒数
	while (1)
	{
		GameDraw();
		if (t2 - t1 > 200)
		{
			SnakeMove();
			t1 = t2;
		}
		t2 = GetTickCount();
		keyControl();
		EatFood();
		stop();
		die();
		//Sleep(500);//使整个程序,延迟,而我要的是移动延迟
	}

	return 0;
}

由于文章篇幅原因,下面程序都只放效果图,所有项目完整源码及资源包可以进群领取哦!还有更多学习资料、电子书籍、案例源码,欢迎大家一起学习交流,共同进步!点击下方链接进群领取

点击链接加入群聊【C语言/C++交流彗星二群】

四、连连看

效果图:

五、拼图游戏

效果图:

六、飞机大战

效果图:

七、流星雨表白(单身程序员必备)

效果图:

八、烟花表白(单身程序员必备)

九、中国象棋

效果图:

十、数字雨

效果图:

今天就先给大家分享这十个最基础的入门项目!后续会更新更多高级案例和项目实战,有需要的小伙伴可以点赞收藏加关注~

需要C语言入门大礼包、各种C语言C++学习资料的小伙伴可以加入小编的学习群,里面聚集了一些正在学习C语言的小伙伴,在学习C语言的过程中遇到任何的问题,大家都可以一起交流,希望大家都能够实现自己的梦想,加油!资料领取点击下面链接加群哦!

点击链接加入群聊【C语言/C++交流群】

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐