C语言项目合集
五子棋
#include <stdio.h>
#include <getch.h>
#include <stdbool.h>
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, 1, -1};
char g[25][25];
void print() {
system("clear");
for (int i = 0; i < 15; ++i) {
for (int j = 0; j < 15; ++j) {
printf("%c ", g[i][j]);
}
puts("");
}
}
bool win(int x, int y, char c) {
int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
for (int i = -2; i <= 2; ++i) if (x + i >= 0 && x + i < 15) {
c1 += g[x + i][y] == c;
}
for (int i = -2; i <= 2; ++i) if (y + i >= 0 && y + i < 15) {
c2 += g[x][y + i] == c;
}
for (int i = -2; i <= 2; ++i) if (y + i >= 0 && y + i < 15 && x + i >= 0 && x + i < 15) {
c3 += g[x + i][y + i] == c;
}
for (int i = -2; i <= 2; ++i) if (x + i >= 0 && x + i < 15 && y - i <= 0 && y - i < 15) {
c4 += g[x + i][y - i] == c;
}
return c1 == 5 || c2 == 5 || c3 == 5 || c4 == 5;
}
bool check() {
for (int i = 0; i < 15; ++i) {
for (int j = 0; j < 15; ++j) if (g[i][j] != '*') {
if (win(i, j, g[i][j])) {
return false;
}
}
}
return true;
}
int main() {
memset(g, '*', sizeof g);
print();
int idx = 0, px = 1, py = 1;
while (check()) {
printf("\33[%d;%dH", px + 1, py * 2 + 2);
while (true) {
int get = getch() - 183;
if (get + 183 == 10) {
if (g[px][py] != '*') {
print();
printf("该位置上已经落子,请重下\n");
continue;
}
g[px][py] = '0' + idx % 2;
print();
break;
} else {
px += dx[get], py += dy[get];
if (px < 0) px = 0;
if (py < 0) py = 0;
if (px > 15) px = 14;
if (py > 15) py = 14;
}
printf("\33[%d;%dH", px + 1, py * 2 + 2);
}
idx += 1;
}
if (idx % 2 == 1) {
printf("黑子赢啦,共用%d步\n", idx / 2 + 1);
} else {
printf("白子赢啦,共用%d步\n", idx / 2);
}
}
2048
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <getch.h>
#include <string.h>
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, 1, -1};
int d[4][4];
bool ok = false;
void print() {
system("clear");
for (int i = 0; i < 9; ++i) {
if (i % 2 == 0) {
puts("-----------------------------");
} else {
for (int j = 0; j < 4; ++j) if (d[i / 2][j] != 0) {
printf("|%6d", d[i / 2][j]);
} else {
printf("| ");
}
printf("|\n");
}
}
}
bool check() {
int cnt = 0;
ok = false;
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
cnt += d[i][j] == 0;
for (int dir = 0; dir < 4; ++dir) {
int fx = i + dx[dir], fy = j + dy[dir];
if (fx >= 0 && fy >= 0 && fx < 4 && fy < 4 && d[fx][fy] == d[i][j] && d[i][j]) {
ok = true;
return true;
}
}
}
}
return cnt != 0;
}
void get() {
if (ok) {
return ;
}
int w = rand() % 2;
w = 1 << w + 1;
int x = rand() % 4, y = rand() % 4;
while (d[x][y] != 0) {
x = rand() % 4, y = rand() % 4;
}
d[x][y] = w;
}
int move() {
int dir = getch() - 183, score = 0;
int cpd[4][4], cp[4][4];
memcpy(cp, d, sizeof d);
if (dir == 0) {
for (int j = 0; j < 4; ++j) {
for (int k = 0; k < 4; ++k) {
for (int i = 1; i < 4; ++i) if (d[i - 1][j] == 0 && d[i][j]) {
d[i - 1][j] ^= d[i][j] ^= d[i - 1][j] ^= d[i][j];
}
}
}
memcpy(cpd, d, sizeof d);
for (int j = 0; j < 4; ++j) {
for (int i = 0; i < 4; ++i) {
int fx = dx[dir] + i, fy = dy[dir] + j;
if (fx >= 0 && fy >= 0 && fx < 4 && fy < 4 && cpd[fx][fy] == cpd[i][j] && cpd[fx][fy]) {
d[fx][fy] += d[i][j];
d[i][j] = 0;
score += d[fx][fy];
}
}
}
for (int j = 0; j < 4; ++j) {
for (int k = 0; k < 4; ++k) {
for (int i = 1; i < 4; ++i) if (d[i - 1][j] == 0 && d[i][j]) {
d[i - 1][j] ^= d[i][j] ^= d[i - 1][j] ^= d[i][j];
}
}
}
} else if (dir == 1) {
for (int j = 3; j >= 0; --j) {
for (int k = 0; k < 4; ++k) {
for (int i = 2; i >= 0; --i) if (d[i + 1][j] == 0 && d[i][j]) {
d[i + 1][j] ^= d[i][j] ^= d[i + 1][j] ^= d[i][j];
}
}
}
memcpy(cpd, d, sizeof d);
for (int j = 3; j >= 0; --j) {
for (int i = 3; i >= 0; --i) {
int fx = dx[dir] + i, fy = dy[dir] + j;
if (fx >= 0 && fy >= 0 && fx < 4 && fy < 4 && cpd[fx][fy] == cpd[i][j] && cpd[fx][fy]) {
d[fx][fy] += d[i][j];
d[i][j] = 0;
score += d[fx][fy];
}
}
}
for (int j = 3; j >= 0; --j) {
for (int k = 0; k < 4; ++k) {
for (int i = 2; i >= 0; --i) if (d[i + 1][j] == 0 && d[i][j]) {
d[i + 1][j] ^= d[i][j] ^= d[i + 1][j] ^= d[i][j];
}
}
}
} else if (dir == 2) {
for (int i = 3; i >= 0; --i) {
for (int k = 0; k < 4; ++k) {
for (int j = 2; j >= 0; --j) if (d[i][j + 1] == 0 && d[i][j]) {
d[i][j + 1] ^= d[i][j] ^= d[i][j + 1] ^= d[i][j];
}
}
}
memcpy(cpd, d, sizeof d);
for (int i = 3; i >= 0; --i) {
for (int j = 3; j >= 0; --j) {
int fx = dx[dir] + i, fy = dy[dir] + j;
if (fx >= 0 && fy >= 0 && fx < 4 && fy < 4 && cpd[fx][fy] == cpd[i][j] && cpd[fx][fy]) {
d[fx][fy] += d[i][j];
d[i][j] = 0;
score += d[fx][fy];
}
}
}
for (int i = 3; i >= 0; --i) {
for (int k = 0; k < 4; ++k) {
for (int j = 2; j >= 0; --j) if (d[i][j + 1] == 0 && d[i][j]) {
d[i][j + 1] ^= d[i][j] ^= d[i][j + 1] ^= d[i][j];
}
}
}
} else if (dir == 3) {
for (int i = 0; i < 4; ++i) {
for (int k = 0; k < 4; ++k) {
for (int j = 1; j < 4; ++j) if (d[i][j - 1] == 0 && d[i][j]) {
d[i][j - 1] ^= d[i][j] ^= d[i][j - 1] ^= d[i][j];
}
}
}
memcpy(cpd, d, sizeof d);
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
int fx = dx[dir] + i, fy = dy[dir] + j;
if (fx >= 0 && fy >= 0 && fx < 4 && fy < 4 && cpd[fx][fy] == cpd[i][j] && cpd[fx][fy]) {
d[fx][fy] += d[i][j];
d[i][j] = 0;
score += d[fx][fy];
}
}
}
for (int i = 0; i < 4; ++i) {
for (int k = 0; k < 4; ++k) {
for (int j = 1; j < 4; ++j) if (d[i][j - 1] == 0 && d[i][j]) {
d[i][j - 1] ^= d[i][j] ^= d[i][j - 1] ^= d[i][j];
}
}
}
}
ok = true;
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) if (cp[i][j] != d[i][j]) {
ok = false;
}
}
return score;
}
int main() {
srand(time(0));
get(), print();
int score = 0, idx = 0;
while (check()) {
idx += 1, score += move();
get(), print();
}
printf("游戏已经结束,您的得分是%d, 共用了%d步\n", score, idx);
}
电子通讯录
#include <stdio.h>
#include <stdbool.h>
#include <getch.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
char name[100][20], sex[100], tel[100][12];
size_t count = 0;
time_t sec = 2.2; // 提示信息显示时间
void clear_stdin() {
stdin->_IO_read_ptr = stdin->_IO_read_end;
}
char get_op(const char start, const char end) {
clear_stdin();
printf("请输入指定选项[%c,%c]\n", start, end);
while (true) {
char op = getch();
if (start <= op && op <= end) {
printf("%c\n", op);
return op;
}
}
}
char* get_str(char* str, size_t size) {
clear_stdin();
size_t len = strlen(fgets(str, size, stdin));
if (str[len - 1] == '\n') str[len - 1] = '\0';
return str;
}
char* sex_to_get(const char sex) {
if (sex == 'w' || sex == 'W') {
return "女";
} else if (sex == 'm' || sex == 'M') {
return "男";
}
return "性别未知";
}
char get_sex() {
clear_stdin();
printf("请输入性别(w女/m男):");
while (true) {
char sex = getch();
if ('w' == sex || 'W' == sex || 'm' == sex || 'M' == sex) {
printf("%s\n", sex_to_get(sex));
return sex;
}
}
}
void put_str(const char* msg, float sec) {
printf("%s\n", msg);
usleep(1000000 * sec);
}
void anykey_continue() {
clear_stdin();
printf("请按任意键继续...");
getch();
}
char menu() {
system("clear");
puts("===欢迎使用电子通讯录===");
puts("1、添加 2、删除");
puts("3、修改 4、查询");
puts("5、遍历 6、退出");
puts("========================");
return get_op('1', '6');
}
void add() {
if (count >= 100) {
put_str("通讯录人数已满!", sec);
return ;
}
for (int i = 0; i < 100; ++i) if (sex[i] == 0) {
printf("请输入新联系人姓名:");
get_str(name[i], sizeof name[0]);
sex[i] = get_sex();
printf("请输入新联系人电话:");
get_str(tel[i], sizeof tel[0]);
put_str("添加联系人成功!",sec);
count += 1;
return ;
}
}
void del() {
if (count == 0) {
put_str("通讯录为空!", sec);
return ;
}
char key[20];
printf("请输入想要删除的联系人姓名:");
get_str(key, sizeof key);
for (int i = 0; i < 100; ++i) if (sex[i]) {
if (strcmp(key, name[i])) {
printf("%s %s %s\n", name[i], sex_to_get(sex[i]), tel[i]);
sex[i] = 0;
count -= 1;
put_str("删除成功!", sec);
return ;
}
}
put_str("查无此人删除失败!", sec);
}
void modify() {
if (count == 0) {
put_str("通讯录为空!", sec);
return ;
}
char key[20];
printf("请输入想要修改的联系人姓名:");
get_str(key, sizeof key);
for (int i = 0; i < 100; ++i) if (sex[i]) {
if (strcmp(name[i], key) == 0) {
printf("请输入新的联系人姓名:");
get_str(name[i], sizeof name[0]);
sex[i] = get_sex();
printf("请输入新的联系人电话:");
get_str(tel[i], sizeof tel[0]);
put_str("修改联系人成功!",sec);
return ;
}
}
put_str("查无此人删除失败!", sec);
}
void query() {
char key[20];
printf("请输入要查询的关键字:");
get_str(key, sizeof key);
bool suc = false;
for (int i = 0; i < 100; ++i) if (sex[i]) {
if (strstr(name[i], key) != NULL && strstr(tel[i], key) != NULL) {
suc = true;
printf("%s %s %s\n", name[i], sex_to_get(sex[i]), tel[i]);
}
}
if (suc) {
anykey_continue();
} else {
put_str("查无此人!", sec);
}
}
void show() {
if (count == 0) {
put_str("暂无联系人...",sec);
return ;
}
for (int i = 0; i < 100; ++i) if (sex[i]) {
printf("%s %s %s\n", name[i], sex_to_get(sex[i]), tel[i]);
}
anykey_continue();
}
int main() {
while (true) {
int op = menu() - '0';
if (op == 1) {
add();
} else if (op == 2) {
del();
} else if (op == 3) {
modify();
} else if (op == 4) {
query();
} else if (op == 5) {
show();
} else {
break;
}
}
}
某个系统的用户管理模块
#include <stdio.h>
#include <getch.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
typedef struct User {
int id;
char name[20], password[21], phone[12];
} User;
User users[100];
size_t cnt;
time_t msg_show_sec = 20.2; // 提示信息显示时间
int lg_index; // 登录成功的下标
void clear_stdin() {
stdin->_IO_read_ptr = stdin->_IO_read_end;
}
char get_op(const char start, const char end) {
clear_stdin();
printf("请输入指定选项[%c,%c]\n", start, end);
while (true) {
char op = getch();
if (start <= op && op <= end) {
printf("%c\n", op);
return op;
}
}
}
char* get_str(char* str, size_t size) {
clear_stdin();
size_t len = strlen(fgets(str, size, stdin));
if (str[len - 1] == '\n') str[len - 1] = '\0';
return str;
}
char* get_passwd(char* pwd, size_t size, bool is_show) {
clear_stdin();
size_t index = 0;
while (index < size - 1) {
pwd[index] = getch();
if (pwd[index] == '\n') break;
if (pwd[index] == 127) {
if(index > 0) {
index--;
if(is_show) {
printf("\b \b");//抹除一个显示字符
}
}
continue;
}
if (is_show) {
printf("*");
}
index++;
}
pwd[index] = '\0';
printf("\n");
return pwd;
}
int get_id(int len) {
char* str = "0123456789";
int id = str[rand() % 9 + 1] - '0';
for (int i = 1; i < len; ++i) {
id = id * 10 + str[rand() % 10] - '0';
}
return id;
}
void put_str(const char* msg, float sec) {
printf("%s\n", msg);
usleep(1000000 * sec);
}
void anykey_continue() {
clear_stdin();
printf("请按任意键继续...");
getch();
}
int binary_search(int x) {
int l = 0, r = cnt - 1;
while (l < r) {
int mid = l + r >> 1;
if (users[mid].id < x) {
l = mid + 1;
} else {
r = mid;
}
}
return users[r].id == x ? r : -1;
}
void swap(User *x, User *y) {
User temp = *x;
*x = *y;
*y = temp;
}
void quick_sort(User *q, int l, int r) {
if (l >= r) return ;
int i = l - 1, j = r + 1;
int x = q[l + r >> 1].id;
while (i < j) {
do i++; while (q[i].id < x);
do j--; while (q[j].id > x);
if (i < j) swap(&q[i], &q[j]);
}
quick_sort(q, 1, j);
quick_sort(q, j + 1, r);
}
char menu() {
system("clear");
puts("============用户登录=============");
puts("1.用户注册 2.用户登录 ");
puts("3.重置密码 4.遍历所有用户");
puts("5.退出系统 ");
puts("=================================");
return get_op('1', '5');
}
void sign_user() {
if (cnt >= 100) {
put_str("系统正在升级,暂停注册!", msg_show_sec);
return;
}
while (true) {
users[cnt].id = get_id(8);
if (binary_search(users[cnt].id) == -1) {
break;
}
}
printf("请输入昵称:");
get_str(users[cnt].name,sizeof users[cnt].name);
printf("请输入手机号:");
get_str(users[cnt].phone,sizeof users[cnt].phone);
while (true) {
printf("请输入密码(6~19位):");
get_passwd(users[cnt].password, sizeof users[cnt].password, true);
size_t len = strlen(users[cnt].password);
if(6 > len) {
printf("密码长度不足6位,请重新输入\n");
} else break;
}
char pass_2[20] = {};
printf("请确认密码:");
get_passwd(pass_2, sizeof pass_2, true);
if (strcmp(users[cnt].password,pass_2) != 0) {
put_str("两次密码不同,注册失败\n", msg_show_sec);
return;
}
quick_sort(&users, 0, cnt);
cnt += 1;
anykey_continue();
}
char menu_login() {
system("clear");
printf("===========欢迎%s登录系统===========\n", users[lg_index].name);
puts("1.查看信息 2.修改信息");
puts("3.修改密码 4.退出登录");
return get_op('1', '4');
}
void show_user_info() {
printf("%d %s %s %s\n",
users[lg_index].id,
users[lg_index].name,
users[lg_index].password,
users[lg_index].phone);
anykey_continue();
}
void modify_user() {
puts("=====请输入要修改的信息=====");
puts("1.修改昵称 2.修改手机号");
if (get_op('1', '2') - '0' == 1) {
printf("请输入新的昵称:");
get_str(users[lg_index].name, sizeof users[lg_index].name);
} else {
printf("请输入新的手机号:");
get_str(users[lg_index].phone, sizeof users[lg_index].phone);
}
printf("修改后个人信息:\n");
show_user_info();
}
void modify_password() {
char pass[20];
printf("请输入旧密码:");
get_passwd(pass, sizeof pass, true);
if (strcmp(users[lg_index].password, pass)) {
put_str("密码验证失败,修改退出\n", msg_show_sec);
return;
}
printf("请输入新密码:");
get_passwd(pass, sizeof pass, true);
char repass[20];
printf("请确认密码:");
get_passwd(repass, sizeof repass, true);
if (0 == strcmp(pass, repass)) {
strcpy(users[lg_index].password, pass);
put_str("修改密码成功\n", msg_show_sec);
return;
}
put_str("两次密码不同,修改失败\n", msg_show_sec);
}
void login_suc() {
while (true) {
int op = menu_login() - '0';
if (op == 1) {
show_user_info();
} else if (op == 2) {
modify_user();
} else if (op == 3) {
modify_password();
} else break;
}
}
void login_user() {
int id = 0;
printf("请输入用户ID:");
clear_stdin();
scanf("%d", &id);
char pass[20];
printf("请输入用户密码;");
get_passwd(pass, sizeof pass, true);
int index = binary_search(id);
if (index >= 0 && strcmp(pass, users[index].password)) {
put_str("登录成功\n", msg_show_sec);
lg_index = index;
login_suc();
return;
}
put_str("用户ID或者密码错误,请检查\n", msg_show_sec);
}
void reset_user() {
clear_stdin();
int id;
printf("请输入用户ID:");
scanf("%d",&id);
char name[20];
printf("请输入用户昵称:");
get_str(name, sizeof name);
char phone[12];
printf("请输入用户手机号:");
get_str(phone,sizeof phone);
int index = binary_search(id);
if (index >= 0 && 0 == strcmp(users[index].name,name)
&& 0 == strcmp(users[index].phone,phone)) {
strcpy(users[index].password, "000000");
put_str("重置密码成功\n", msg_show_sec);
return;
}
put_str("数据信息有误,重置失败\n", msg_show_sec);
}
void show_user() {
if (cnt <= 0) {
puts("暂无普通用户!");
anykey_continue();
return ;
}
for (int i = 0; i < cnt; ++i) {
printf("ID:%d 昵称:%s \n", users[i].id, users[i].name);
}
anykey_continue();
}
int main() {
srand(time(NULL));
while (true) {
int op = menu() - '0';
if (op == 1) {
sign_user();
} else if (op == 2) {
login_user();
} else if (op == 3) {
reset_user();
} else if (op == 4) {
show_user();
} else break;
}
}
扫雷
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <getch.h>
#include <assert.h>
#include <stdbool.h>
#include <string.h>
// 地图
#define MAX_ROW 20
#define MAX_COL 30
int map[MAX_ROW][MAX_COL] = {};
#define OPEN 1000
#define MARK 100
// 根据data这个值来判断当前位置的状态
#define IS_INIT(data) (data >= -1 && data <= 8)
#define IS_OPEN(data) (data >= -1 + OPEN && data <= 8 + OPEN)
#define IS_MARK(data) (data >= -1 + MARK && data <= 8 + MARK)
enum Stat{INIT, PLAY, DEAD, SUCCESS};
enum Stat stat = INIT; // 游戏状态
// 实际的行列和雷数
int row = 16, col = 16, mines = 40;
#define MINE -1
// 记录光标在二维数组中的下标位置
int mx = 7, my = 7;
enum KEY {
KEY_OPEN = 10, // 用Enter键来表示打开或智能推导
KEY_SIGN = 32, // 用Space键来表示标记
KEY_QUIT = 'q', // q退出
KEY_UP = 183, // 上
KEY_DOWN = 184, // 下
KEY_RIGHT = 185, // 右
KEY_LEFT = 186 // 左
};
int aroundMines(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 >= 0 && i < row && j >= 0 && j < col) {
cnt += map[i][j] == MINE;
}
}
}
return cnt;
}
bool checkLayMines(int x, int y) {
if ((abs(x - mx) > 1 || abs(y - my) > 1) && map[x][y] != -1) return false;
return true;
}
void layMines() {
for (int i = 0; i < mines; ++i) {
int x, y;
do {
x = rand() % row, y = rand() % col;
} while (checkLayMines(x, y));
map[x][y] = MINE;
}
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) if (map[i][j] != MINE) {
map[i][j] = aroundMines(i, j);
}
}
}
void show_init_data() {
system("clear");
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
printf("%d ", map[i][j]);
}
printf("\n");
}
printf("\033[%d;%dH\033[0m", mx + 1, my * 2 + 1); // 屏幕的光标位置
}
int init_data(int data) {
if (IS_INIT(data)) {
return data;
}
if (IS_OPEN(data)) {
return data - OPEN;
}
return data - MARK;
}
void showPlay() {
system("clear");
int initCnt = 0, signCnt = 0;
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
// 根据情况显示
// 如果没有被打开显示#
// 这个位置如果用户标识地雷显示 &
// 如果这个位置被打开显示原始数据
if (IS_INIT(map[i][j])) {
printf("# ");
initCnt += 1;
} else if (IS_OPEN(map[i][j])) {
int data = init_data(map[i][j]);
if (data == MINE) {
printf("\033[31m* \033[0m");
} else if (data == 0) {
printf(" ");
} else {
printf("%d ", data);
}
} else {
signCnt += 1;
printf("& ");
}
}
printf("\n");
}
if (initCnt + signCnt == mines) {
stat = SUCCESS;
}
if (stat == SUCCESS) {
printf("恭喜你,press any key to restart...");
} else {
printf("\033[%d;%dH\033[0m", mx + 1, my * 2 + 1); // 屏幕的光标位置
}
}
void showDead() {
system("clear");
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
int data = init_data(map[i][j]);
if (IS_OPEN(map[i][j])) {
if (data == MINE) {
printf("\033[31;44m* \033[0m");
} else if (data == 0) {
printf(" ");
} else {
printf("%d ", data);
}
} else if (IS_MARK(map[i][j])) {
if (data == MINE) {
printf("& ");
} else {
printf("\033[31;45m& \033[0m");
}
} else {
if (data == MINE) {
printf("\033[31m* \033[0m");
} else {
printf("# ");
}
}
}
printf("\n");
}
printf("Sorry, You Fail! Pess any key to restart...\n");
printf("\033[%d;%dH\033[0m", mx + 1, my * 2 + 1); // 屏幕的光标位置
}
void autoOpen(int x, int y) {
assert(x >= 0 && x < row && y >= 0 && y < col);
if (!IS_INIT(map[x][y])) return ;
map[x][y] += OPEN;
if (init_data(map[x][y]) != 0) return ;
for (int i = x - 1; i <= x + 1; ++i) {
for (int j = y - 1; j <= y + 1; ++j) {
if (i >= 0 && i < row && j >= 0 && j < col) {
autoOpen(i, j);
}
}
}
}
// 统计(x, y)周围玩家雷的数量
int aroundSignMines(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 >= 0 && i < row && j >= 0 && j < col) {
cnt += IS_MARK(map[i][j]);
}
}
}
return cnt;
}
void openAround(int x, int y) {
for (int i = x - 1; i <= x + 1; ++i) {
for (int j = y - 1; j <= y + 1; ++j) {
if (i >= 0 && i < row && j >= 0 && j < col && IS_INIT(map[i][j])) {
if (map[i][j] == 0) {
autoOpen(i, j);
} else {
if (map[i][j] == MINE) { // 根据错误标记推导,打开了雷
stat = DEAD;
}
map[i][j] += OPEN;
}
}
}
}
}
void smartDeviration(int x, int y) {
int signCnt = aroundSignMines(x, y); // 标记地雷的数量
int mineCnt = init_data(map[x][y]);
if (signCnt >= mineCnt) {
openAround(x, y);
}
}
void open() {
if (stat == INIT) {
layMines();
stat = PLAY;
open();
}
if (IS_INIT(map[mx][my])) {
if (map[mx][my] == 0) {
autoOpen(mx, my);
} else {
if (map[mx][my] == MINE) {
stat = DEAD;
}
map[mx][my] += OPEN;
}
} else if (IS_OPEN(map[mx][my])) {
smartDeviration(mx, my);
}
}
void sign() {
if (IS_INIT(map[mx][my])) {
map[mx][my] += MARK;
} else if (IS_MARK(map[mx][my])) {
map[mx][my] -= MARK;
}
}
// 扫雷
void sweepMine() {
while (true) {
if (stat == PLAY || stat == INIT) {
showPlay();
if (stat == SUCCESS) return ;
} else if (stat == DEAD) {
showDead(); // 显示死亡地图
getch();
return ;
}
int key = getch();
if (key == KEY_OPEN) {
open();
} else if (key == KEY_SIGN) {
sign();
} else if (key == KEY_QUIT) {
exit(0);
} else {
if (key == KEY_UP) {
mx -= mx > 0;
} else if (key == KEY_DOWN) {
mx += mx + 1 < row;
} else if (key == KEY_LEFT) {
my -= my > 0;
} else if (key == KEY_RIGHT) {
my += my + 1 < col;
}
}
}
}
void run() {
while (true) {
stat = INIT;
sweepMine();
memset(map, 0, sizeof map);
}
}
int main() {
srand(time(NULL));
run();// 程序启动
}
推箱子
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <getch.h>
// 关卡数量
#define MAX_LEVEL 3
// 文件名最大长度
#define FILE_NAME_LEN 128
// 地图最大行和列
#define MAX_ROW 15
#define MAX_COL 15
enum BT {
ROAD = 0, // 可以自由行走的路 空白
WALL = 1, // 障碍物 墙
TERM = 2, // 终点 箱子最终要被推放的位置
MOUSE = 3, // 小老鼠 控制小老鼠移动
BOX = 4, // 箱子
// 特殊的物体
MINT = MOUSE + TERM, // 小老鼠站在终点上
BINT = BOX + TERM // 箱子被推到终点上
};
// 键值
enum KEY {
KEY_UP = 183, // 上
KEY_DOWN = 184, // 下
KEY_RIGHT = 185, // 右
KEY_LEFT = 186, // 左
KEY_RESET = 'r', // 复位
KEY_QUIT = 'q', // 退出
KEY_BACK = 'b' // 撤销最新的那一步动作
};
// 枚举类型,用来记录按下一个方向键后可能出现的三种情况
enum ActSts {
NOTM = -1, // 没有任何东西移动
ONLYM = 0, // 只有小老鼠移动
ALLM = 2 // 小老鼠和箱子都移动了
};
typedef struct Act {
int key; // key 移动的方向
int bm; // bm箱子是否移动
} Act;
// 实际当前地图实际的大小
int row = 0, col = 0;
// 记录小老鼠的坐标位置
int mx = 0, my = 0;
// 地图的数据
int map[MAX_ROW][MAX_COL] = {};
// 箱子的个数
int bcnt = 0;
// 撤销动作时 数据
#define MAX_BACK_STEP 10
Act acts[MAX_BACK_STEP] = {};
int backStep = 0; // 记录目前可以回退的步数
// 加载数据
void load(int level) {
bcnt = 0, backStep = 0;
char filename[FILE_NAME_LEN] = {};
// printf fprintf sprintf
sprintf(filename, "./map/%d.txt", level); // 格式化输出到字符串中
//puts(filename);
// 以只读方式打开文件
FILE* fp = fopen(filename, "r");
if (fp == NULL) {
printf("加载%s地图数据失败!\n", filename);
exit(-1); // 退出程序
}
// 读取文件中的数据
// 读取地图的尺寸(行和列)
if (fscanf(fp, "%d %d", &row, &col) < 2) {
printf("加载%s地图数据失败!\n", filename);
fclose(fp);
exit(-1);
}
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
fscanf(fp, "%d", &map[i][j]); // 读取文件中的数据
if (map[i][j] == BOX || map[i][j] == BINT) {
bcnt += 1;
}
if (map[i][j] == MOUSE || map[i][j] == MINT) {
mx = i, my = j;
}
}
}
fclose(fp);
}
// 每次显示地图的时候统计在终点上箱子的个数
int show() { // 打印数据
/* 原样打印
printf("row = %d, col = %d\n", row, col);
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
printf("%d%c", map[i][j], " \n"[j == col - 1]);
}
}
*/
system("clear");
int tbox = 0;
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
int op = map[i][j];
if (op == ROAD) {
printf(" ");
} else if (op == WALL) {
printf("#");
} else if (op == TERM) {
printf("O");
} else if (op == BINT || op == BOX) { // box in term
if (op == BOX) {
printf("@");
} else {
printf("\033[34m@\033[0m"); // \033开启颜色控制 30-39 字体颜色
tbox += 1;
}
} else if (op == MOUSE || op == MINT) { // mouse in term
if (op == MOUSE) {
printf("&");
} else {
printf("\033[31m&\033[0m"); // \033开启颜色控制 30-39 字体颜色
}
}
}
printf("\n");
}
return tbox;
}
// 移动函数 stepx, stepy方向增量
// NOTM ONLYM ALLM
int move(int stepx, int stepy) {
int nx = mx + stepx, ny = my + stepy;
// 所有地图最外面肯定有一圈墙 防止越界
if (map[nx][ny] == ROAD || map[nx][ny] == TERM) {
map[mx][my] -= MOUSE; // 小老鼠从(mx, my)离开
map[nx][ny] += MOUSE; // 小老鼠到达(nx, ny)位置
mx = nx, my = ny; // 重新记录小老鼠位置
return ONLYM; // 只有小老鼠移动了
} else if (map[nx][ny] == BOX || map[nx][ny] == BINT) {
// 需要考虑箱子前面的坐标
int nnx = nx + stepx, nny = ny + stepy;
// 老鼠推着箱子走
if (map[nnx][nny] == ROAD || map[nnx][nny] == TERM) {
map[nx][ny] -= BOX;
map[nnx][nny] += BOX;
map[mx][my] -= MOUSE;
map[nx][ny] += MOUSE;
mx = nx, my = ny;
return ALLM; // 小老鼠推着箱子移动
}
}
return NOTM; // 没有移动
}
void back(int stepx, int stepy, int bm) {
int ox = mx - stepx, oy = my - stepy;
map[mx][my] -= MOUSE; // 老鼠离开现在的位置
map[ox][oy] += MOUSE; // 老鼠回到原来的位置
if (bm == ALLM) { // 人和箱子都移动了
int bx = mx + stepx, by = my + stepy;
map[bx][by] -= BOX;
map[mx][my] += BOX;
}
mx = ox, my = oy;
}
void moveback() {
if (backStep > 0) {
backStep -= 1;
int key = acts[backStep].key, bm = acts[backStep].bm;
if (key == KEY_UP) {
back(-1, 0, bm);
} else if (key == KEY_DOWN) {
back(+1, 0, bm);
} else if (key == KEY_LEFT) {
back(0, -1, bm);
} else {
back(0, +1, bm);
}
}
}
// 玩游戏的过程
void play(int level) {
while (true) {
if (show() == bcnt) { // 1.显示地图
printf("恭喜你,通关了, press any key to next level...");
getch();
break;
}
// 玩家交互
int key = getch();
if (key == KEY_RESET) { // 复位
load(level); // 把地图数据重新加载
} else if (key == KEY_QUIT) { // 退出游戏
exit(-1);
} else if (key == KEY_BACK) { // 返回上一步
moveback();
} else {
int bm = NOTM; // 用于记录动作的结果
if (key == KEY_UP) {
bm = move(-1, 0);
} else if (key == KEY_DOWN) {
bm = move(+1, 0);
} else if (key == KEY_LEFT) {
bm = move(0, -1);
} else if (key == KEY_RIGHT) {
bm = move(0, +1);
}
if (bm != NOTM) { // 有效的动作
Act act = {key, bm};
// 把act有效动作放到全局数组中
if (backStep < MAX_BACK_STEP) {
acts[backStep++] = act;
} else {
for (int i = 1; i < MAX_BACK_STEP; ++i) {
acts[i - 1] = acts[i];
}
acts[MAX_BACK_STEP - 1] = act;
}
}
}
}
}
// 推箱子 游戏
void run() {
// 闯关形式的
for (int level = 1; level <= MAX_LEVEL; ++level) {
// 第level关
load(level); // 加载level关的地图数据 从文件中加载
play(level); // 供玩家i闯关
}
printf("恭喜闯关成功!\n");
}
// main函数作为程序的入口,一般都不会写业务代码
int main() {
run();
}
附1:#include "getch.h"头文件
#ifndef GETCH_H
#define GETCH_H
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
// 修改终端的控制方式,1取消回显、确认 2获取数据 3还原
static int getch(void)
{
// 记录终端的配置信息
struct termios old;
// 获取终端的配置信息
tcgetattr(STDIN_FILENO,&old);
// 设置新的终端配置
struct termios new_1 = old;
// 取消确认、回显
new_1.c_lflag &= ~(ICANON|ECHO);
// 设置终端配置信息
tcsetattr(STDIN_FILENO,TCSANOW,&new_1);
// 在新模式下获取数据
int key_val = 0;
do{
key_val += getchar();
}while(stdin->_IO_read_end - stdin->_IO_read_ptr);
// 还原配置信息
tcsetattr(STDIN_FILENO,TCSANOW,&old);
return key_val;
}
#endif//GETCH_H
附2:推箱子地图
地图下载