逆向软件工程
本逆向软件工程的项目来自我朋友大一做的扫雷项目,以下是其源代码 运行环境是VScode。
点击查看代码
#include<stdio.h>
//#include"asaolei.h"
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define Count 10
void initially(char arr[ROWS][COLS],int r,int c,char ch);
void DisplayBoard(char a[ROWS][COLS],int row,int col);
void setmine(char a[ROWS][COLS],int row,int col);
void menu()//游戏的菜单
{
printf("********************\n");
printf("******1、PLAY*******\n");
printf("******0、exit*******\n");
printf("********************\n");
}
void initially(char a[ROWS][COLS],int row,int col,char ch)
{
int i,j;
for(i=0;i<row;i++)
{
j=0;
for(j=0;j<col;j++)
{
a[i][j]=ch;
}
}
}
void DisplayBoard(char a[ROWS][COLS],int row,int col)
{
int i,j;
printf("-------扫雷游戏------\n");
printf("--------start-------\n");
for(i=0;i<=col;i++)
{
printf("%-2d",i);
}
printf("\n");
for(i=1;i<=row;i++)
{
printf("%d",i);
for(j=1;j<=col;j++)
{
printf("%2c",a[i][j]);
}
printf("\n");
}
}
void setmine(char a[ROWS][COLS],int row,int col)
{
int count = Count;
while(count)
{
int x=rand()%row+1;
int y=rand()%col+1;//将雷的坐标控制在1~9之内
if(a[x][y]=='0')
{
a[x][y]='1';
count --;
}
}
}
int Getmine_count(char mine[ROWS][COLS],int x,int y)
{
int count=0,i,j;
for(i=x-1;i<=x+1;i++)
{
for(j=y-1;j<=y+1;j++)
{
if(mine[i][j]=='1')
{
count++;
}
}
}
return count;
}
void Findmine(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
int x;
int y;
int win=0;
printf("请输入要排查的坐标\n");
while(win<row*col-Count)
{
scanf("%d %d",&x,&y);
if(x>=1&&x<=row&&y>=1&&y<=col)
{
if(mine[x][y]=='1')
{
printf("很遗憾,你被我埋的雷炸死咯哈哈哈\n");
printf("小趴菜,让你看看我的雷在哪\n");
DisplayBoard(mine,ROW,COL);
break;
}
else
{
//统计该坐标周围一共有多少个雷
int n=Getmine_count(mine,x,y);
show[x][y]=n+'0';
DisplayBoard(show,ROW,COL);
win++;
}
}
else{
printf("坐标非法请重新输入\n");
}
if(win==row*col-Count)
{
printf("铁子实力有的呢,拆弹专家,排雷成功\n");
break;
}
}
}
void game()//完成扫雷游戏
{
char mine[ROWS][COLS] = {0};//全部初始化为‘0’
char show[ROWS][COLS] = {0};// 全部初始化为‘*’
//定义一个初始化函数完成初始化
initially(mine,ROWS,COLS,'0');
initially(show,ROWS,COLS,'*');
//打印棋盘
//DisplayBoard(mine,ROW,COL);
//DisplayBoard(show,ROW,COL);
//布置雷,在9*9的棋盘上随机布置10个雷
setmine(mine,ROW,COL);
//DisplayBoard(mine,ROW,COL);
DisplayBoard(show,ROW,COL);
//排查雷
Findmine(mine,show,ROW,COL);
}
void test()
{
int n;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择->");
scanf("%d",&n);
switch(n)
{
case 1 :
game();
n=0;
break;
case 0 :
printf("游戏结束,退出游戏\n");
break;
default :
printf("选择错误,请重新选择\n");
break;
}
} while (n);
}
int main()
{
test();
return 0;
}

原来的代码存在的问题是:
1、有重复的代码 代码冗余
2、有不必要的循环,在Findmine函数中,每次输入坐标后都会重新计算周围雷的数量,可以考虑在初始化时预先计算每个格子的雷数,减少运行时计算量。
3、在setmine函数中,随机生成雷的位置时,如果位置已经被占用,会重新生成随机数。(可以考虑使用洗牌算法(Fisher-Yates shuffle)来生成雷的位置,避免重复生成随机数)
4、在Findmine函数中缺少对输入坐标的验证,没有确保输入的坐标是有效的
以下是改进后的代码:
点击查看代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define MINE_COUNT 10
void initially(char arr[ROWS][COLS], int rows, int cols, char ch);
void displayBoard(char a[ROWS][COLS], int row, int col);
void setMines(char a[ROWS][COLS], int row, int col);
int getMineCount(char mine[ROWS][COLS], int x, int y);
void findMines(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
void menu();
void game();
void test();
void initially(char a[ROWS][COLS], int rows, int cols, char ch) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
a[i][j] = ch;
}
}
}
void displayBoard(char a[ROWS][COLS], int row, int col) {
printf("-------扫雷游戏------\n");
printf("--------start-------\n");
for (int i = 0; i <= col; i++) {
printf("%-2d", i);
}
printf("\n");
for (int i = 1; i <= row; i++) {
printf("%d", i);
for (int j = 1; j <= col; j++) {
printf("%2c", a[i][j]);
}
printf("\n");
}
}
void setMines(char a[ROWS][COLS], int row, int col) {
int count = MINE_COUNT;
while (count) {
int x = rand() % row + 1;
int y = rand() % col + 1;
if (a[x][y] == '0') {
a[x][y] = '1';
count--;
}
}
}
int getMineCount(char mine[ROWS][COLS], int x, int y) {
int count = 0;
for (int i = x - 1; i <= x + 1; i++) {
for (int j = y - 1; j <= y + 1; j++) {
if (mine[i][j] == '1') {
count++;
}
}
}
return count;
}
void findMines(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
int x, y;
int win = 0;
while (win < row * col - MINE_COUNT) {
printf("请输入要排查的坐标 (x y): ");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) {
if (mine[x][y] == '1') {
printf("很遗憾,你被我埋的雷炸死咯哈哈哈\n");
printf("小趴菜,让你看看我的雷在哪\n");
displayBoard(mine, ROW, COL);
break;
} else {
int n = getMineCount(mine, x, y);
show[x][y] = n + '0';
displayBoard(show, ROW, COL);
win++;
}
} else {
printf("坐标非法请重新输入\n");
}
}
if (win == row * col - MINE_COUNT) {
printf("铁子实力有的呢,拆弹专家,排雷成功\n");
}
}
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};
initially(mine, ROWS, COLS, '0');
initially(show, ROWS, COLS, '*');
setMines(mine, ROW, COL);
displayBoard(show, ROW, COL);
findMines(mine, show, ROW, COL);
}
void test() {
int n;
srand((unsigned int)time(NULL));
do {
menu();
printf("请选择->");
scanf("%d", &n);
switch (n) {
case 1:
game();
break;
case 0:
printf("游戏结束,退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (n != 0);
}
int main() {
test();
return 0;
}

浙公网安备 33010602011771号