简单介绍一下需要的知识点
1,基本的输入与输出scanf和printf
2,分支与循环语句基本掌握,如if,switch,while,for,do while
3,函数的实现与调用
4,宏定义(不用也可以)
5,二维数组的基本掌握
核心思路介绍
我们可以用宏定义定义棋盘的大小,又因为棋盘查找雷的时候是查找周围的八个格子,容易越界访问,所以我们的棋盘得设置大一圈,最外圈不显示。现在你可能不懂,不过你继续看下去,你就懂了。
首先需要游戏说明,所以得先写一个菜单显示玩法。然后,它得可以循环玩,可以用while设置循环。
第一步,得有一个棋盘吧,棋盘我们分为两层,表面棋盘和埋雷棋盘。显而易见,棋盘我们用二维数组创作,我们可以创建两个棋盘,平常显示的表面棋盘,查找时可以刷新棋盘,显示周围的八个格子的雷的个数。
第二步,想想需要什么函数。首先,我们得有初始化棋盘函数,将表面棋盘设置为*,表示隐藏,隐藏棋盘初始设置为字符 ’0‘ 。所以这就需要一个初始化函数。 然后我们需要一个显示棋盘的函数,也就是打印棋盘。还要就是埋雷函数,我们可以以 ’1‘ 为雷,再有查雷函数。完成这些一个简单的扫雷就实现了。
实例如下,边上的为坐标,方便查看:
为了方便,我们可以将之放在三个文件中,分别是声明文件,测试文件,函数实现文件。如下:
大概流程如下,仅供参考
先从主体函数开始实现,也就是main函数和菜单
void menu() //菜单提供游戏选择
{
printf("--------------------\n");
printf("--- 1:play ------\n");
printf("--- 0:exit ------\n");
printf("--------------------\n");
}
int main()
{
int input = 0; //游戏操作标志
do //创作一个可以反复玩的游戏,用do while循环实现
{
menu(); //每次先显示菜单
printf("请输入游戏选择->");
scanf("%d", &input);
switch (input)
{
case 1:
break;
case 0:
break;
default:
printf("无效游戏操作,请重新输入\n");
break;
}
} while (input);
return 0;
}
一个大概的框架如此,先创作菜单,接着构建主体函数,通过do while 循环实现游戏可以反复玩,接着提供选择让玩家输入操作标志来实现功能。接下来就是函数功能的实现了与宏定义了。
实现后如下:
函数与宏定义
首先,定义棋盘大小与雷的个数,这些都是常量。你也可以根据自己的想法用全局变量实现。我是用的9 * 9 的大小。
代码如下:
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<Windows.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define MINE 10
其中,row代表行,col代表列,MINE代表雷的个数,这些是实现在头文件的,我取名为mine.h。你们可以根据自己的需要更改大小,实现宏定义的好处就是修改起来很容易,该一些row和col就可以了。
为了代码的可读性与美观方便,我们可以再修改一下初始代码,变成如下形式,函数可以写在game函数中:
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//棋盘的初始化
boardinit(mine,ROWS,COLS,'0');
boardinit(show,ROWS,COLS,'*');
//埋雷
setmine(mine, ROW, COL, MINE);
//棋盘显示
//displayboard(mine,ROW,COL);
displayboard(show,ROW,COL);
//查雷
findmine(mine, show, ROW, COL,MINE);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL)); //设置随机数种子
do
{
menu();
printf("请输入游戏选择->");
int x = scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
break;
default:
printf("无效游戏操作,请重新输入\n");
Sleep(500); //缓0.5秒后清空屏幕,美观。
system("cls"); //清空屏幕函数 此两条你可以不写
break;
}
} while (input);
return 0;
}
接下来我们一步步实现这些函数。上面的是我已经写好的,你们写的时候可以一个个函数来写,边写变调试一下看看会不会报错。
这样更方便调整代码。
首先,先写初始化函数。我们要先定义两个数组棋盘后初始化。
初始化函数你首先要确定返回类型,显然,它不需要返回类型,就是void类型的函数,函数名需要通俗易懂,就叫initboard(),再就是确定参数,我们要初始化的期盼数组,行,列,和初始化的参数。具体如下: (写在fun.cpp中)
void boardinit(char board[ROWS][COLS],int rows,int cols,char set)
{
//set表示你要初始化的东西是什么,比如’0‘或者’*‘
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
//没啥注意的,大家应该都会写吧
这些是写在头文件中声明的函数(注意分号):
void boardinit(char board[ROWS][COLS], int rows, int cols, char set);
void displayboard(char board[ROWS][COLS], int row, int col);
void setmine(char mine[ROWS][COLS], int row, int col,int minenum);
void findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,int minenum);
写完之后是这样的:
主要要调试打印看看,看看有没有错误。
打印函数
第二个函数就是显示棋盘的函数,先写这个方便查看。思路和上面是一样的,为了方便查看坐标,还会打印一圈周边的数字。
void displayboard(char board[ROWS][COLS],int row,int col)
{
printf("------扫雷游戏------\n"); //美观隔开
for (int x = 0; x < row+1; x++)
{
printf("%2d", x); //打印横坐标
}
printf("\n"); //注意换行隔开
for (int i = 1; i <= row; i++)
{
printf("%2d", i);
for (int j = 1; j <= col; j++)
{
printf("%2c", board[i][j]);
}
printf("\n");
}
}
打印的初始棋盘是这样的(坐标清晰明了):
设置雷的函数
参数都是类似的,这个就是多了个雷的个数的参数,之后就是实现了。
实现这个需要用到伪随机数函数,在这里简单介绍一下。
头文件为 #include<stdlib.h>, 涉及到两个函数,一个种子一个随机数,srand函数用来设置种子,括号中是unsigned int类型的种子。rand生成一个随机数并返回。然后需要用到时间函数用来设置一个变化的种子,用到#include<time.h>,具体实现如下:
#include<stdlib.h>
#include<time.h>
int main()
{
srand((unsigned int)time(NULL));
int x = rand() % 10;
printf("%d",x);
//用%10来限制随机数的范围在0-9
}
回归正题的设置雷函数:
最外圈是边界,所以坐标从1开始。
void setmine(char mine[ROWS][COLS], int row, int col,int minenum)
{
while (minenum)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
minenum--;
}
}
}
查雷函数
int findminenum(char mine[ROWS][COLS], int x, int y)
{
int minecount = 0; //计算周围八个格子雷的个数
for (int i = x - 1; i < x + 2; i++)
{
for (int j = y - 1; j < y + 2; j++)
{
if (mine[i][j] == '1')
{
minecount++;
}
}
}
return minecount;
}
void findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,int minenum)
{
int remain = row * col - minenum;
while (remain)
{
int x = 0;
int y = 0;
printf("请输入查找坐标:");
scanf("%d %d", &x, &y);
//判断边界
if ((x > row || x < 1 ) || (y > col || y < 1))
{
printf("无效坐标,请重新输入!\n");
continue;
}
int count = 0; //计算周围雷的个数
if (mine[x][y] == '1')
{
printf("可惜,你被雷炸死了,壮哉!\n");
displayboard(mine, row, col);
break;
}
else
{
system("cls");
count = findminenum(mine, x, y);
remain--;
show[x][y] = count + '0';
displayboard(show, row, col);
}
}
}
remain为不是雷的个数,需要进行排查的次数,如果排查到雷,直接结束游戏,否则就更新表面棋盘并显示周围雷的个数,因为是字符数组,所以显示的并不是纯数字,需要加’0‘,表示字符数字。
注意,不能忘记边界判断,否则容易出错。
如果你想要实现更复杂的功能,可以在此基础进行改进,不如进行复杂度的选择,雷的个数的选择,又或者你可以用图形库函数实现真正的扫雷完整版。
完整代码如下:
//mine.h
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<Windows.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define MINE 10
void boardinit(char board[ROWS][COLS], int rows, int cols, char set);
void displayboard(char board[ROWS][COLS], int row, int col);
void setmine(char mine[ROWS][COLS], int row, int col,int minenum);
void findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,int minenum);
//fun.cpp
#define _CRT_SECURE_NO_WARNINGS
#include"mine.h"
void boardinit(char board[ROWS][COLS],int rows,int cols,char set)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
void displayboard(char board[ROWS][COLS],int row,int col)
{
printf("------扫雷游戏------\n");
for (int x = 0; x < row+1; x++)
{
printf("%2d", x);
}
printf("\n");
for (int i = 1; i <= row; i++)
{
printf("%2d", i);
for (int j = 1; j <= col; j++)
{
printf("%2c", board[i][j]);
}
printf("\n");
}
}
void setmine(char mine[ROWS][COLS], int row, int col,int minenum)
{
while (minenum)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
minenum--;
}
}
}
int findminenum(char mine[ROWS][COLS], int x, int y)
{
int minecount = 0; //计算周围八个格子雷的个数
for (int i = x - 1; i < x + 2; i++)
{
for (int j = y - 1; j < y + 2; j++)
{
if (mine[i][j] == '1')
{
minecount++;
}
}
}
return minecount;
}
void findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,int minenum)
{
int remain = row * col - minenum;
while (remain)
{
int x = 0;
int y = 0;
printf("请输入查找坐标:");
scanf("%d %d", &x, &y);
if ((x > row || x < 1 ) || (y > col || y < 1))
{
printf("无效坐标,请重新输入!\n");
continue;
}
int count = 0; //计算周围雷的个数
if (mine[x][y] == '1')
{
printf("可惜,你被雷炸死了,壮哉!\n");
displayboard(mine, row, col);
break;
}
else
{
system("cls");
count = findminenum(mine, x, y);
remain--;
show[x][y] = count + '0';
displayboard(show, row, col);
}
}
}
//test.cpp
#define _CRT_SECURE_NO_WARNINGS
#include"mine.h"
void menu()
{
printf("--------------------\n");
printf("--- 1:play ------\n");
printf("--- 0:exit ------\n");
printf("--------------------\n");
}
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//棋盘的初始化
boardinit(mine,ROWS,COLS,'0');
boardinit(show,ROWS,COLS,'*');
//埋雷
setmine(mine, ROW, COL, MINE);
//棋盘显示
//displayboard(mine,ROW,COL);
displayboard(show,ROW,COL);
//查雷
findmine(mine, show, ROW, COL,MINE);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL)); //设置随机数种子
do
{
menu();
printf("请输入游戏选择->");
int x = scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
break;
default:
printf("无效游戏操作,请重新输入\n");
Sleep(500);
system("cls");
break;
}
} while (input);
return 0;
}
讲到这就结束了,看不懂可以多看几次,或者自己实践一下,实践出真知嘛,你可以跟着先敲一次,再自己独立完成,然后你可以试着开发几个自己的玩法,实现举一反三。