- 在上一篇文章中已经带大家如何搭建开发环境了
需求分析
- 这里是一个8*8的地图
地雷随机分布数字表示周围一共有多少颗雷
数字1表示红色区域内有1课雷,2表示有两颗
如何显示数字
右上角没有如何判断呢?行加1或列加一不就越界了吗,所以为了帮面条件判断我们把8行8列改成10行10列
游戏实现
-
先包含头文件
-
#include
-
#include
-
初始化窗口大小,就类似于我们要搭台唱戏一样,需要一个舞台这个舞台大小需要多大,我们需要指定一下舞台大小,不指定怎么知道需要多大的舞台呢?这就是初始化
-
初始化窗口: RenderWindow window(VideoMode(800, 800), “Canxin-MINE”);
-
RenderWindow window(VideoMode(窗口宽度,窗口高度),“窗口右上角的描述信息”);
宽为x坐标,高为y坐标;
-
获取当前鼠标点击的x坐标和y坐标
-
Vector2i pos = Mouse::getPosition(window);
-
我们要把鼠标的x坐标和y坐标转化成行和列,就需要鼠标的x坐标除以方块的像素宽度,y坐标也是一样
-
#include
#include
#include
using namespace sf;
#define SIZE 10 //地图宽度
enum {
NONE_MINE = 0,
MINE = 9, //地雷
GROUND, //地面
FLAG //旗帜
};
enum {
SUCCESS,
FAILURE,
GOING
};
int unitSize = 64;
int mineData[SIZE + 2][SIZE + 2]; // 0:没有雷 9:有雷(以避免和雷的数字提示混淆)
int showData[SIZE + 2][SIZE + 2];
int mineCount = 0;
bool success_flag = false;
bool failure_flag = false;
void initMine() {
//布雷
for (int i = 1; i <= SIZE; i++) {
for (int j = 1; j <= SIZE; j++) {
showData[i][j] = GROUND; // 设置为未点击状态(“地面”)
//布雷
if (rand() % 5 == 0) {
mineData[i][j] = MINE;
mineCount++;
}
else {
mineData[i][j] = NONE_MINE;
}
}
}
// 计算雷周围位置的数字显示
for (int i = 1; i <= SIZE; i++)
for (int j = 1; j <= SIZE; j++)
{
int n = 0;
if (mineData[i][j] == MINE) continue;
if (mineData[i + 1][j] == MINE) n++;
if (mineData[i][j + 1] == MINE) n++;
if (mineData[i - 1][j] == MINE) n++;
if (mineData[i][j - 1] == MINE) n++;
if (mineData[i + 1][j + 1] == MINE) n++;
if (mineData[i - 1][j - 1] == MINE) n++;
if (mineData[i - 1][j + 1] == MINE) n++;
if (mineData[i + 1][j - 1] == MINE) n++;
mineData[i][j] = n;
}
}
int check(RenderWindow* window) {
int count = 0;
for (int i = 1; i <= SIZE; i++) {
for (int j = 1; j <= SIZE; j++) {
if (mineData[i][j] == MINE && showData[i][j] == FLAG) {
count++;
continue;
}
else if (mineData[i][j] == MINE && showData[i][j] == MINE) {
failure_flag = true;
return FAILURE;
}
}
}
if (count == mineCount) {
success_flag = true;
return SUCCESS;
}
return GOING;
}
int main()
{
srand(time(0));
RenderWindow window(VideoMode(800, 800), "Canxin-MINE"); //初始化窗口
//加载图片
Texture t;
t.loadFromFile("images/tiles2.jpg");
Sprite s(t);
//布雷
initMine();
Texture t1, t2;
t1.loadFromFile("images/victory.png");
t2.loadFromFile("images/fail.png");
Sprite spriteVictory(t1);
Sprite spriteFail(t2);
Sound soundOK;
SoundBuffer buff1;
buff1.loadFromFile("OK.wav");
soundOK.setBuffer(buff1);
Sound soundFail;
SoundBuffer buff2;
buff2.loadFromFile("bom.wav");
soundFail.setBuffer(buff2);
while (window.isOpen())
{
// 获取鼠标在游戏窗口内的位置坐标
Vector2i pos = Mouse::getPosition(window);
int x = pos.x / unitSize;
int y = pos.y / unitSize;
int ret = -1;
Event e;
while (window.pollEvent(e))
{
if (x <= 0 || x > SIZE || y <= 0 || y > SIZE) {
break;
}
if (e.type == Event::Closed) //关闭窗口按钮
window.close();
if (e.type == Event::MouseButtonPressed) {
if (e.key.code == Mouse::Left) showData[x][y] = mineData[x][y];
else if (e.key.code == Mouse::Right) showData[x][y] = FLAG;
ret = check(&window);
}
}
// 清除屏幕
window.clear(Color::Yellow);
// 绘制雷区的各方块
for (int i = 1; i <= SIZE; i++) {
for (int j = 1; j <= SIZE; j++) {
if (showData[x][y] == 9) showData[i][j] = mineData[i][j];
s.setTextureRect(IntRect(showData[i][j] * unitSize, 0, unitSize, unitSize));
s.setPosition(i * unitSize, j * unitSize);
window.draw(s);
}
}
//int ret = check(&window);
if (success_flag) {
spriteVictory.setPosition(250, 250);
window.draw(spriteVictory);
}
if (failure_flag) {
spriteFail.setPosition(250, 250);
window.draw(spriteFail);
}
if (ret == FAILURE) {
soundFail.play();
}
else if (ret == GOING) {
soundOK.play();
}
// 刷新显示
window.display();
}
//奇牛学院-残芯
return 0;
}