C++实现扫雷、排雷小游戏
本文实例为大家分享了C++实现扫雷、排雷小游戏的具体代码,供大家参考,具体内容如下
界面:
游戏思想:
扫雷游戏:
1.随机给定雷点坐标
2.判断每个点的雷情况
3.由用户根据上下左右键到达指定位置,点击enter,翻开该点
如果该点是雷点,此时翻开所有雷点,告知游戏结束
非雷点,翻开该点坐标
代码:
#include<iostream>
#include<vector>
#include<sstream>
#include<algorithm>
#include<graphics.h>
#include<ctime>
#include<conio.h>
using namespace std;
#define WIDTH 500
#define HEIGHT 500
#define SIDE 50
#define THUNDERNUM 10
#define TOTALSCORE 100
#define EVERY_OF_DESC 5
int score = TOTALSCORE;
class Point {
public:
int x;
int y;
Point() {}
Point(int _x, int _y)
:x(_x), y(_y)
{}
void setPoint(int x, int y) {
this->x = x;
this->y = y;
}
Point(const Point& xy)
:x(xy.x), y(xy.y)
{}
bool operator<(const Point& xy)const {
if (x <= xy.x)
return true;
return y <= xy.y;
}
Point& operator=(const Point& xy) {
if (this != &xy) {
x = xy.x;
y = xy.y;
}
return *this;
}
bool operator==(const Point& xy) {
return ((x == xy.x) && (y = xy.y));
}
bool operator!=(const Point& xy) {
return !(*this == xy);
}
};
class ThunderPoint {
private:
vector<Point> storage;
int num;
public:
ThunderPoint(int _num = THUNDERNUM)
:num(_num) {
//初始化雷点位置
int count = 0;
while (count != num) {
int x = (rand() % (WIDTH / SIDE)) * SIDE;//随机生成数据,使之在图形界面之中
int y = (rand() % (HEIGHT / SIDE)) * SIDE;
Point tem(x, y);
int i = -1;
bool flag = false;
for (i = 0; i < storage.size(); i++) {
if (tem == storage[i]) {
flag = true;
break;
}
}
if (flag==false) {
//说明没有重复
storage.push_back(tem);
count++;
}
}
}
vector<Point>& getThunderPoint() {
//获得雷点位置
return storage;
}
void drawThunderPoint() {
auto it = storage.begin();
while (it != storage.end()) {
setfillcolor(RED);
fillcircle((*it).x, (*it).y, SIDE / 2);
++it;
}
}
};
class Grid {
private:
vector<vector<int>> nearbythunder;
vector<vector<bool>> isopen;
ThunderPoint thunder;
Point currposition;
Point preposition;
vector<COLORREF> color;
public:
bool isOver;
public:
Grid()
:thunder(10),currposition()
{
preposition.setPoint(0, 0);
for (int i = 0; i < 10; ++i) {
color.push_back(RGB(rand() % 256, rand() % 256, rand() % 256));
}
isOver = false;
isopen.resize(HEIGHT / SIDE, vector<bool>(WIDTH / SIDE, false));
nearbythunder.resize(HEIGHT/SIDE,vector<int>(WIDTH/SIDE,0));
currposition.setPoint(0, 0);
//先将雷点的位置标出来,标为数字 9
// 任何一个点,他附近的雷点最多8个
auto it = thunder.getThunderPoint().begin();
while (it != thunder.getThunderPoint().end()) {
int x = ((*it).x)/SIDE;
int y = ((*it).y)/SIDE;
nearbythunder[x][y] = 9;
if (((y - SIDE/SIDE) >= 0) && (nearbythunder[x][y - SIDE/SIDE] != 9)) {
nearbythunder[x][y - SIDE/SIDE]++;
}
if (((y - SIDE/SIDE) >= 0) && ((x - SIDE/SIDE) >= 0) && (nearbythunder[x - SIDE/SIDE][y - SIDE/SIDE] != 9)) {
nearbythunder[x - SIDE/SIDE][y - SIDE/SIDE]++;
}
if (((y - SIDE/SIDE) >= 0) && ((x + SIDE/SIDE) < WIDTH/SIDE) && (nearbythunder[x + SIDE/SIDE][y - SIDE/SIDE] != 9)) {
nearbythunder[x + SIDE/SIDE][y - SIDE/SIDE]++;
}
if (((x - SIDE/SIDE) >= 0) && (nearbythunder[x - SIDE/SIDE][y] != 9)) {
nearbythunder[x - SIDE/SIDE][y]++;
}
if (((x + SIDE/SIDE) < WIDTH/SIDE) && (nearbythunder[x + SIDE/SIDE][y] != 9)) {
nearbythunder[x + SIDE/SIDE][y]++;
}
if (((y + SIDE/SIDE) < HEIGHT/SIDE) && (nearbythunder[x][y + SIDE/SIDE] != 9)) {
nearbythunder[x][y + SIDE/SIDE]++;
}
if (((y + SIDE/SIDE) < HEIGHT/SIDE) && ((x - SIDE/SIDE) >= 0) && (nearbythunder[x - SIDE/SIDE][y + SIDE/SIDE] != 9)) {
nearbythunder[x - SIDE/SIDE][y + SIDE/SIDE]++;
}
if (((y + SIDE / SIDE) < HEIGHT / SIDE) && ((x + SIDE / SIDE) < WIDTH / SIDE) && (nearbythunder[x + SIDE / SIDE][y + SIDE / SIDE] != 9)) {
nearbythunder[x + SIDE / SIDE][y + SIDE / SIDE]++;
}
++it;
}
for (int i = 0; i < HEIGHT; i = i + SIDE) {
setlinecolor(YELLOW);
line(0, i, WIDTH, i);
line(i, 0, i, HEIGHT);
}
}
void keyDown()
{
char userKey = _getch();
if (userKey == -32) // 表明这是方向键
userKey = -_getch(); // 获取具体方向,并避免与其他字母的 ASCII 冲突
setfillcolor(GREEN);
preposition = currposition;
switch (userKey)
{
case 'w':
case 'W':
case -72: //上
{
if (currposition.y - SIDE >= 0) {
currposition.y -= SIDE;
}
}
break;
case 's':
case 'S':
case -80://下
{
if (currposition.y + SIDE < HEIGHT)
currposition.y += SIDE;
}
break;
case 'a':
case 'A':
case -75://左
{
if (currposition.x - SIDE >= 0)
currposition.x -= SIDE;
}
break;
case 'd':
case 'D':
case -77://右
{
if (currposition.x + SIDE < WIDTH) {
currposition.x += SIDE;
}
}
break;
case '\r':
{
score -= EVERY_OF_DESC;
settextstyle(10, 10, "楷体");
settextcolor(GREEN);
RECT rect;
rect.left = WIDTH-100; rect.top = 100; rect.right = WIDTH; rect.bottom = 200;
string ll = to_string(score);
const char* str = ll.c_str();
//drawtext(str, &rect, 1);
//现在开始翻
openOne(currposition);
}
break;
}
setlinecolor(BLACK);
setlinestyle(1, 0);
line(preposition.x, preposition.y, preposition.x + SIDE, preposition.y);
setfillcolor(GREEN);
setlinecolor(WHITE);
setlinestyle(1, 2);
line(currposition.x, currposition.y, currposition.x + SIDE, currposition.y );
}
private:
bool pred(bool x) {
return x == true;
}
void openOne(const Point& cur) {
//说明此时翻一个
isopen[cur.x / SIDE][cur.y / SIDE] = true;
//此时应该着色
settextcolor(color[nearbythunder[cur.x/SIDE][cur.y/SIDE]]);
RECT rect;
settextstyle(SIDE, SIDE, "楷体");
rect.left = cur.x; rect.top = cur.y; rect.right = cur.x + SIDE; rect.bottom = cur.y + SIDE;
drawtext((to_string(nearbythunder[cur.x / SIDE][cur.y / SIDE])).c_str(), &rect, 1);
int count = 0;
for (int i = 0; i < HEIGHT / SIDE; ++i) {
for (int j = 0; j < WIDTH / SIDE; ++j) {
if (isopen[i][j] == true) {
count++;
}
}
}
cout << count << endl;
if (nearbythunder[cur.x / SIDE][cur.y / SIDE] == 9 || count==((WIDTH/SIDE)*(HEIGHT/SIDE)- THUNDERNUM)) {
//说明游戏结束
setfillcolor(RED);
for (int i = 0; i < thunder.getThunderPoint().size(); i++) {
fillcircle((thunder.getThunderPoint()[i]).x + SIDE / 2, (thunder.getThunderPoint()[i]).y + SIDE / 2, SIDE / 2);
}
settextcolor(WHITE);
settextstyle(SIDE, SIDE, "楷体");
rect.left = 0; rect.top = 4*SIDE; rect.right = WIDTH; rect.bottom = HEIGHT;
drawtext("GAMEOVER!", &rect, 2);
isOver = true;
return;
}
}
};
int main() {
initgraph(WIDTH, HEIGHT);//初始化界面
srand((unsigned)time(NULL));//设置随机数据种子,以当前的时间戳为种子
setbkcolor(RED);
srand((unsigned)time(NULL));
settextcolor(BLUE);
setbkmode(TRANSPARENT); // 设置文字输出模式为透明c
setbkcolor(HSLtoRGB(100, 0.3, 7.5f));
Grid gr;
while (gr.isOver==false) {
gr.keyDown();
}
system("pause");
clearcliprgn();
}
代码解读:
1.类之间的联系
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
以上是 C++实现扫雷、排雷小游戏 的全部内容, 来源链接: utcz.com/p/245200.html