SigilPlacer

前一阵子趁着Steam上《塔罗斯的法则》打折,玩了玩。不光是解谜,还有一些哲学的东西,游戏还有很多彩蛋,我挺喜欢的。《Sigils of Elohim》算是一个推广前者的一个免费游戏,主要就是给你一些方块,让你铺满给定的棋盘。很多人都说反向的是俄罗斯方块。在前者的流程中也包括一些这个拼图游戏,有些确实得需要一些时间才能试出来,玩了半天并不觉得这种东西有啥好的方法去解。于是就想着用Java编写一个解题的程序,写程序比完成拼图要有意思的多XD

拼图游戏

问题描述

现有若干不同种类的方块,请试着利用所给的方块将所给的棋盘铺满。

输入格式

一行正整数,依次代表棋盘的宽、棋盘的高、LL方块个数、LR方块个数、ZL方块个数、ZR方块个数、I方块个数、O方块个数、T方块个数。

名称与其所代表的方块入下:LL: ┏━、LR: ━┓、ZL: ┗┓、ZR: ┏┛、I: ━━━、O: ■、T: ┳。

输出格式

利用制表符,将放满方块的棋盘以文本形式输出,╳代表空白。

1
2
3
4
5
6
7
8
9
┏┳━━┳┓
┃┗━┓┃┃
┣━┳╋┛┃
┃┏┛┣━┫
┃┃┏┫╳┃
┣╋┛┗┳┫
┃┗┳━┛┃
┃┏┻━━┫
┗┻━━━┛

仿着算法题,简单说了一下我想要的效果,懒得给示例了,大家有兴趣也可以先自己试着写写看。

程序

共有四个文件:Brick、Main、Placer、Printer

这里主要说说具体解题和制表符输出的实现。

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
private void run(int x, int y) {
if (y == BOARD_Y) {
unfinished = false;
result = new Integer[BOARD_Y][BOARD_X];
return;
}
if (x == BOARD_X) {
run(0, y + 1);
return;
}
if (BOARD[y][x]) {
run(x + 1, y);
return;
}

for (Brick brick : BRICKS) {
if (NUM_OF_BRICKS[brick.ordinal()] == 0) {
continue;
}
for (int rotation = 0; rotation < brick.getNumOfShapes(); rotation++) {
if (canPlace(brick, rotation, x, y)) {
place(brick, rotation, x, y);
run(x + 1, y);
if (unfinished) {
remove(brick, rotation, x, y);
} else {
set(result, brick, rotation, x, y, index++);
return;
}
}
}
}
}

解题部分就是这个方法,是不是挺简单的,毕竟复杂的我也想不出来XD。说白了就是一个深度优先的遍历,假设当前情况下可以放A、B、C…种类的方块,每一种选择就是沿着选择向下延伸,当发现是死胡同时往上退一层,再选择其他的道路向下,这层的路都试完了再往上退,换个路向下。就这样上上下下,如果有解的话试出答案只是时间问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
     public static class Point {
private static final String[] CODE = new String[]{"╳", null, null, "┗", null, "┃", "┏", "┣", null, "┛", "━", "┻", "┓", "┫", "┳", "╋"};
private final byte code;

public Point(int ul, int ur, int dr, int dl) {
int temp = 0;
temp += ul == ur ? 0 : 1;
temp += ur == dr ? 0 : 2;
temp += dr == dl ? 0 : 4;
temp += dl == ul ? 0 : 8;
code = (byte) temp;
}

public String toString() {
return CODE[code];
}
}

变为制表符输出,画画图就好理解了。我们想要的效果就是不同的方块之间有线分开,再看制表符并不能单独画出一个格子的东西,而是其在四个格子的中心点,代表着这四个格子上方块的异同。如此一来利用上下左右四角的方块的ID就能得出上左右异同、右上下异同、下左右异同、左上下异同。相同就代表这俩格子中间没有线,相异就是有线,以有线为1、没线为0,按照顺序排列后这一点的类型就能用0000、0001、0010…1111这种二进制的方式表示,比较方便的实现了4个bool的组合对应到不同制表符的映射。

其他的话

东西没什么难度,不过做起来很好玩,所以也拿出来分享分享。不知还有没有什么改进的空间,现有的题目规模来说是不算慢的。

发现纯字符的表现能力也是不错的,毕竟字符不严格地讲也是画出来的。感觉比图形界面更好写,性能可能也更好,《塔罗斯的法则》中的文字游戏就很有意思,虽然主要是靠文案。感觉没UI纯文字的游戏应该也能挺有趣的。

今天(2023.10.15)TeaCon2023闭幕了。这代表着什么,礼物!自娱自乐的代码环节的额外收获,嘻嘻。




性感CC - 在线找打
------ 我是分割线 ------