📄 glpuzzle.c
字号:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <malloc.h>
#include <time.h>
#include <math.h>
#include <GL/glaux.h>
#define WIDTH 4
#define HEIGHT 5
#define PIECES 10
#define OFFSETX -2
#define OFFSETY -2.5
#define OFFSETZ -0.5
typedef char Config[HEIGHT][WIDTH];
struct puzzle {
struct puzzle *backptr;
struct puzzle *solnptr;
Config pieces;
struct puzzle *next;
unsigned hashvalue;
};
#define HASHSIZE 10691
struct puzzlelist {
struct puzzle *puzzle;
struct puzzlelist *next;
};
static char convert[PIECES + 1] = {0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4};
static unsigned char colors[PIECES + 1][3] =
{
{ 0, 0, 0},{255, 255, 127},{255, 255, 127},{255, 255, 127},
{255, 255, 127},{255, 127, 255},{255, 127, 255},{255, 127, 255},
{255, 127, 255},{255, 127, 127},{255, 255, 255}
};
static struct puzzle *hashtable[HASHSIZE];
static struct puzzle *startPuzzle;
static struct puzzlelist *puzzles;
static struct puzzlelist *lastentry;
int curX, curY, visible;
#define MOVE_SPEED 0.2
static unsigned char movingPiece;
static float move_x, move_y;
static float curquat[4];
static int doubleBuffer = 1;
static int depth = 1;
static char xsize[PIECES + 1] = {0,1,1,1,1,1,1,1,1,2,2};
static char ysize[PIECES + 1] = {0,1,1,1,1,2,2,2,2,1,2};
static float zsize[PIECES + 1] = {0.0f,1.0f,1.0f,1.0f,1.0f,1.0f,
1.0f,1.0f,1.0f,1.0f,0.6f};
static Config startConfig =
{
{8,10,10,7}, {8,10,10,7}, {6,9,9,5},{6,4,3,5}, {2,0,0,1}
};
static Config thePuzzle =
{
{8,10,10,7},{8,10,10,7},{6,9,9,5},{6,4,3,5},{2,0,0,1}
};
static int xadds[4] = {-1, 0, 1, 0};
static int yadds[4] = {0, -1, 0, 1};
static long W = 400, H = 300;
static GLint viewport[4];
unsigned hash(Config config)
{
int i, j, value;
value = 0;
for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < WIDTH; j++) {
value = value + convert[config[i][j]];
value *= 6;
}
}
return (value);
}
float boxcoords[][3] =
{
{0.2f, 0.2f, 0.9f}, {0.8f, 0.2f, 0.9f},
{0.8f, 0.8f, 0.9f}, {0.2f, 0.8f, 0.9f},
{0.2f, 0.1f, 0.8f}, {0.8f, 0.1f, 0.8f},
{0.9f, 0.2f, 0.8f}, {0.9f, 0.8f, 0.8f},
{0.8f, 0.9f, 0.8f}, {0.2f, 0.9f, 0.8f},
{0.1f, 0.8f, 0.8f}, {0.1f, 0.2f, 0.8f},
{0.2f, 0.1f, 0.2f}, {0.8f, 0.1f, 0.2f},
{0.9f, 0.2f, 0.2f}, {0.9f, 0.8f, 0.2f},
{0.8f, 0.9f, 0.2f}, {0.2f, 0.9f, 0.2f},
{0.1f, 0.8f, 0.2f}, {0.1f, 0.2f, 0.2f},
{0.2f, 0.2f, 0.1f}, {0.8f, 0.2f, 0.1f},
{0.8f, 0.8f, 0.1f}, {0.2f, 0.8f, 0.1f},
};
float boxnormals[][3] =
{
{0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f},
{1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f},
{0.0f, -1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f},
{0.7071f, 0.7071f, 0.0000f}, {0.7071f, -0.7071f, 0.0000f},
{-0.7071f, 0.7071f, 0.0000f}, {-0.7071f, -0.7071f, 0.0000f},
{0.7071f, 0.0000f, 0.7071f}, {0.7071f, 0.0000f, -0.7071f},
{-0.7071f, 0.0000f, 0.7071f}, {-0.7071f, 0.0000f, -0.7071f},
{0.0000f, 0.7071f, 0.7071f}, {0.0000f, 0.7071f, -0.7071f},
{0.0000f, -0.7071f, 0.7071f}, {0.0000f, -0.7071f, -0.7071f},
{0.5774f, 0.5774f, 0.5774f}, {0.5774f, 0.5774f, -0.5774f},
{0.5774f, -0.5774f, 0.5774f}, {0.5774f, -0.5774f, -0.5774f},
{-0.5774f, 0.5774f, 0.5774f}, {-0.5774f, 0.5774f, -0.5774f},
{-0.5774f, -0.5774f, 0.5774f},{-0.5774f, -0.5774f, -0.5774f},
};
int boxfaces[][4] =
{
{0, 1, 2, 3}, {9, 8, 16, 17},
{6, 14, 15, 7}, {20, 23, 22, 21},
{12, 13, 5, 4}, {19, 11, 10, 18},
{7, 15, 16, 8}, {13, 14, 6, 5},
{18, 10, 9, 17},{19, 12, 4, 11},
{1, 6, 7, 2}, {14, 21, 22, 15},
{11, 0, 3, 10}, {20, 19, 18, 23},
{3, 2, 8, 9}, {17, 16, 22, 23},
{4, 5, 1, 0}, {20, 21, 13, 12},
{2, 7, 8, -1}, {16, 15, 22, -1},
{5, 6, 1, -1}, {13, 21, 14, -1},
{10, 3, 9, -1}, {18, 17, 23, -1},
{11, 4, 0, -1}, {20, 12, 19, -1},
};
#define NBOXFACES (sizeof(boxfaces)/sizeof(boxfaces[0]))
/* Draw a box. Bevel as desired. */
void drawBox(int piece, float xoff, float yoff)
{
int xlen, ylen;
int i, k;
float x, y, z;
float zlen;
float *v;
xlen = xsize[piece];
ylen = ysize[piece];
zlen = zsize[piece];
glColor3ubv(colors[piece]);
glBegin(GL_QUADS);
for (i = 0; i < 18; i++) {
glNormal3fv(boxnormals[i]);
for (k = 0; k < 4; k++) {
if (boxfaces[i][k] == -1)
continue;
v = boxcoords[boxfaces[i][k]];
x = v[0] + OFFSETX;
if (v[0] > 0.5)
x += xlen - 1;
y = v[1] + OFFSETY;
if (v[1] > 0.5)
y += ylen - 1;
z = v[2] + OFFSETZ;
if (v[2] > 0.5)
z += zlen - 1;
glVertex3f(xoff + x, yoff + y, z);
}
}
glEnd();
glBegin(GL_TRIANGLES);
for (i = 18; i < NBOXFACES; i++) {
glNormal3fv(boxnormals[i]);
for (k = 0; k < 3; k++) {
if (boxfaces[i][k] == -1)
continue;
v = boxcoords[boxfaces[i][k]];
x = v[0] + OFFSETX;
if (v[0] > 0.5)
x += xlen - 1;
y = v[1] + OFFSETY;
if (v[1] > 0.5)
y += ylen - 1;
z = v[2] + OFFSETZ;
if (v[2] > 0.5)
z += zlen - 1;
glVertex3f(xoff + x, yoff + y, z);
}
}
glEnd();
}
float containercoords[][3] =
{
{-0.1f, -0.1f, 1.0f}, {-0.1f, -0.1f, -0.1f},
{4.1f, -0.1f, -0.1f}, {4.1f, -0.1f, 1.0f},
{1.0f, -0.1f, 0.6f}, {3.0f, -0.1f, 0.6f},
{1.0f, -0.1f, 0.0f}, {3.0f, -0.1f, 0.0f},
{1.0f, 0.0f, 0.0f}, {3.0f, 0.0f, 0.0f},
{3.0f, 0.0f, 0.6f}, {1.0f, 0.0f, 0.6f},
{0.0f, 0.0f, 1.0f}, {4.0f, 0.0f, 1.0f},
{4.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f},
{0.0f, 5.0f, 0.0f}, {0.0f, 5.0f, 1.0f},
{4.0f, 5.0f, 1.0f}, {4.0f, 5.0f, 0.0f},
{-0.1f, 5.1f, -0.1f}, {4.1f, 5.1f, -0.1f},
{4.1f, 5.1f, 1.0f}, {-0.1f, 5.1f, 1.0f},
};
float containernormals[][3] =
{
{0.0f, -1.0f, 0.0f}, {0.0f, -1.0f, 0.0f},
{0.0f, -1.0f, 0.0f}, {0.0f, -1.0f, 0.0f},
{0.0f, -1.0f, 0.0f}, {0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f}, {0.0f, 1.0f, 0.0f},
{1.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f},
{0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
};
int containerfaces[][4] =
{
{1, 6, 4, 0}, {0, 4, 5, 3},
{1, 2, 7, 6}, {7, 2, 3, 5},
{16, 19, 18, 17}, {23, 22, 21, 20},
{12, 11, 8, 15}, {10, 13, 14, 9},
{15, 16, 17, 12}, {2, 21, 22, 3},
{6, 8, 11, 4}, {1, 0, 23, 20},
{14, 13, 18, 19}, {9, 7, 5, 10},
{12, 13, 10, 11}, {1, 20, 21, 2},
{4, 11, 10, 5}, {15, 8, 19, 16},
{19, 8, 9, 14}, {8, 6, 7, 9},
{0, 3, 13, 12}, {13, 3, 22, 18},
{18, 22, 23, 17}, {17, 23, 0, 12},
};
#define NCONTFACES (sizeof(containerfaces)/sizeof(containerfaces[0]))
/* Draw the container */
void drawContainer(void)
{
int i, k;
float *v;
/* Y is reversed here because the model has it reversed */
/* Arbitrary bright wood-like color */
glColor3ub(209, 103, 23);
glBegin(GL_QUADS);
for (i = 0; i < NCONTFACES; i++) {
v = containernormals[i];
glNormal3f(v[0], -v[1], v[2]);
for (k = 3; k >= 0; k--) {
v = containercoords[containerfaces[i][k]];
glVertex3f(v[0] + OFFSETX, -(v[1] + OFFSETY), v[2] + OFFSETZ);
}
}
glEnd();
}
void drawAll(void)
{
int i, j;
int piece;
char done[PIECES + 1];
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -10);
glRotatef(180, 0, 0, 1);
if (depth) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
} else {
glClear(GL_COLOR_BUFFER_BIT);
}
for (i = 1; i <= PIECES; i++) {
done[i] = 0;
}
glLoadName(0);
drawContainer();
for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < WIDTH; j++) {
piece = thePuzzle[i][j];
if (piece == 0)
continue;
if (done[piece])
continue;
done[piece] = 1;
glLoadName(piece);
if (piece == movingPiece) {
drawBox(piece, move_x, move_y);
} else {
drawBox(piece, j, i);
}
}
}
}
void CALLBACK redraw(void)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, 1.0, 0.1, 100.0);
drawAll();
if (doubleBuffer)
auxSwapBuffers();
else
glFinish();
}
/* Checks if a space can move */
int canmove0(Config pieces, int x, int y, int dir, Config newpieces)
{
char piece;
int xadd, yadd;
int l, m;
xadd = xadds[dir];
yadd = yadds[dir];
if (x + xadd < 0 || x + xadd >= WIDTH ||
y + yadd < 0 || y + yadd >= HEIGHT)
return 0;
piece = pieces[y + yadd][x + xadd];
if (piece == 0)
return 0;
memcpy(newpieces, pieces, HEIGHT * WIDTH);
for (l = 0; l < WIDTH; l++) {
for (m = 0; m < HEIGHT; m++) {
if (newpieces[m][l] == piece)
newpieces[m][l] = 0;
}
}
xadd = -xadd;
yadd = -yadd;
for (l = 0; l < WIDTH; l++) {
for (m = 0; m < HEIGHT; m++) {
if (pieces[m][l] == piece) {
int newx, newy;
newx = l + xadd;
newy = m + yadd;
if (newx < 0 || newx >= WIDTH ||
newy < 0 || newy >= HEIGHT)
return 0;
if (newpieces[newy][newx] != 0)
return 0;
newpieces[newy][newx] = piece;
}
}
}
return 1;
}
/* Checks if a piece can move */
int canmove(Config pieces, int x, int y, int dir, Config newpieces)
{
int xadd, yadd;
xadd = xadds[dir];
yadd = yadds[dir];
if (x + xadd < 0 || x + xadd >= WIDTH ||
y + yadd < 0 || y + yadd >= HEIGHT)
return 0;
if (pieces[y + yadd][x + xadd] == pieces[y][x]) {
return canmove(pieces, x + xadd, y + yadd, dir, newpieces);
}
if (pieces[y + yadd][x + xadd] != 0)
return 0;
return canmove0(pieces, x + xadd, y + yadd, (dir + 2) % 4, newpieces);
}
int selectPiece(int mousex, int mousey)
{
long hits;
GLuint selectBuf[1024];
GLuint closest;
GLuint dist;
glSelectBuffer(1024, selectBuf);
(void) glRenderMode(GL_SELECT);
glInitNames();
/* Because LoadName() won't work with no names on the stack */
glPushName(-1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPickMatrix(mousex, H - mousey, 4, 4, viewport);
gluPerspective(45, 1.0, 0.1, 100.0);
drawAll();
hits = glRenderMode(GL_RENDER);
if (hits <= 0) {
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -