-
Notifications
You must be signed in to change notification settings - Fork 0
/
rletools.cpp
141 lines (120 loc) · 4.06 KB
/
rletools.cpp
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "rletools.h"
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
bool RLETools::saveToRLE(const QString &filename, const int* pCells, int rows, int cols, const std::vector<int> &birthRules, const std::vector<int> &survivalRules) {
QFile file(filename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return false;
QTextStream out(&file);
QString birthStr = "B";
for (int rule : birthRules) {
birthStr += QString::number(rule);
}
QString survivalStr = "S";
for (int rule : survivalRules) {
survivalStr += QString::number(rule);
}
out << "x = " << cols << ", y = " << rows << ", rule = " << birthStr << "/" << survivalStr << "\n";
for (int i = 0; i < rows; ++i) {
int count = 1;
for (int j = 0; j < cols; ++j) {
int cell = pCells[i * cols + j];
if (j == cols - 1 || pCells[i * cols + j + 1] != cell) {
if (cell == 1) {
if (count > 1) out << count;
out << "o";
} else {
if (count > 1) out << count;
out << "b";
}
count = 1;
} else {
count++;
}
}
out << "$\n";
}
out << "!";
return true;
}
bool RLETools::parseRule(const QString &ruleStr, std::vector<int> &birthRules, std::vector<int> &survivalRules) {
QStringList parts = ruleStr.split("/");
if (parts.size() != 2) {
return false;
}
QString birthStr = parts[0].mid(1);
QString survivalStr = parts[1].mid(1);
for (QChar ch : birthStr) {
if (ch.isDigit()) {
birthRules.push_back(ch.digitValue());
}
}
for (QChar ch : survivalStr) {
if (ch.isDigit()) {
survivalRules.push_back(ch.digitValue());
}
}
return true;
}
bool RLETools::loadFromRLE(const QString &filename, int* &pCells, int &rows, int &cols, std::vector<int> &birthRules, std::vector<int> &survivalRules) {
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return false;
QTextStream in(&file);
QString line;
// Skip char #
while (!in.atEnd()) {
line = in.readLine();
if (!line.startsWith("#")) break;
}
// parse x, y
QStringList parts = line.split(", ");
cols = parts[0].split("=")[1].toInt();
rows = parts[1].split("=")[1].toInt();
pCells = new int[rows * cols];
memset(pCells, 0, rows * cols * sizeof(int));
QString ruleStr = parts[2].split("=")[1].trimmed();
qDebug() << "load ruleStr: " << ruleStr;
if (parseRule(ruleStr, birthRules, survivalRules) != true) {
qDebug() << "load rule str failed.";
return false;
}
int x = 0, y = 0;
while (!in.atEnd()) {
line = in.readLine().trimmed();
if (line.startsWith("#")) continue;
int repeat = 0;
for (int i = 0; i < line.length(); ++i) {
QChar ch = line[i];
if (ch.isDigit()) {
repeat = repeat * 10 + ch.digitValue();
} else if (ch == 'o' || ch == 'b') {
int cellValue = (ch == 'o') ? 1 : 0;
repeat = (repeat == 0) ? 1 : repeat;
while (repeat) {
pCells[y * cols + x] = cellValue;
x++;
repeat--;
}
repeat = 0;
} else if (ch == '$') {
y += (repeat == 0) ? 1 : repeat;
x = 0;
repeat = 0;
} else if (ch == '!') {
// for (int i = 0; i < rows; i++) {
// QString rowStr = "row" + QString::number(i) + ": ";
// for (int j = 0; j < cols; j++) {
// rowStr += QString::number(pCells[i * cols + j]);
// }
// qDebug() << rowStr;
// }
return true;
}
}
}
return false;
}