C语言编程练习(15)——扫雷游戏(图片音乐版)

扫雷游戏(图片音乐版)

使用工具:VS2019、easyX图形库

easyX官网:https://easyx.cn/
代码、素材已发布到 “资源”。

功能:
1、扫雷游戏的基本实现。
2、鼠标左键单击:扫雷
3、鼠标中键单击:游戏提示
4、鼠标右键单击:插一个小旗子/拔一个小旗子
5、游戏获胜和失败的提示。

C语言实现——“扫雷小游戏”


一、代码部分

头文件game.h:

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <graphics.h>
#include <time.h>
#include <mmsystem.h>

#pragma comment(lib,"winmm.lib")

#define GRID_WIDTH		45				//小方格子的宽度
#define GRID_HEIGHT		45				//小方格子的高度
#define GRID_ROW_NUMBER		10			//小方格子一行的数量
#define GRID_COL_NUMBER		10			//小方格子一列的数量
#define PICTURE_NUMBER		12			//图片素材的数量
#define MINE_NUMBER		10				//地雷的数量
#define CODE			40

//初始化图片素材
void pictureInit(IMAGE pic[PICTURE_NUMBER]);

//初始化地图数值
void mapInit(int map[][GRID_COL_NUMBER]);

//在控制台上显示地图的数值
void mapShow(int map[][GRID_COL_NUMBER]);

//窗口上的图片显示
void pictureShow(int map[][GRID_COL_NUMBER], IMAGE pic[PICTURE_NUMBER]);

//鼠标操作
void mouseControl(int map[][GRID_COL_NUMBER], MOUSEMSG msg);

//播放音乐
void playmusic(const char music[]);

//打开附近的空地
void openNull(int map[][GRID_COL_NUMBER], int row, int col);

//是否获胜
int ifWin(int map[][GRID_COL_NUMBER]);

源文件game.c:

#include "game.h"

//初始化图片素材
void pictureInit(IMAGE pic[PICTURE_NUMBER])
{
    
    
	char str[50] = {
    
     "" };

	for (int i = 0; i < PICTURE_NUMBER; i++)			//对图片进行批量加载
	{
    
    
		sprintf_s(str, "./resource/%d.jpg", i);
		loadimage(&pic[i], str, GRID_WIDTH, GRID_HEIGHT);
	}
}

//初始化地图数值
void mapInit(int map[][GRID_COL_NUMBER])
{
    
    
	//将 -1 作为地雷的数值,放入地图中(地雷的位置不能重复)
	for (int i = 0; i < MINE_NUMBER; )
	{
    
    
		int r = rand() % GRID_ROW_NUMBER;
		int c = rand() % GRID_COL_NUMBER;
		if (map[r][c] != -1)
		{
    
    
			map[r][c] = -1;
			i++;
		}
	}
	//将地雷附近的九宫格写入数值
	for (int i = 0; i < GRID_ROW_NUMBER; i++)			//遍历地图
	{
    
    
		for (int j = 0; j < GRID_COL_NUMBER; j++)
		{
    
    
			if (map[i][j] == -1)						//找到地图上的地雷位置
			{
    
    
				for (int r = i - 1; r <= i + 1; r++)	//遍历地雷附近的九宫格
				{
    
    
					for (int c = j - 1; c <= j + 1; c++)
					{
    
    
						//在不越界的情况下,使地雷附近的九宫格数值+1
						if (r >= 0 && r < GRID_ROW_NUMBER && c >= 0 && c < GRID_COL_NUMBER && map[r][c] != -1)
						{
    
    
							map[r][c]++;
						}	
					}
				}
			}
		}
	}
	//将地图的值全部隐藏		-1~8 -> -1+CODE ~ 8+CODE
	for (int i = 0; i < GRID_ROW_NUMBER; i++)
	{
    
    
		for (int j = 0; j < GRID_COL_NUMBER; j++)
		{
    
    
			map[i][j] += CODE;			//通过加减一个固定的值,使数值加密、解密
		}
	}
}

//在控制台上显示地图的数值
void mapShow(int map[][GRID_COL_NUMBER])
{
    
    
	for (int i = 0; i < GRID_ROW_NUMBER; i++)
	{
    
    
		for (int j = 0; j < GRID_COL_NUMBER; j++)
		{
    
    
			printf("%2d ", map[i][j]);
		}
		printf("\n");
	}
	
}

//窗口上的图片显示
void pictureShow(int map[][GRID_COL_NUMBER], IMAGE pic[PICTURE_NUMBER])
{
    
    
	for (int i = 0; i < GRID_ROW_NUMBER; i++)
	{
    
    
		for (int j = 0; j < GRID_COL_NUMBER; j++)
		{
    
    
			if (map[i][j] >= -1 + CODE && map[i][j] <= 8 + CODE)		//点开之前
			{
    
    
				putimage(j * GRID_WIDTH, i * GRID_HEIGHT, &pic[10]);
			}
			else if (map[i][j] >= 0 && map[i][j] <= 8)					//点开之后
			{
    
    
				putimage(j * GRID_WIDTH, i * GRID_HEIGHT, &pic[map[i][j]]);
			}
			else if (map[i][j] == -1)									//点开地雷
			{
    
    
				putimage(j * GRID_WIDTH, i * GRID_HEIGHT, &pic[9]);
			}
			else if (map[i][j] >= -1 + 2 * CODE && map[i][j] <= 8 + 2 * CODE)//插小旗子
			{
    
    
				putimage(j * GRID_WIDTH, i * GRID_HEIGHT, &pic[11]);
			}
		}
	}
}

