Morpion solitaire: Difference between revisions
Content added Content deleted
m (link to rules) |
(→{{header|C}}: reinterpreted rules when one position can complete multiple lines) |
||
Line 29: | Line 29: | ||
/* option: how long a line is. Options probably should have been made into |
/* option: how long a line is. Options probably should have been made into |
||
* commandline args, if I were not lazy. Also, if line_len is set to 3, |
|||
* the game may keep going indefinitely: best use auto mode. */ |
|||
int line_len = 5; |
int line_len = 5; |
||
/* option: whether two lines are allowed to be in the same direction and |
/* option: whether two lines are allowed to be in the same direction and |
||
* connected end to end. Note: two lines crossing are always ok. */ |
|||
int disjoint = |
int disjoint = 0; |
||
int **board = 0, width, height; |
int **board = 0, width, height; |
||
Line 49: | Line 49: | ||
s_dir_nw_se = 1 << 4, |
s_dir_nw_se = 1 << 4, |
||
s_newly_added = 1 << 5, |
s_newly_added = 1 << 5, |
||
s_current = 1 << 6, |
|||
}; |
}; |
||
Line 107: | Line 108: | ||
int i, j; |
int i, j; |
||
for_i for_j mvprintw(i + 1, j * 2, |
for_i for_j mvprintw(i + 1, j * 2, |
||
(board[i][j] & |
(board[i][j] & s_current) ? "X " |
||
: (board[i][j] & |
: (board[i][j] & s_newly_added) ? "O " |
||
⚫ | |||
refresh(); |
refresh(); |
||
} |
} |
||
Line 130: | Line 132: | ||
{1, 1, s_dir_nw_se} |
{1, 1, s_dir_nw_se} |
||
}; |
}; |
||
typedef struct { int m, s, seq, x, y; } move_t; |
|||
/* test if a point can complete a line, or take that point */ |
/* test if a point can complete a line, or take that point */ |
||
void test_postion(int y, int x, move_t * rec) |
|||
{ |
{ |
||
int m, k, s, dx, dy, xx, yy, dir; |
int m, k, s, dx, dy, xx, yy, dir; |
||
⚫ | |||
if (test_only) { |
|||
⚫ | |||
} else |
|||
⚫ | |||
for (m = 0; m < 4; m++) { /* 4 directions */ |
for (m = 0; m < 4; m++) { /* 4 directions */ |
||
Line 162: | Line 163: | ||
if (k != line_len) continue; |
if (k != line_len) continue; |
||
/* position ok |
/* position ok; irand() to even each option's chance of |
||
⚫ | |||
⚫ | |||
if (! irand(++rec->seq)) |
|||
rec->m = m, rec->s = s, rec->x = x, rec->y = y; |
|||
/* mark existing pieces for direction taken */ |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
} |
|||
} |
} |
||
} |
} |
||
} |
|||
return 0; |
|||
void add_piece(move_t *rec) { |
|||
int dx = ofs[rec->m][0]; |
|||
int dy = ofs[rec->m][1]; |
|||
int dir= ofs[rec->m][2]; |
|||
int xx, yy, k; |
|||
board[rec->y][rec->x] |= (s_current | s_occupied); |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
} |
|||
} |
} |
||
int next_move() |
int next_move() |
||
{ |
{ |
||
int i, j |
int i, j; |
||
move_t rec; |
|||
rec.seq = 0; |
|||
/* wipe last iteration's new line markers */ |
|||
for_i for_j board[i][j] &= ~s_newly_added; |
for_i for_j board[i][j] &= ~(s_newly_added | s_current); |
||
/* randomly pick one of next legal moves */ |
|||
for_i for_j |
|||
for_i for_j test_postion(i, j, &rec); |
|||
/* irand() ensures every legal move gets equal chance of |
|||
⚫ | |||
if (add_piece(j, i, 1) && !irand(++found)) |
|||
x = j, y = i; |
|||
/* didn't find any move, game over */ |
|||
if (x == -1) return 0; |
|||
⚫ | |||
add_piece( |
add_piece(&rec); |
||
x = (x == width - 1) ? 1 : x ? 0 : -1; |
rec.x = (rec.x == width - 1) ? 1 : rec.x ? 0 : -1; |
||
y = (y == height - 1) ? 1 : y ? 0 : -1; |
rec.y = (rec.y == height - 1) ? 1 : rec.y ? 0 : -1; |
||
if (x || y) expand_board(x, y); |
if (rec.x || rec.y) expand_board(rec.x, rec.y); |
||
return 1; |
return 1; |
||
} |
} |