bmp拼图游戏linux代码
时间: 2023-11-21 08:08:54 浏览: 137
拼图游戏的源代码
以下是一个简单的 BMP 拼图游戏的 Linux 代码示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include <linux/fb.h>
#include <sys/mman.h>
#define FB_DEVICE "/dev/fb0"
#define INPUT_DEVICE "/dev/input/event0"
#define BMP_FILE "./test.bmp"
struct fb_var_screeninfo var; // 变量存储屏幕信息
struct fb_fix_screeninfo fix; // 变量存储固定信息
char *fbp = NULL; // 变量存储映射的内存地址
int fd_fb, fd_input; // 设备文件描述符
struct point {
int x;
int y;
};
typedef struct {
unsigned short type;
unsigned int size;
unsigned short reserved1;
unsigned short reserved2;
unsigned int offset;
}__attribute__((packed)) bmp_file_header_t;
typedef struct {
unsigned int size;
int width;
int height;
unsigned short planes;
unsigned short bit_count;
unsigned int compression;
unsigned int image_size;
int x_px_per_meter;
int y_px_per_meter;
unsigned int colors_used;
unsigned int colors_important;
}__attribute__((packed)) bmp_info_header_t;
int read_bmp(char *filename, bmp_info_header_t *info_header, char **data)
{
bmp_file_header_t file_header;
int fd_bmp, ret;
fd_bmp = open(filename, O_RDONLY);
if (fd_bmp < 0) {
printf("Can't open file %s\n", filename);
return -1;
}
ret = read(fd_bmp, &file_header, sizeof(file_header));
if (ret < 0) {
printf("Can't read bmp file header\n");
close(fd_bmp);
return -1;
}
ret = read(fd_bmp, info_header, sizeof(*info_header));
if (ret < 0) {
printf("Can't read bmp info header\n");
close(fd_bmp);
return -1;
}
*data = malloc(info_header->image_size);
if (*data == NULL) {
printf("Can't allocate memory for data\n");
close(fd_bmp);
return -1;
}
ret = read(fd_bmp, *data, info_header->image_size);
if (ret < 0) {
printf("Can't read bmp data\n");
close(fd_bmp);
return -1;
}
close(fd_bmp);
return 0;
}
void draw_bmp(int x, int y, char *data, bmp_info_header_t *info_header)
{
int xres = var.xres, yres = var.yres;
int xstart = x, ystart = y;
int bpp = var.bits_per_pixel / 8;
char *fbp_offset = fbp + ystart * fix.line_length + xstart * bpp;
for (int i = 0; i < info_header->height; i++) {
memcpy(fbp_offset, data + (info_header->height - i - 1) * info_header->width * bpp, info_header->width * bpp);
fbp_offset += fix.line_length;
}
}
int get_input(struct input_event *ev)
{
int ret;
while (1) {
ret = read(fd_input, ev, sizeof(struct input_event));
if (ret < 0) {
printf("Can't read input event\n");
return -1;
}
if (ev->type == EV_KEY && ev->value == 1) {
break;
}
}
return 0;
}
int main(int argc, char *argv[])
{
bmp_info_header_t info_header;
char *data;
struct input_event ev;
struct point blank_pos, mouse_pos, clicked_pos;
int blank_num, clicked_num, count = 0;
srand(time(NULL));
fd_fb = open(FB_DEVICE, O_RDWR);
if (fd_fb < 0) {
printf("Can't open framebuffer device\n");
return -1;
}
if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var) < 0) {
printf("Can't get variable screen info\n");
close(fd_fb);
return -1;
}
if (ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix) < 0) {
printf("Can't get fixed screen info\n");
close(fd_fb);
return -1;
}
fbp = mmap(NULL, fix.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
if (fbp == MAP_FAILED) {
printf("Can't mmap framebuffer device\n");
close(fd_fb);
return -1;
}
fd_input = open(INPUT_DEVICE, O_RDONLY);
if (fd_input < 0) {
printf("Can't open input device\n");
return -1;
}
if (read_bmp(BMP_FILE, &info_header, &data) < 0) {
printf("Can't read bmp file\n");
return -1;
}
blank_pos.x = var.xres / 2 - info_header.width / 2;
blank_pos.y = var.yres / 2 - info_header.height / 2;
while (1) {
count++;
draw_bmp(blank_pos.x, blank_pos.y, data, &info_header);
blank_num = rand() % 15 + 1;
clicked_num = 0;
for (int i = 1; i <= 15; i++) {
if (i == blank_num) {
continue;
}
mouse_pos.x = (i - 1) % 4 * info_header.width / 4 + blank_pos.x;
mouse_pos.y = (i - 1) / 4 * info_header.height / 4 + blank_pos.y;
draw_bmp(mouse_pos.x, mouse_pos.y, data + (i - 1) * info_header.width * info_header.height / 16, &info_header);
if (get_input(&ev) < 0) {
printf("Game over\n");
goto end;
}
clicked_pos.x = ev.value % 4 * info_header.width / 4 + blank_pos.x;
clicked_pos.y = ev.value / 4 * info_header.height / 4 + blank_pos.y;
if (mouse_pos.x == clicked_pos.x && mouse_pos.y == clicked_pos.y) {
clicked_num = i;
}
}
if (clicked_num == 0) {
continue;
}
mouse_pos.x = (clicked_num - 1) % 4 * info_header.width / 4 + blank_pos.x;
mouse_pos.y = (clicked_num - 1) / 4 * info_header.height / 4 + blank_pos.y;
draw_bmp(mouse_pos.x, mouse_pos.y, data + (blank_num - 1) * info_header.width * info_header.height / 16, &info_header);
draw_bmp(blank_pos.x, blank_pos.y, data + (clicked_num - 1) * info_header.width * info_header.height / 16, &info_header);
blank_num = clicked_num;
blank_pos = mouse_pos;
if (count >= 100) {
printf("You win!\n");
goto end;
}
}
end:
munmap(fbp, fix.smem_len);
close(fd_fb);
close(fd_input);
return 0;
}
```
该代码使用了 Linux 的 framebuffer 设备和输入设备,需要以 root 权限运行。在游戏中,将一个完整的 BMP 图像分成 15 块,并进行打乱。玩家需要通过点击某块图像,将其移动到空白区域,最终还原整张图像。
阅读全文