Skip to content

Instantly share code, notes, and snippets.

@GoranM
Created October 18, 2013 22:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GoranM/7049155 to your computer and use it in GitHub Desktop.
Save GoranM/7049155 to your computer and use it in GitHub Desktop.
Column squish/packing demonstration.
// Column squish demo - Goran Milovanovic, 2013
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define ROWS 5
#define COLS 20
#define STR_COLS "20"
void* grid[ROWS][COLS];
void print_grid(){
int i, j;
char line[COLS + 1];
char* c;
line[COLS] = '\0';
for (i = 0; i < ROWS; ++i){
for (j = 0; j < COLS; ++j){
c = (char*)grid[i][j];
if (c)
line[j] = *c;
else
line[j] = ' ';
}
printf("%s\n", line);
}
memset(line, '=', COLS);
printf("%s\n", line);
}
void column_bust(int col){
int i;
for (i = 0; i < ROWS; ++i){
grid[i][col] = NULL;
}
}
void bust_columns(){
char buf[COLS];
scanf("%"STR_COLS"[^\n]", buf); // including whitespace
getchar(); // pop off remaining new-line
int i;
for (i = 0; buf[i] != '\0'; ++i){
switch (buf[i]){
case 'q':
exit(0);
break;
case ' ':
break;
default:
column_bust(i);
break;
}
}
}
int column_empty(int col){
int i;
for (i = 0; i < ROWS; ++i){
if (grid[i][col]){
return 0;
}
}
return 1;
}
void column_swap(int col_a, int col_b){
int i;
void* tmp;
for (i = 0; i < ROWS; ++i){
tmp = grid[i][col_a];
grid[i][col_a] = grid[i][col_b];
grid[i][col_b] = tmp;
}
}
void reform_horizontal(){
int done = 1;
int i;
for (i = 1; i < COLS; ++i){
if (!column_empty(i) && column_empty(i-1)){
done = 0;
column_swap(i, i-1);
}
}
sleep(1);
print_grid();
if (!done){
reform_horizontal();
}
}
int main(int argc, char* argv[]){
char fill = 'X';
int i, j;
for (i = 0; i < ROWS; ++i){
for (j = 0; j < COLS; ++j){
grid[i][j] = &fill;
}
}
print_grid();
while (1){
bust_columns();
print_grid();
reform_horizontal();
}
}
# Column squish demo - Goran Milovanovic, 2013
#
# requires pslab: https://github.com/GoranM/pslab
#
import pslab
import random
import time
class Block:
slab_empty = pslab.Slab(64, 64)
slab_stamp = pslab.Slab(62, 62)
color_slabs = []
for col in (0xFFFF00, 0x0055FF, 0x00FF55, 0xFF0000):
slab = pslab.Slab(64, 64)
slab_stamp.fill(col)
slab_stamp.burnInto(slab, 1, 1)
color_slabs.append(slab)
def __init__(self):
self.slab = random.choice(self.color_slabs)
class Grid(list):
def __init__(self):
self.dim = (8, 8)
super().__init__(
( [ Block() for j in range(self.dim[1]) ] for i in range(self.dim[0]) )
)
def burnInto(self, slab_dest):
for row in range(self.dim[0]):
for col in range(self.dim[1]):
block = self[row][col]
if block:
slab = block.slab
else:
slab = Block.slab_empty
slab.burnInto(slab_dest, col * slab.getWidth(), row * slab.getHeight())
def posToIdx(self, sx, sy):
slab = Block.slab_empty
return (sy // slab.getHeight(), sx // slab.getWidth())
def posValid(self, pos_grid):
for i, n in enumerate(pos_grid):
if n > self.dim[i] - 1 or n < 0:
return False
return True
if __name__ == "__main__":
window = pslab.Window(512, 512)
window.setTitle("Block Move")
window.fill(0xEEEEEE)
grid = Grid()
def render():
grid.burnInto(window)
window.update()
time.sleep(0.25)
render()
def clicked_gridcoord():
mx, my = mouse.getPosition()
row, col = grid.posToIdx(mx, my)
return (row, col)
def neighbor_coords(pos):
add = lambda a, b: (a[0] + b[0], a[1] + b[1])
offsets = ((-1, 0), (1, 0), (0, 1), (0, -1))
positions = (add(pos, o) for o in offsets)
return (p for p in positions if grid.posValid(p))
def bust(pos):
r, c = pos
grid[r][c] = None
def chain_bust(pos):
block = grid[pos[0]][pos[1]]
same_color = []
for p in neighbor_coords(pos):
neighbor = grid[p[0]][p[1]]
if neighbor and block and neighbor.slab == block.slab:
same_color.append(p)
bust(pos)
for p in same_color:
chain_bust(p)
def swap(pos_a, pos_b):
r, c = pos_a
_r, _c = pos_b
tmp = grid[r][c]
grid[r][c] = grid[_r][_c]
grid[_r][_c] = tmp
def reform_vertical():
rows_bottom_up = reversed(list(enumerate(grid)))
next(rows_bottom_up)
done = True
for r, row in rows_bottom_up:
for c, col in enumerate(row):
if grid[r][c] and not grid[r + 1][c]:
done = False
swap((r, c), (r + 1, c))
render()
if not done:
reform_vertical()
def column_empty(idx_col):
for row in grid:
if row[idx_col]:
return False
return True
def column_swap(idx_col_a, idx_col_b):
for idx_row in range(grid.dim[0]):
swap((idx_row, idx_col_a), (idx_row, idx_col_b))
def reform_horizontal():
done = True
for idx_col in range(1, grid.dim[1]):
if not column_empty(idx_col) and column_empty(idx_col - 1):
done = False
column_swap(idx_col, idx_col - 1)
render()
if not done:
reform_horizontal()
mouse = window.mouse
kb = window.keyboard
while True:
window.processEvents()
if mouse.btnHit("lmb"):
pos = clicked_gridcoord()
chain_bust(pos)
reform_vertical()
reform_horizontal()
if kb.keyHit("esc"):
break
time.sleep(1/30)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment