一、扫雷程序
头文件
#include <stdio.h>
#include <windows.h>
#define EASY_count 10 //简易难度下的雷的个数 设为10
#define ROW 9 //雷盘的行数
#define COL 9 //雷盘的列数
#define ROWS 11 //实际定义雷盘数组的行数和列数
#define COLS 11 //往大了定义是为了排查雷时不出现数组越界的情况
int win_s; //win_s用于记录标记了多少正确的的雷
//当win_s == EASY_count时,则游戏胜利
void game();
//初始化棋盘
void Intboard(char board[ROWS][COLS], int rows, int cols, char aim);
//打印棋盘
void Displayboard(char board[ROWS][COLS], int row, int col);
//布置雷
void Setmine(char board[ROWS][COLS], int row, int col);
//排查雷
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//优化排查雷
void get_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col, int* p);
//标记雷
void Setnote(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col);
具体函数
#define _CRT_SECURE_NO_WARNINGS
#include"源.h"
//初始化棋盘
void Intboard(char board[ROWS][COLS], int rows, int cols, char aim)
{
int a, b;
for (a = 0; a < rows; a++)
{
for (b = 0; b < cols; b++)
{
board[a][b] = aim;
}
}
}
//打印棋盘
void Displayboard(char board[ROWS][COLS], int row, int col)
{
int a, b;
for (a = 0; a <= col; a++)
{
if (a == 0)
printf(" ");
else
printf("%d ", a);
}
printf("\n");
for (a = 0; a <= col; a++)
{
if (a == 0)
printf(" ");
else
printf("%c ", 'v');
}
printf("\n");
for (a = 1; a <= row; a++)
{
printf("%d > ", a);
for (b = 1; b <= col; b++)
{
printf("%c ", board[a][b]);
}
printf("\n");
}
}
//布置雷
void Setmine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_count;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
//排查周围八格总计的雷数
static int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return mine[x - 1][y - 1] +
mine[x - 1][y] +
mine[x - 1][y + 1] +
mine[x][y - 1] +
mine[x][y + 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] - 8 * '0';
}
//游戏排查雷的主函数
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
//选择要进行排查雷或标记雷
//输入要排查的坐标或要标记的坐标
//判断输入的坐标是否合理
int x = 0, y = 0, flag = 0, note = 0, win = 0;
int* p = &win;
while (1)
{
printf("请选择要:0.排查雷 1.标记雷\n");
scanf("%d", ¬e);
switch (note)
{
case 0:
opt:
printf("请输入要排查的雷\n坐标(行号 列号):");
scanf("%d %d", &x, &y);
system("cls");
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
Displayboard(mine, row, col);
do
{
printf("输入0进行下一步操作:");
scanf("%d", &flag);
if (flag == 0)
goto exit;
else
{
printf("输入错误,请重新输入\n");
Displayboard(show, row, col);
}
Sleep(2500);
} while (flag);
break;
}
else
{
//用递归实现自动排查周围无雷的格子
get_mine(mine, show, x, y, row, col, p);
//显示排查的信息
Displayboard(show, row, col);
}
}
else
{
printf("坐标不合法,请重新输入\n");
Displayboard(show, row, col);
goto opt;
}
break;
case 1:
Setnote(mine, show, x, y, row, col);
break;
}
if (win == row * col - EASY_count || win_s == EASY_count)
{
printf("恭喜你,排雷成功\n");
win = 0;
win_s = 0;
Sleep(5000);
exit:
system("cls");
break;
}
}
}
//定义递归函数
void get_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col, int* p)
{
if (x > 0 && x <= row && y > 0 && y <= col)
{
int count = get_mine_count(mine, x, y);
if (count == 0)
{
(*p)++;
int a, b;
show[x][y] = '0';
for (a = -1; a <= 1; a++)
{
for (b = -1; b <= 1; b++)
{
if (show[x + a][y + b] == '*')
get_mine(mine, show, x + a, y + b, row, col, p);
}
}
}
else
{
(*p)++;
show[x][y] = count + '0';
}
}
}
//标记雷的函数定义
void Setnote(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col)
{
while (1)
{
printf("请输入要标记的雷的坐标:");
scanf("%d %d", &x, &y);
system("cls");
if (x >= 1 && x <= row && y >= 1 && y <= col && show[x][y] != '0' && show[x][y] != '1')
{
show[x][y] = '@';
if (mine[x][y] == '1')
win_s++;
break;
}
else
{
printf("输入坐标不合法,请重新输入\n");
Displayboard(show, row, col);
}
}
Displayboard(show, row, col);
}
主程序
#define _CRT_SECURE_NO_WARNINGS
#include"源.h"
void Description()
{
int n;
printf("欢迎来到C语言扫雷游戏,此处为游戏说明\n在游戏中,‘0’表示无雷,‘1’表示有雷\n");
printf("'*'表示未被排查的区域,‘@’表示自己所标记的雷的位置\n");
printf("如果您已悉知,请按‘任意键+回车键’确定正式进入游戏选择界面");
scanf("%d", &n);
system("cls");
}
void menu()
{
printf(" \n");
printf(" \n");
printf(" \n");
printf(" 扫雷游戏 \n");
printf(" 1.开始 \n");
printf(" 0.退出 \n");
printf(" \n");
printf(" \n");
printf(" \n");
}
void game()
{
Sleep(1000);
system("cls");
char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息
char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息
//初始化棋盘
Intboard(mine, ROWS, COLS, '0');
Intboard(show, ROWS, COLS, '*');
//打印棋盘
//Displayboard(mine, ROW, COL);用于检测雷是否正常布置
Displayboard(show, ROW, COL);
//布置雷
Setmine(mine, ROW, COL);
Displayboard(mine, ROW, COL);//必要时显示雷盘,便于测试
//排查雷
Findmine(mine, show, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
Description();
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
二、操作符
&按2进制位与:同1
|按2进制位或:同0,或1(有1就输出1)
^按2进制位异或:同0,异1
int main()
{
int a = 3;//补码00000000 00000000 00000000 00000011
int b = -6;// 10000000 00000000 00000000 00000110—>
//补码11111111 11111111 11111111 11111010
int c = a & b;//00000000 00000000 00000000 00000010
int d = a | b;//11111111 11111111 11111111 11111011—>101
int f = a ^ b;//11111111 11111111 11111111 11111001—>111
printf("c=%d\n", c);
printf("d=%d\n", d);
printf("f=%d\n", f);
return 0;
}
例题:不能创建临时变量,实现两个数的交换
int main()
{
int a = 3;
int b = 5;
printf("a=%d b=%d\n", a, b);
a = a + b;
b = a - b;
a = a - b;
printf("a=%d b=%d\n", a, b);
return 0;
}
异或支持交换律
3^3=000->a^a=0
0^5=101=5->0^a=a
3^3^5=5
3^5^3=101=5
int main()
{
int a = 3;
int b = 5;
printf("a=%d b=%d\n", a, b);
a = a ^ b;//3^5
b = a ^ b;//3^5^5=3
a = a ^ b;//3^5^3=5
printf("a=%d b=%d\n", a, b);
return 0;
}
求补码二进制中1的个数
int count_ones(int num) {
int count = 0;
unsigned int n = num; // 转换为无符号数,确保负数正确处理
while (n) {
count += n & 1; // 用位与取最低位(代替 n % 2)
n >>= 1; // 用右移一位(代替 n / 2)
}
return count;
}
int main() {
int num;
printf("请输入一个整数: ");
scanf("%d", &num);
printf("%d 的二进制补码中有 %d 个1\n", num, count_ones(num));
return 0;
}
~二进制取反
int main()
{
int a = 0; //00000000 00000000 00000000 00000000
printf("%d\n", ~a);//11111111 11111111 11111111 11111111—>补码—>原码—>10000000 00000000 00000000 00000001
int c = 5;
c <<= 1;//二进制左移1
printf("%d", ~c);
return 0;
}