diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..175c707d58f563677c3d0424822425c60340c231 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +*.exe +.vs/ +.gitee/ +test/ \ No newline at end of file diff --git a/README.md b/README.md index f33b4fab48cc8c0c84936253ea610dc531bf7338..d985e98cf78819494a4513bab22615dba8e127b7 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ - 基础交互 - [ ] UI - - [ ] 逻辑处理 + - [√] 逻辑处理 - [ ] 局面选项(长宽等等) - [ ] 存档、读档 - 高级设计 diff --git a/bin/opt.o b/bin/opt.o new file mode 100644 index 0000000000000000000000000000000000000000..4c969ae8571ae53d782c6cfaf941943754ce32f0 Binary files /dev/null and b/bin/opt.o differ diff --git a/include/map.h b/include/map.h new file mode 100644 index 0000000000000000000000000000000000000000..1596a127178ea0006cb7b6c188fa6fc688c5d0a3 --- /dev/null +++ b/include/map.h @@ -0,0 +1,11 @@ +#pragma once + +#include "mine_map.h" + +/** + * @brief 设置一个的雷 + * + * @param mode 难易度 + * @return map* 生成的地图的指针 + */ +map* Setmine(int mode); \ No newline at end of file diff --git a/include/mine_map.h b/include/mine_map.h new file mode 100644 index 0000000000000000000000000000000000000000..d07856f5942ee7174b9aece998d5e03f5895d3ed --- /dev/null +++ b/include/mine_map.h @@ -0,0 +1,49 @@ +#pragma once + +#define UNCOVERED 0 +#define COVERED 1 +#define FLAGED 2 +#define MARKED 3 + +/** + * @brief 扫雷地图 + * mx,my地图长宽 + * mineMap[i][j]=1 表示第i行第j列为雷 + * mode 表示困难度 + * stage[i][j] 表示地图显示状态 + * cnt 表示雷的总数 + * autobook 用于自动打开的数组 + */ +typedef struct map{ + int mineMap[105][105]; + int mx, my; + int mode; + int stage[105][105]; + int cnt; + int autobook[105][105]; +}map; + +#define ROW_1 10 +#define COL_1 10 +#define ROW_2 ROW_1 + 2 +#define COL_2 COL_1 + 2 +#define MINECOUNT 9 + +#define MODE_EASY 1 +#define MODE_MID 2 +#define MODE_HARD 3 + +#define MX_EASY 9 +#define MX_MID 16 +#define MX_HARD 16 + +#define MY_EASY 9 +#define MY_MID 16 +#define MY_HARD 30 + +#define NUM_EASY 10 +#define NUM_MID 40 +#define NUM_HARD 99 + + + diff --git a/include/opt.h b/include/opt.h new file mode 100644 index 0000000000000000000000000000000000000000..fd1a83b776233ba55101622e0f33942d0f56141f --- /dev/null +++ b/include/opt.h @@ -0,0 +1,124 @@ +#pragma once +#include "mine_map.h" +#include + +/** + * @brief define status after click + * BOOM Indicates thunder + * UNALLOWED indicates that the behavior is not allowed + * ALLOWED indicates that the lattice was successfully opened + */ +#define BOOM 0 +#define UNALLOWED 1 +#define ALLOWED 2 + +/** + * @brief define Mouse Action + * + */ +#define OPT_LEFT_CLICK 1 +#define OPT_MID_CLICK 2 +#define OPT_RIGTH_CLICK 3 +#define OPT_TOTAL_CLICK 4 +/** + * @brief 用于数周围有多少个雷 + * + * @param map + * @param x + * @param y + * @return int 返回周围雷的数量 + */ + +/** + * @brief 单次操作数据 + * + */ +typedef struct +{ + int x,y; + int mode; +}opt_t; + +/** + * @brief 统计周围雷数量 + * + * @param map + * @param x + * @param y + * @return int + */ +int opt_count(map *map, int x, int y); +/** + * @brief 单次鼠标操作 + * + * @param m 地图 + * @param opt 操作数据,包含坐标,操作类型等信息 + * @return int 操作后状态 + */ +int opt(map* m, opt_t opt); + +/** + * @brief 鼠标左击 + * + * @param x + * @param y + * @param m 指向地图的一个指针 + * @return int 当次操作状态 + */ +int fnOptLeftClick(int x,int y,map *m); + +/** + * @brief 鼠标右击 + * + * @param x + * @param y + * @param m 指向地图的一个指针 + * @return int 当次操作状态 + */ +int fnOptRightClick(int x,int y,map *m ); + +/** + * @brief 鼠标中击 + * + * @param x + * @param y + * @param m 指向地图的一个指针 + * @return int 当次操作状态 + */ +int fnOptMidClick(int x,int y,map *m); + +/** + * @brief 用于自动展开地图 + * + * @param x + * @param y + * @param m 地图指针 + */ +void fnOptAuto(int x,int y, map *m); + +/** + * @brief 用于统计周围旗子数量 + * + * @param map + * @param x + * @param y + * @return int 旗子数量 + */ +int opt_flag_count(map* map, int x, int y); + +/** + * @brief 用于判断是否扫雷成功 + * + * @param m + * @return true + * @return false + */ +bool opt_is_scuess(map m); + +/** + * @brief 如果全部雷标记 打开剩余格子 + * + * @param m + * @return int + */ +int fnTotalFlag(map *m); \ No newline at end of file diff --git a/log/team.txt b/log/team.txt new file mode 100644 index 0000000000000000000000000000000000000000..83115bf43b178ca5606652f60386465ea2c72f94 --- /dev/null +++ b/log/team.txt @@ -0,0 +1,5 @@ +map +record +opt +ui + diff --git a/pullTest/pull b/pullTest/pull deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/app.c b/src/app.c new file mode 100644 index 0000000000000000000000000000000000000000..7fc4a82046aa3a53292bc132e4ca46a719dfa5d5 --- /dev/null +++ b/src/app.c @@ -0,0 +1,2 @@ +#include "../include/map.h" + diff --git a/src/map.c b/src/map.c new file mode 100644 index 0000000000000000000000000000000000000000..4ba224cef129a1c9f0773f8c14bec5a52a65f0a4 --- /dev/null +++ b/src/map.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include "../include/map.h" +#include "../include/mine_map.h" + + +map *Setmine(int mode) +{ + map *Map = malloc(sizeof(map)); + if (Map == NULL) + return NULL; + switch (mode) + { + case MODE_EASY: + Map->mx = MX_EASY; + Map->my = MY_EASY; + Map->cnt = NUM_EASY; + break; + case MODE_MID: + Map->mx = MX_MID; + Map->my = MY_MID; + Map->cnt = NUM_MID; + break; + case MODE_HARD: + Map->mx = MX_HARD; + Map->my = MY_HARD; + Map->cnt = NUM_HARD; + break; + default: + break; + } + int cnt = 0; + srand((unsigned int)time(0)); + while (cnt < Map->cnt) + { + int x, y; + x = (rand() % (Map->mx)) + 1; + y = (rand() % (Map->my)) + 1; + if (Map->mineMap[x][y] == 0) + { + Map->mineMap[x][y] = 1; + cnt++; + } + } + return Map; +} diff --git a/src/opt.c b/src/opt.c new file mode 100644 index 0000000000000000000000000000000000000000..7494e29d0a2bd549b289bbf0d1e8e05e350fcc95 --- /dev/null +++ b/src/opt.c @@ -0,0 +1,226 @@ +#include "../include/mine_map.h" +#include "../include/opt.h" +#include + +int opt(map *m, opt_t opt) +{ + /** + * @brief 操作类型 + * + */ + int optMode; + /** + * @brief 操作坐标 + * + */ + int optX, optY; + optX = opt.x; + optY = opt.y; + optMode = opt.mode; + if (optX < 1 || optX > m->mx || optY < 1 || optY > m->my) + return UNALLOWED; + switch (optMode) + { + case OPT_LEFT_CLICK: + return fnOptLeftClick(optX, optY, m); + break; + case OPT_MID_CLICK: + return fnOptMidClick(optX, optY, m); + break; + case OPT_RIGTH_CLICK: + return fnOptRightClick(optX, optY, m); + break; + case OPT_TOTAL_CLICK: + return fnTotalFlag(m); + break; + default: + return UNALLOWED; + break; + } +} + +int opt_count(map *map, int x, int y) +{ + int cnt = 0; + for (int i = x - 1; i <= x + 1; i++) + { + for (int j = y - 1; j <= y + 1; j++) + { + if (i < 1 || j < 1 || i > map->mx || j > map->my) + continue; + if (i == x && j == y) + continue; + if (map->mineMap[i][j] == 1) + cnt++; + } + } + return cnt; +} + +int opt_flag_count(map *map, int x, int y) +{ + int cnt = 0; + for (int i = x - 1; i <= x + 1; i++) + { + for (int j = y - 1; j <= y + 1; j++) + { + if (i < 1 || j < 1 || i > map->mx || j > map->my) + continue; + if (i == x && j == y) + continue; + if (map->stage[i][j] == FLAGED) + cnt++; + } + } + return cnt; +} + +int fnOptLeftClick(int x, int y, map *m) +{ + /** + * @brief 地图当前状态 + * + */ + int map_stage; + + map_stage = m->stage[x][y]; + /** + * @brief 判断当前格子是否是雷 + * + */ + bool map_mine; + map_mine = (m->mineMap[x][y] == 1) ? true : false; + /** + * @brief 左键实现 + * 如果当前格子被标记或者已经打开 + * 返回UNALLOWED + */ + if (map_stage == FLAGED || map_stage == COVERED || map_stage == MARKED) + return UNALLOWED; + + if (map_mine == true) + { + m->stage[x][y] = COVERED; + return BOOM; + } + + m->stage[x][y] = COVERED; + if (opt_count(m, x, y) == 0) + fnOptAuto(x, y, m); + return ALLOWED; +} + +int fnOptRightClick(int x, int y, map *m) +{ + + /** + * @brief 地图当前状态 + * + */ + int map_stage; + + map_stage = m->stage[x][y]; + switch (map_stage) + { + case COVERED: + return UNALLOWED; + break; + case UNCOVERED: + m->stage[x][y] = FLAGED; + break; + case FLAGED: + m->stage[x][y] = MARKED; + break; + case MARKED: + m->stage[x][y] = UNCOVERED; + break; + default: + return ALLOWED; + break; + } +} + +int fnOptMidClick(int x, int y, map *m) +{ + /** + * @brief 地图当前状态 + * + */ + int map_stage; + map_stage = m->stage[x][y]; + if (map_stage != COVERED) + return UNALLOWED; + if (opt_count(m, x, y) != opt_flag_count(m, x, y)) + return UNALLOWED; + fnOptAuto(x, y, m); + return ALLOWED; +} + +void fnOptAuto(int x, int y, map *m) +{ + + for (int i = -1; i <= 1; i++) + { + for (int j = -1; j <= 1; j++) + { + int fx = x + i, fy = y + j; + if (i == 0 && j == 0) + continue; + if (fx < 1 || fx > m->mx || fy < 1 || fy > m->my) + continue; + if (m->stage[fx][fy] = UNCOVERED) + { + m->stage[fx][fy] == COVERED; + if (opt_count(m, fx, fy) == 0) + fnOptAuto(fx, fy, m); + } + } + } + return; +} + +bool opt_is_scuess(map m) +{ + /** + * @brief 扫雷成功条件 + * 打开所有不是雷的格子 + * + */ + int coverCnt = 0; + for (int i = 1; i <= m.mx; i++) + { + for (int j = 1; j <= m.my; j++) + { + if (m.stage[i][j] == COVERED) + coverCnt++; + } + } + if (coverCnt == (m.mx * m.my - m.cnt)) + return true; + else + return false; +} + +int fnTotalFlag(map *m) +{ + int flagCnt = 0; + for (int i = 1; i <= m->mx; i++) + for (int j = 1; j <= m->my; j++) + if (m->stage[i][j] == FLAGED) + flagCnt++; + if (flagCnt != m->cnt) + return UNALLOWED; + + for (int i = 1; i <= m->mx; i++) + { + for (int j = 1; j <= m->my; j++) + { + if (m->stage[i][j] != UNCOVERED) + continue; + m->stage[i][j] = COVERED; + if (m->mineMap[i][j] == 1) + return BOOM; + } + } + return ALLOWED; +} \ No newline at end of file diff --git a/test/app b/test/app new file mode 100644 index 0000000000000000000000000000000000000000..2ee2aa5e2b90c2f73659fce4b4390d7b12d71536 Binary files /dev/null and b/test/app differ diff --git a/test/make b/test/make new file mode 100644 index 0000000000000000000000000000000000000000..c3a60fa35747b0ee81680e485c11574a233eb3c3 --- /dev/null +++ b/test/make @@ -0,0 +1,4 @@ +main:map_test.o + gcc map.o map_test.o -o app +map_test.o:map_test.c + gcc -c map_test.c -o map_test.o \ No newline at end of file diff --git a/test/map_test.c b/test/map_test.c new file mode 100644 index 0000000000000000000000000000000000000000..4c157b57375f8bbe6fde02f4221a35ba66994790 --- /dev/null +++ b/test/map_test.c @@ -0,0 +1,41 @@ +#include "../include/map.h" +#include +int opt_count(map *map, int x, int y) +{ + int cnt = 0; + for (int i = x - 1; i <= x + 1; i++) + { + for (int j = y - 1; j <= y + 1; j++) + { + if (i < 1 || j < 1 || i > map->mx || j > map->my) + continue; + if (i == x && j == y) + continue; + if (map->mineMap[i][j] == 1) + cnt++; + } + } + return cnt; +} +void printmap(map m) +{ + for (int i = 1; i <= m.mx; i++) + { + for (int j = 1; j <= m.my; j++) + { + if(m.mineMap[i][j]==1) + printf("B"); + else + printf("%d",opt_count(&m, i,j)); + + } + printf("\n"); + } + return; +} + +int main() +{ + map* m = Setmine(MODE_HARD); + printmap(*m); +} \ No newline at end of file diff --git a/test/opt/3 2 2.txt b/test/opt/3 2 2.txt new file mode 100644 index 0000000000000000000000000000000000000000..04acc9d2b525975c1413066fd6de4b8056a668b5 --- /dev/null +++ b/test/opt/3 2 2.txt @@ -0,0 +1,2 @@ +3 2 2 +2 1 3 \ No newline at end of file diff --git a/test/opt/Tot.txt b/test/opt/Tot.txt new file mode 100644 index 0000000000000000000000000000000000000000..5a5a12d0b8db8e81c097d48cfb34443c913a3c1c --- /dev/null +++ b/test/opt/Tot.txt @@ -0,0 +1,6 @@ +3 1 1 +3 2 2 +3 3 3 +3 4 4 +3 5 5 +3 6 6 \ No newline at end of file diff --git a/test/opt/opt_test.c b/test/opt/opt_test.c new file mode 100644 index 0000000000000000000000000000000000000000..67587c82cb8d9f307a7321e8df11d775ab598aea --- /dev/null +++ b/test/opt/opt_test.c @@ -0,0 +1,315 @@ +#include +#include +#include +#include "../../lib/mine_map.h" +#include "../../lib/opt.h" + +#define DE printf("debug\n") + +map m; + +void initmap(map *m) +{ + m->mx = 6; + m->my = 6; + for (int i = 1; i <= 6; i++) + { + m->mineMap[i][i] = 1; + } + m->cnt = 6; +} +/** + * @brief 打印地图 + * + * @param m + * + * 未打开打印U + * 打开打印数字 + * 旗子打印F + * 标记打印? + */ +void printmap(map m) +{ + for (int i = 1; i <= m.mx; i++) + { + for (int j = 1; j <= m.my; j++) + { + if (m.mineMap[i][j] && m.stage[i][j] == COVERED) + { + printf("B"); + continue; + } + if (m.stage[i][j] == COVERED) + printf("%d", opt_count(&m, i, j)); + if (m.stage[i][j] == UNCOVERED) + printf("U"); + if (m.stage[i][j] == FLAGED) + printf("F"); + if (m.stage[i][j] == MARKED) + printf("?"); + } + printf("\n"); + } + return; +} +void printmine(map m) +{ + for (int i = 1; i <= m.mx; i++) + { + for (int j = 1; j <= m.my; j++) + { + printf("%d", opt_count(&m, i, j)); + } + printf("\n"); + } + return; +} +int main() +{ + initmap(&m); + // printmap(m); + // printmine(m); + fnOptAuto(1, 6, &m); + printmap(m); + int flag = 1; + while (flag) + { + opt_t tmp; + /** + * @brief #define OPT_LEFT_CLICK 1 + #define OPT_MID_CLICK 2 + #define OPT_RIGTH_CLICK 3 + * + */ + scanf("%d%d%d", &tmp.mode, &tmp.x, &tmp.y); + flag = opt(&m, tmp); + if (flag == UNALLOWED) + printf("ERROR OPPERATION\n"); + else + printmap(m); + if(opt_is_scuess(m)) + break; + } + return 0; +} +int opt(map *m, opt_t opt) +{ + /** + * @brief 操作类型 + * + */ + int optMode; + /** + * @brief 操作坐标 + * + */ + int optX, optY; + optX = opt.x; + optY = opt.y; + optMode = opt.mode; + if(optX<1||optX>m->mx||optY<1||optY>m->my) + return UNALLOWED; + switch (optMode) + { + case OPT_LEFT_CLICK: + return fnOptLeftClick(optX, optY, m); + break; + case OPT_MID_CLICK: + return fnOptMidClick(optX, optY, m); + break; + case OPT_RIGTH_CLICK: + return fnOptRightClick(optX, optY, m); + break; + case OPT_TOTAL_CLICK: + return fnTotalFlag(m); + break; + default: + return UNALLOWED; + break; + } +} + +int opt_count(map *map, int x, int y) +{ + int cnt = 0; + for (int i = x - 1; i <= x + 1; i++) + { + for (int j = y - 1; j <= y + 1; j++) + { + if (i < 1 || j < 1 || i > map->mx || j > map->my) + continue; + if (i == x && j == y) + continue; + if (map->mineMap[i][j] == 1) + cnt++; + } + } + return cnt; +} + +int opt_flag_count(map *map, int x, int y) +{ + int cnt = 0; + for (int i = x - 1; i <= x + 1; i++) + { + for (int j = y - 1; j <= y + 1; j++) + { + if (i < 1 || j < 1 || i > map->mx || j > map->my) + continue; + if (i == x && j == y) + continue; + if (map->stage[i][j] == FLAGED) + cnt++; + } + } + return cnt; +} + +int fnOptLeftClick(int x, int y, map *m) +{ + /** + * @brief 地图当前状态 + * + */ + int map_stage; + + map_stage = m->stage[x][y]; + /** + * @brief 判断当前格子是否是雷 + * + */ + bool map_mine; + map_mine = (m->mineMap[x][y] == 1) ? true : false; + /** + * @brief 左键实现 + * 如果当前格子被标记或者已经打开 + * 返回UNALLOWED + */ + if (map_stage == FLAGED || map_stage == COVERED || map_stage == MARKED) + return UNALLOWED; + + if (map_mine == true) + { + m->stage[x][y] = COVERED; + return BOOM; + } + m->stage[x][y] = COVERED; + if (opt_count(m, x, y) == 0) + fnOptAuto(x, y, m); + return ALLOWED; +} + +int fnOptRightClick(int x, int y, map *m) +{ + + /** + * @brief 地图当前状态 + * + */ + int map_stage; + DE; + map_stage = m->stage[x][y]; + switch (map_stage) + { + case COVERED: + return UNALLOWED; + break; + case UNCOVERED: + m->stage[x][y] = FLAGED; + break; + case FLAGED: + m->stage[x][y] = MARKED; + break; + case MARKED: + m->stage[x][y] = UNCOVERED; + break; + default: + return ALLOWED; + break; + } +} + +int fnOptMidClick(int x, int y, map *m) +{ + /** + * @brief 地图当前状态 + * + */ + int map_stage; + map_stage = m->stage[x][y]; + if (map_stage != COVERED) + return UNALLOWED; + if (opt_count(m, x, y) != opt_flag_count(m, x, y)) + return UNALLOWED; + fnOptAuto(x, y, m); + return ALLOWED; +} +void fnOptAuto(int x, int y, map *m) +{ + //DE; + if (m->autobook[x][y] == 1) + return; + m->autobook[x][y] = 1; + for (int i = -1; i <= 1; i++) + { + for (int j = -1; j <= 1; j++) + { + int fx = x + i, fy = y + j; + if (fx < 1 || fx > m->mx || fy < 1 || fy > m->my) + continue; + if (m->stage[fx][fy] == UNCOVERED) + { + // DE; + m->stage[fx][fy] = COVERED; + if (opt_count(m, fx, fy) == 0) + fnOptAuto(fx, fy, m); + } + } + } + return; +} + +bool opt_is_scuess(map m) +{ +/** + * @brief 扫雷成功条件 + * 打开所有不是雷的格子 + * + */ + int coverCnt = 0; + for(int i = 1;i<=m.mx;i++) + { + for(int j= 1;j<=m.my;j++) + { + if(m.stage[i][j]==COVERED) + coverCnt++; + } + } + printf("Cover = %d\n",coverCnt); + if(coverCnt==(m.mx*m.my-m.cnt)) + return true; + else + return false; +} +int fnTotalFlag(map *m) +{ + int flagCnt = 0; + for(int i = 1;i<=m->mx;i++) + for(int j = 1;j<=m->my;j++) + if(m->stage[i][j]==FLAGED) flagCnt++; + if(flagCnt!=m->cnt) + return UNALLOWED; + + for(int i = 1;i<=m->mx;i++) + { + for(int j = 1;j<=m->my;j++) + { + if(m->stage[i][j]!=UNCOVERED) + + continue; + m->stage[i][j] = COVERED; + if(m->mineMap[i][j]==1) return BOOM; + } + } + return ALLOWED; +} \ No newline at end of file diff --git a/test/opt/opt_test.exe b/test/opt/opt_test.exe new file mode 100644 index 0000000000000000000000000000000000000000..c3f75313431195cb87425e6c9578c577859b0fb9 Binary files /dev/null and b/test/opt/opt_test.exe differ diff --git a/test/opt/tempCodeRunnerFile.c b/test/opt/tempCodeRunnerFile.c new file mode 100644 index 0000000000000000000000000000000000000000..24e0fec72289955b8723efae9cdda904b52c6454 --- /dev/null +++ b/test/opt/tempCodeRunnerFile.c @@ -0,0 +1 @@ +printf \ No newline at end of file diff --git a/test/test b/test/test new file mode 100644 index 0000000000000000000000000000000000000000..6486ab2bce4b552dc86564c761131d5d4453cc07 Binary files /dev/null and b/test/test differ