//鼠标操作
void mouseControl(int map[][GRID_COL_NUMBER], MOUSEMSG msg)
{
    
    
	if (MouseHit())			//如果鼠标点击
	{
    
    
		msg = GetMouseMsg();			//读取鼠标消息
		int r = msg.y / GRID_WIDTH;
		int c = msg.x / GRID_HEIGHT;
		switch (msg.uMsg)
		{
    
    
		case WM_LBUTTONDOWN:			//左键按下
			playmusic("click.wav");
			if (map[r][c] >= -1 + CODE && map[r][c] <= 8 + CODE)
			{
    
    
				map[r][c] -= CODE;
				//打开附近的空地
				openNull(map, r, c);
			}
			break;
		case WM_MBUTTONDOWN:			//中键按下
			playmusic("search.wav");
			system("cls");
			//在控制台上显示地图的数值
			mapShow(map);
			break;
		case WM_RBUTTONDOWN:			//右键按下
			playmusic("rightclick.wav");
			if (map[r][c] >= -1 + CODE && map[r][c] <= 8 + CODE)
			{
    
    
				map[r][c] += CODE;
			}
			else if (map[r][c] >= -1 + 2 * CODE && map[r][c] <= 8 + 2 * CODE)
			{
    
    
				map[r][c] -= CODE;
			}
			break;
		default:
			break;
		}
	}
}

//播放音乐
void playmusic(const char music[])
{
    
    
	char str[50] = {
    
     "" };
	
	sprintf_s(str, "close ./resource/%s", music);
	mciSendString(str, 0, 0, 0);				//先关闭音乐
	sprintf_s(str, "open ./resource/%s", music);
	mciSendString(str, 0, 0, 0);				//后打开音乐
	sprintf_s(str, "play ./resource/%s", music);
	mciSendString(str, 0, 0, 0);				//最后播放音乐
}

//打开附近的空地
void openNull(int map[][GRID_COL_NUMBER], int row, int col)
{
    
    
	if (map[row][col] == 0)
	{
    
    
		for (int i = row - 1; i <= row + 1; i++)
		{
    
    
			for (int j = col - 1; j <= col + 1; j++)
			{
    
    
				if (i >= 0 && i < GRID_ROW_NUMBER && j >= 0 && j < GRID_COL_NUMBER && map[i][j] >= 0 + CODE && map[i][j] <= 8 + CODE)
				{
    
    
					map[i][j] -= CODE;
					openNull(map, i, j);
				}

			}
		}
	}
	
}

//是否获胜
int ifWin(int map[][GRID_COL_NUMBER])
{
    
    
	int cnt = 0;			//点开的 非雷格子数量
	for (int i = 0; i < GRID_ROW_NUMBER; i++)
	{
    
    
		for (int j = 0; j < GRID_COL_NUMBER; j++)
		{
    
    
			if (map[i][j] == -1)		//踩到地雷,失败
			{
    
    
				return 0;
			}
			if (map[i][j] >= 0 && map[i][j] <= 8)
			{
    
    
				cnt++;
			}
			if (cnt == (GRID_ROW_NUMBER * GRID_COL_NUMBER - MINE_NUMBER))//90个非雷格子
			{
    
    
				return 1;
			}
		}
	}
	return 999;			//继续游戏
}

源文件main.c:

#include "game.h"

IMAGE pic[PICTURE_NUMBER];
int map[GRID_ROW_NUMBER][GRID_COL_NUMBER];
MOUSEMSG msg;

int main()
{
    
    
	srand((unsigned)time(NULL));

	//7.播放音乐
	playmusic("start.mp3");
	//1.创建窗口(窗口的宽:列数*格子的宽度)(窗口的高:行数*格子的高度)
	initgraph(GRID_COL_NUMBER * GRID_WIDTH, GRID_HEIGHT * GRID_ROW_NUMBER, SHOWCONSOLE);
	//2.初始化图片素材
	pictureInit(pic);
	//3.初始化地图数值
	mapInit(map);
	//4.在控制台上显示地图的数值
	mapShow(map);

	while (1)
	{
    
    
		//5.窗口上的图片显示
		pictureShow(map, pic);
		//6.鼠标操作
		mouseControl(map, msg);
		//8.是否获胜
		if (ifWin(map) == 0)
		{
    
    
			//5.窗口上的图片显示
			pictureShow(map, pic);
			MessageBox(GetHWnd(), "你输了!", "Lose", MB_OK);
			break;
		}
		else if (ifWin(map) == 1)
		{
    
    
			//5.窗口上的图片显示
			pictureShow(map, pic);
			MessageBox(GetHWnd(), "你赢了!", "Win", MB_OK);
			break;
		}
	}
	
	//关闭窗口
	closegraph();
	return 0;
}

二、运行结果

1.压缩包里有什么?
在这里插入图片描述
2.debug文件
在这里插入图片描述
3.resource文件
在这里插入图片描述
4.游戏界面

在这里插入图片描述
5.左键单击
在这里插入图片描述
6.中键单击
在这里插入图片描述
7.中键单击
在这里插入图片描述
8.游戏结束
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44739914/article/details/112410196