1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "pieces.h"
const int N_SHAPES = 17;
const struct piece SHAPES[] = {
{1, 1, "+"},
{1, 2, "++"},
{1, 3, "+++"},
{1, 4, "++++"},
{1, 5, "+++++"},
{2, 2, "+ +"}, // 2x2 diagonal
{2, 2, "++++"}, // 2x2 square
{2, 3, "++++ "}, // L shape
{2, 3, "++ ++"}, // Z shape
{2, 3, "+++ + "}, // T shape
{2, 3, "++++++"}, // 2x3 rectangle
{2, 4, "+++++ "}, // long L shape
{2, 4, "++++++++"}, // 2x4 rectangle
{3, 3, "++++ + "}, // large L shape
{3, 3, "+++ + + "}, // large T shape
{3, 3, "+ + +"}, // 3x3 diagonal
{3, 3, "+++++++++"}, // 3x3 square
};
void transpose(struct piece* pc) {
// transpose blocks
char* old = malloc(strlen(pc->blocks) + 1);
strcpy(old, pc->blocks); // before transposition
for (int r = 0; r < pc->h; r++) {
for (int c = 0; c < pc->w; c++) {
pc->blocks[c * (pc->h) + r] = old[r * (pc->w) + c];
}
}
free(old);
// swap dimensions
int h = pc->h;
pc->h = pc->w;
pc->w = h;
}
void rotate(struct piece* pc) {
// rotate `pc` ccw by 90 degrees
// transpose blocks
char* old = malloc(strlen(pc->blocks) + 1);
strcpy(old, pc->blocks); // before transposition
for (int r = 0; r < pc->h; r++) {
for (int c = 0; c < pc->w; c++) {
pc->blocks[(pc->w - c - 1) * (pc->h) + r] = old[r * (pc->w) + c];
}
}
free(old);
// swap dimensions
int h = pc->h;
pc->h = pc->w;
pc->w = h;
}
struct piece* randpiece() {
// select a random shape from `SHAPES`, make a copy where memory for `.blocks` is manually managed,
// then do random transformations to the copy
struct piece shape = SHAPES[rand() % N_SHAPES];
char* blocks = malloc(strlen(shape.blocks) + 1);
strcpy(blocks, shape.blocks);
struct piece* pc = malloc(sizeof(struct piece));
pc->h = shape.h;
pc->w = shape.w;
pc->blocks = blocks;
if (rand() % 2) transpose(pc);
for (int i = rand() % 4; i > 0; i--) // 0 to 3 times
rotate(pc);
return pc;
}
|