下面是我在学习扫雷后,自己整理思路写出的代码,并完成了拓展以及优化,还有对胜利条件,失败条件设立彩蛋,分为三个文件,两个源文件,一个头文件,我会在附属文件里定义函数,在头文件声明,而主函数所在的源文件短小精悍。
//这个是附属源文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("*************************\n");
printf("*******1. 进入游戏*******\n");
printf("*******0. 退出游戏*******\n");
printf("*************************\n");
}
void print_board(char show[ROWS][COLS], int row, int col)
{
printf("-----------------扫雷------------------\n");
int i, j;
for (j = 1; j <= col + 1; j++)
{
printf("--- ");
}
printf("\n");
for (j = 0; j <= col; j++)
printf(" %d】", j);
printf("\n");
for (j = 0; j <= col; j++)
printf("--- ");
printf("\n");
for (i = 1; i <= row; i++)
{
printf(" %d】", i);
for (j = 1; j <= col; j++)
{
printf(" %c |", show[i][j]);
}
printf("\n");
for (j = 1; j <= col + 1; j++)
{
printf("--- ");
}
printf("\n");
}
}
void init_board(char show[ROWS][COLS], int row, int col, char a)
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
show[i][j] = a;
}
}
void setmine(char mine[ROWS][COLS], int row, int col)
{
int i;
for (i = 0; i < NUM; i++)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
mine[x][y] = '1';
else
i--;
}
}
int get_mine_num(char mine[ROWS][COLS], int row, int col)
{
return (mine[row + 1][col + 1] + mine[row][col + 1] + mine[row + 1][col]
+ mine[row - 1][col + 1] + mine[row + 1][col - 1] + mine[row - 1][col - 1]
+ mine[row][col - 1] + mine[row - 1][col] - '0' * 8);
}
void it_is_0(char mine[ROWS][COLS], char show[ROWS][COLS],int x,int y)
{
int i , j;
if (get_mine_num(mine, x, y) == 0)
{
show[x][y] = ' ';
for (i = -1; i <= 1; i++)
{
if (x + i == 0 || x + i == ROW + 1)
continue;
for (j = -1; (j <= 1) && (y + i != 0) && (y + i != COL + 1); j++)
{
if (y + j == 0 || y + j != COL + 1)
if (!(i == 0 && j == 0) && show[x + i][y + j] == '*')
{
show[x + i][y + j] = get_mine_num(mine, x + i, y + j) + '0';
it_is_0(mine, show, x+i, y+j);
}
}
}
}
}
int howmany_mine(char show[ROWS][COLS], int row, int col)
{
int n = 0, i, j;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (show[i][j] == '*')
n++;
}
}
return n;
}
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0, y = 0;
while ((howmany_mine(show,ROW,COL))>NUM)
{
printf("\n请输入你要排查的位置:>");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] != '*')
{
printf("这个位置被排查过了!\n");
Sleep(2500);
}
if (mine[x][y] == '1')
{
system("cls");
printf("Oh!");
Sleep(1000);
system("cls");
printf("NO!");
Sleep(1000);
system("cls");
printf("脑子被雷炸没了!\n");
print_board(show, ROW, COL);
printf("这个是答案坐标,1就是雷的位置,0是安全点\n");
print_board(mine, ROW, COL);
break;
}
else
{
show[x][y] = get_mine_num(mine, x, y) + '0';
it_is_0(mine, show, x, y);
system("cls");
print_board(show, ROW, COL);
}
}
else
{
printf("输入错误,请重新输入\n");
print_board(mine, ROW, COL);
}
}
if ((howmany_mine(show, ROW, COL)) == NUM)
{
system("cls");
char arr5[] = "ohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh";
char arr6[] = " ";
int left2 = 0;
int right2 = strlen(arr5) - 1;//用sizeof会把\0算进去。
for (; left2 <= right2; left2++)
{
arr6[left2] = arr5[left2];
printf("%s\n", arr6);
printf("%s\n", arr6);
printf("%s\n", arr6);
printf("%s\n", arr6);
printf("%s\n", arr6);
printf("%s\n", arr6);
printf("%s\n", arr6);
printf("%s\n", arr6);
Sleep(25);
system("cls");
}
char arr1[] = "gong xi ni cheng gong la !";
char arr2[] = " ";
int left = 0;
int right = strlen(arr1) - 1;
for (; left <= right; left++, right--)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf("%s\n", arr2);
Sleep(250);
system("cls");
}
printf("gong xi ni cheng gong la !");
Sleep(1000);
system("cls");
char arr3[] = "CONGRATULATION!";
char arr4[] = " ";
int left1 = 0;
int right1 = strlen(arr3) - 1;
for (; left1 <= right1; left1++, right1--)
{
arr4[left1] = arr3[left1];
arr4[right1] = arr3[right1];
printf("%s\n", arr4);
Sleep(250);
}
system("cls");
printf("CONGRATULATION!");
Sleep(1000);
system("cls");
printf("恭喜你!!!!!!!!!!!!!!!!!");
system("cls");
printf("恭喜你呀恭喜你\n");
Sleep(500);
printf(" 恭喜你呀恭喜你~\n");
Sleep(500);
printf("恭喜你呀恭喜你\n");
Sleep(500);
printf(" 恭喜你呀恭喜你~\n");
Sleep(500);
printf("恭喜你呀恭喜你\n");
Sleep(500);
printf(" 恭喜你呀恭喜你~\n");
Sleep(500);
printf("恭喜你呀恭喜你\n");
Sleep(500);
printf(" 恭喜你呀恭喜你~\n");
Sleep(500);
system("cls");
print_board(show, ROW, COL);
printf("恭喜你成功了!\n这个是布雷的坐标图,1因为雷点,0为安全点\n");
print_board(mine, ROW, COL);
}
}
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
init_board(mine, ROWS, COLS, '0');
init_board(show, ROWS, COLS, '*');
print_board(show, ROW, COL);
setmine(mine, ROW, COL);
find_mine(mine, show, ROW, COL);
}
void start()
{
srand((unsigned int)time(NULL));
int count = 2;
int n = 0;
do
{
menu();
printf("请玩家选择:>");
scanf("%d", &n);
switch (n)
{
case 1:
{
system("cls");
game();
break;
}
case 0:
{
if (count == 1)
printf("好吧,下次再玩!\n");
if (count == 2)
printf("你确定要退出游戏?\n");
count--;
break;
}
default:
printf("\n请重新输入:>");
break;
}
} while (count);
}
//这个是声明用的头文件
#pragma once
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<Windows.h>
#include<string.h>
#define ROW 9 //行数
#define COL 9 //列数
#define ROWS (ROW+2)
#define COLS (COL+2)
#define NUM 10 //雷数
//启动函数
void start();
//菜单函数
void menu();
//打印函数
void print_board(char show[ROWS][COLS], int row, int col);
//初始化函数
void inti_board(char show[ROWS][COLS], int row, int col, char a);
//随机布雷函数
void setmine(char mine[ROWS][COLS], int row, int col);
//获得附近雷数函数
int get_mine_num(char mine[ROWS][COLS], int row, int col);
//排雷函数
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//游戏函数
void game();
//遇0自动扩展递归函数
void it_is_0(char mine[ROWS][COLS], char show[ROWS][COLS], int* win, int x, int y);
//*的个数函数
int howmany_mine(char show[ROWS][COLS], int row, int col);
这个是主函数所在源文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
int main()
{
start();
return 0;
}
而对于游戏创作,应该定好功能,分好模块,设立函数(先直接写函数名,然后再去定义),再去想算法,(临时的想法有可能成立,敢于尝试!!!)
这个扫雷有个很巧妙的地方,就是设立了两个棋盘,一个是布置雷的,一个是展示的,但也很正常,因为布置雷的是“答案”,而我们展示肯定是不能给答案的。
还有一个就是表格扩大一圈,目的是为了测试边边的地点周围的雷的个数,而打印什么,还是自己说了算。
还有优化方面,我优化了表格可以自定义(数组定义时不能填变量,但是可以填宏),还有使用递归去使得判定雷的个数是0的时候自动扩张,但是这样判定胜利条件的方法就要改变。
而观感优化了表格的形式,我加了一些线条,还有坐标提示,eg 0】| 1】.......,使得填的时候更加舒适,以及结束时候失败以及胜利设立有趣的彩蛋。
总而言之就是先定好框架,有自己的思路,一步一步来,需要什么函数大胆设立下来,然后去定义去实现,想到一些算法就大胆去干!