Compare commits
2 commits
44576efaca
...
bb79e841e8
Author | SHA1 | Date | |
---|---|---|---|
bb79e841e8 | |||
38cb412fc8 |
5 changed files with 75 additions and 163 deletions
72
block.cpp
72
block.cpp
|
@ -6,15 +6,7 @@ Block::Block(int _depth, Rectangle trg) {
|
||||||
depth = _depth;
|
depth = _depth;
|
||||||
if(depth > 0)
|
if(depth > 0)
|
||||||
for(int i = 0; i < 9; i++)
|
for(int i = 0; i < 9; i++)
|
||||||
sons[i] = new Block( depth-1, get_son_rectangle(i) );
|
sons[i] = new Block( depth-1, get_son_rect(i) );
|
||||||
}
|
|
||||||
Rectangle Block::get_son_rectangle(int son) {
|
|
||||||
return {
|
|
||||||
float(int(place.x + place.width/3 * (son%3))),
|
|
||||||
float(int(place.y + place.height/3 * int(son/3))),
|
|
||||||
float(int(place.width/3)),
|
|
||||||
float(int(place.height/3))
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
int Block::set(tile pl) {
|
int Block::set(tile pl) {
|
||||||
t = pl;
|
t = pl;
|
||||||
|
@ -25,8 +17,10 @@ int Block::set(tile pl) {
|
||||||
bool Block::playable(deque<int> v) {
|
bool Block::playable(deque<int> v) {
|
||||||
if(depth == 0 && t == empty)
|
if(depth == 0 && t == empty)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if(t != empty || v.size() == 0)
|
if(t != empty || v.size() == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int son = v.front();
|
int son = v.front();
|
||||||
v.pop_front();
|
v.pop_front();
|
||||||
return sons[son]->playable(v);
|
return sons[son]->playable(v);
|
||||||
|
@ -47,13 +41,6 @@ int Block::play(deque<int> v, tile pl) {
|
||||||
return set(update());
|
return set(update());
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
bool Block::check_tie() {
|
|
||||||
bool is_tie = true;
|
|
||||||
for(Block* s : sons)
|
|
||||||
if(s->t == empty)
|
|
||||||
is_tie = false;
|
|
||||||
return is_tie;
|
|
||||||
}
|
|
||||||
tile Block::update() {
|
tile Block::update() {
|
||||||
tile d1 = sons[0]->t, d2 = sons[2]->t;
|
tile d1 = sons[0]->t, d2 = sons[2]->t;
|
||||||
for(int k = 0; k < 3; k++) {
|
for(int k = 0; k < 3; k++) {
|
||||||
|
@ -78,44 +65,41 @@ tile Block::update() {
|
||||||
if(d2 != empty)
|
if(d2 != empty)
|
||||||
return d2;
|
return d2;
|
||||||
|
|
||||||
if(check_tie())
|
// Check tie
|
||||||
|
bool is_tie;
|
||||||
|
for(Block* s : sons)
|
||||||
|
if(s->t == empty)
|
||||||
|
is_tie = false;
|
||||||
|
if(is_tie)
|
||||||
return tie;
|
return tie;
|
||||||
|
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
Rectangle Block::getRect(deque<int> v) {
|
|
||||||
|
|
||||||
|
void Block::update_rect(Rectangle trg) {
|
||||||
|
place = trg;
|
||||||
|
if(depth == 0)
|
||||||
|
return;
|
||||||
|
for(int i = 0; i < 9; i++)
|
||||||
|
sons[i]->update_rect(get_son_rect(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle Block::get_rect(deque<int> v) {
|
||||||
if(v.size() == 0)
|
if(v.size() == 0)
|
||||||
return place;
|
return place;
|
||||||
else {
|
else {
|
||||||
int index = v.front();
|
int index = v.front();
|
||||||
v.pop_front();
|
v.pop_front();
|
||||||
return sons[index]->getRect(v);
|
return sons[index]->get_rect(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Block::updateRect(Rectangle trg) {
|
|
||||||
place = trg;
|
|
||||||
if(depth == 0)
|
|
||||||
return;
|
|
||||||
for(int i = 0; i < 9; i++)
|
|
||||||
sons[i]->updateRect(get_son_rectangle(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Block::save(vector<tile> *r) {
|
Rectangle Block::get_son_rect(int son) {
|
||||||
if(depth == 0)
|
return {
|
||||||
r->push_back(t);
|
float(int(place.x + place.width/3 * (son%3))),
|
||||||
else
|
float(int(place.y + place.height/3 * int(son/3))),
|
||||||
for(Block* son : sons)
|
float(int(place.width/3)),
|
||||||
son->save(r);
|
float(int(place.height/3))
|
||||||
}
|
};
|
||||||
void Block::load_state(vector<tile> state, int pos) {
|
|
||||||
if(depth == 0)
|
|
||||||
t = state[pos];
|
|
||||||
else {
|
|
||||||
for(int i = 0; i < 9; i++)
|
|
||||||
sons[i]->load_state(state, pos*9+i);
|
|
||||||
t = update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Block::undo(deque<int> &prev) {
|
|
||||||
// TODO
|
|
||||||
}
|
}
|
||||||
|
|
23
global.hpp
23
global.hpp
|
@ -13,8 +13,6 @@ using std::string;
|
||||||
using std::array;
|
using std::array;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
using std::cin;
|
|
||||||
using std::cout;
|
|
||||||
|
|
||||||
#define FPS 15
|
#define FPS 15
|
||||||
#define SCREEN 800
|
#define SCREEN 800
|
||||||
|
@ -22,6 +20,10 @@ using std::cout;
|
||||||
|
|
||||||
#define IMG_COUNT 2
|
#define IMG_COUNT 2
|
||||||
|
|
||||||
|
#define BACKGROUND WHITE
|
||||||
|
#define GHOST BLACK
|
||||||
|
#define GRID BLACK
|
||||||
|
|
||||||
enum tile {empty = 0, p1 = 1, p2 = 2, tie = 3};
|
enum tile {empty = 0, p1 = 1, p2 = 2, tie = 3};
|
||||||
#define OKAY -1
|
#define OKAY -1
|
||||||
#define CHANGE -2
|
#define CHANGE -2
|
||||||
|
@ -39,22 +41,17 @@ struct Block {
|
||||||
|
|
||||||
Block() {}
|
Block() {}
|
||||||
Block(int _depth, Rectangle trg);
|
Block(int _depth, Rectangle trg);
|
||||||
Rectangle get_son_rectangle(int son);
|
|
||||||
int set(tile pl);
|
int set(tile pl);
|
||||||
bool playable(deque<int> v);
|
bool playable(deque<int> v);
|
||||||
int play(deque<int> v, tile pl);
|
int play(deque<int> v, tile pl);
|
||||||
bool check_tie();
|
|
||||||
tile update();
|
tile update();
|
||||||
Rectangle getRect(deque<int> v);
|
|
||||||
void updateRect(Rectangle trg);
|
|
||||||
|
|
||||||
void save(vector<tile> *r);
|
void update_rect(Rectangle trg);
|
||||||
void load_state(vector<tile> state, int pos);
|
Rectangle get_rect(deque<int> v);
|
||||||
void undo(deque<int> &prev);
|
Rectangle get_son_rect(int son);
|
||||||
};
|
};
|
||||||
|
|
||||||
void update(Block* root, int time, deque<int> &turn);
|
|
||||||
void undo(Block *root, deque<int> &prev, int time);
|
|
||||||
bool valid(Block* root, Rectangle play_area, deque<int> &turn);
|
bool valid(Block* root, Rectangle play_area, deque<int> &turn);
|
||||||
|
|
||||||
class Renderer {
|
class Renderer {
|
||||||
|
@ -64,9 +61,9 @@ class Renderer {
|
||||||
void prepareTextures();
|
void prepareTextures();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void renderImage(tile t, Rectangle dst, Color color = WHITE);
|
Renderer(Block* root, int time, Rectangle dst);
|
||||||
|
void render_image(tile t, Rectangle dst, Color color = WHITE);
|
||||||
void render_all(Block* root, int time, Rectangle play_area, deque<int> highlight = {});
|
void render_all(Block* root, int time, Rectangle play_area, deque<int> highlight = {});
|
||||||
void render_block(Block *b);
|
void render_block(Block *b);
|
||||||
int update_board_size(int depth);
|
int update_board_size(int depth);
|
||||||
void prepare_screen(Block* root, int time, Rectangle dst);
|
|
||||||
};
|
};
|
||||||
|
|
26
graphics.cpp
26
graphics.cpp
|
@ -4,40 +4,43 @@
|
||||||
// Rendering
|
// Rendering
|
||||||
void Renderer::prepareTextures() {
|
void Renderer::prepareTextures() {
|
||||||
const char* paths[] = {"img/circle.png", "img/cross.png"};
|
const char* paths[] = {"img/circle.png", "img/cross.png"};
|
||||||
for(int i = 0; i < IMG_COUNT; i++) {
|
for(int i = 0; i < IMG_COUNT; ++i) {
|
||||||
Image img;
|
Image img;
|
||||||
img = LoadImage(paths[i]);
|
img = LoadImage(paths[i]);
|
||||||
textures[i] = LoadTextureFromImage(img);
|
textures[i] = LoadTextureFromImage(img);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Renderer::renderImage(tile t, Rectangle dst, Color color) {
|
|
||||||
|
void Renderer::render_image(tile t, Rectangle dst, Color color) {
|
||||||
if(t == empty || t == tie)
|
if(t == empty || t == tie)
|
||||||
return;
|
return;
|
||||||
Texture tex = textures[t-1];
|
Texture tex = textures[t-1];
|
||||||
Rectangle src = {0, 0, (float)tex.width, (float)tex.height};
|
Rectangle src = {0, 0, (float)tex.width, (float)tex.height};
|
||||||
DrawTexturePro(textures[t-1], src, dst, {0,0}, 0, color);
|
DrawTexturePro(tex, src, dst, {0,0}, 0, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::render_block(Block *b) {
|
void Renderer::render_block(Block *b) {
|
||||||
if(b->depth > 0)
|
if(b->depth > 0)
|
||||||
DrawRectangleLinesEx(b->place, b->depth, BLACK);
|
DrawRectangleLinesEx(b->place, b->depth, GRID);
|
||||||
renderImage(b->t, b->place);
|
|
||||||
if(b->depth == 0 || (b->t != empty && b->t != tie))
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
render_image(b->t, b->place);
|
||||||
|
if(b->depth > 0 && (b->t == empty || b->t == tie))
|
||||||
for(int i = 0; i < 9; i++)
|
for(int i = 0; i < 9; i++)
|
||||||
render_block(b->sons[i]);
|
render_block(b->sons[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::render_all(Block* root, int time, Rectangle play_area, deque<int> highlight) {
|
void Renderer::render_all(Block* root, int time, Rectangle play_area, deque<int> highlight) {
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(RAYWHITE);
|
ClearBackground(BACKGROUND);
|
||||||
|
|
||||||
render_block(root);
|
render_block(root);
|
||||||
if(valid(root, play_area, highlight))
|
if(valid(root, play_area, highlight))
|
||||||
renderImage(act(time), root->getRect(highlight), BLACK);
|
render_image(act(time), root->get_rect(highlight), GHOST);
|
||||||
DrawRectangleLinesEx(play_area, 3*LINE_W, col(time+1));
|
DrawRectangleLinesEx(play_area, 3*LINE_W, col(time+1));
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Renderer::update_board_size(int depth) {
|
int Renderer::update_board_size(int depth) {
|
||||||
int max_size = std::min(GetScreenWidth(), GetScreenHeight());
|
int max_size = std::min(GetScreenWidth(), GetScreenHeight());
|
||||||
|
|
||||||
|
@ -48,12 +51,11 @@ int Renderer::update_board_size(int depth) {
|
||||||
max_size -= max_size % size;
|
max_size -= max_size % size;
|
||||||
return max_size;
|
return max_size;
|
||||||
}
|
}
|
||||||
void Renderer::prepare_screen(Block* root, int time, Rectangle dst) {
|
|
||||||
|
Renderer::Renderer(Block* root, int time, Rectangle dst) {
|
||||||
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
|
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
|
||||||
InitWindow(SCREEN, SCREEN, "Rekurze");
|
InitWindow(SCREEN, SCREEN, "Rekurze");
|
||||||
SetTargetFPS(FPS);
|
SetTargetFPS(FPS);
|
||||||
prepareTextures();
|
prepareTextures();
|
||||||
render_all(root, time, dst);
|
render_all(root, time, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
BIN
piskvorky
BIN
piskvorky
Binary file not shown.
111
recursive.cpp
111
recursive.cpp
|
@ -22,94 +22,22 @@ deque<int> to_deque(Vector2 v, int depth, int size) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void save_state(Block* root, int time, deque<int> &turn) {
|
|
||||||
vector<tile> state = {};
|
|
||||||
root->save(&state);
|
|
||||||
|
|
||||||
string filename; std::cin >> filename;
|
|
||||||
std::ofstream outfile("saves/" + filename);
|
|
||||||
|
|
||||||
outfile << root->depth << "\n" << time << "\n" << turn.size() << "\n";
|
|
||||||
|
|
||||||
// Save turns
|
|
||||||
for(int play : turn)
|
|
||||||
outfile << play << std::endl;
|
|
||||||
|
|
||||||
// Save game state
|
|
||||||
for(tile t : state)
|
|
||||||
outfile << int(t) << std::endl;
|
|
||||||
}
|
|
||||||
void load_state(Block** root, deque<int> &turn, int &time, char* argv) {
|
|
||||||
int depth = atoi(argv);
|
|
||||||
if(depth) {
|
|
||||||
*root = new Block(depth, {0, 0, SCREEN, SCREEN});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load file
|
|
||||||
string path = "saves/" + string(argv);
|
|
||||||
std::ifstream infile(path);
|
|
||||||
infile >> depth >> time;
|
|
||||||
|
|
||||||
// Load turns
|
|
||||||
int K; infile >> K;
|
|
||||||
for(int k = 0; k < K; k++) {
|
|
||||||
int play; infile >> play;
|
|
||||||
turn.push_back(play);
|
|
||||||
cout << play;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load board
|
|
||||||
vector<tile> state = {};
|
|
||||||
|
|
||||||
long long pw = 1;
|
|
||||||
for(int i = 0; i < depth; i++)
|
|
||||||
pw *= 9;
|
|
||||||
|
|
||||||
for(int i = 0; i < pw; i++) {
|
|
||||||
int next; infile >> next;
|
|
||||||
state.push_back((tile)next);
|
|
||||||
}
|
|
||||||
|
|
||||||
*root = new Block(depth, {0, 0, SCREEN, SCREEN});
|
|
||||||
(*root)->load_state(state, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void update(Block *root, int time, deque<int> &turn) {
|
|
||||||
time++;
|
|
||||||
turn.erase(turn.begin());
|
|
||||||
int rval_2 = root->play(turn, pas(time));
|
|
||||||
for(int i = 0; i <= rval_2; i++)
|
|
||||||
turn.pop_back();
|
|
||||||
}
|
|
||||||
void undo(Block *root, deque<int> &prev, int time) {
|
|
||||||
if(prev.size() == 0) return;
|
|
||||||
time--;
|
|
||||||
root->undo(prev);
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
bool valid(Block *root, Rectangle play_area, deque<int> &turn) {
|
bool valid(Block *root, Rectangle play_area, deque<int> &turn) {
|
||||||
return CheckCollisionRecs(root->getRect(turn), play_area) && root->playable(turn);
|
return CheckCollisionRecs(root->get_rect(turn), play_area) && root->playable(turn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
deque<int> turn = {};
|
|
||||||
int time = 0, depth;
|
int time = 0, depth;
|
||||||
Block* root = nullptr;
|
Block* root = nullptr;
|
||||||
|
|
||||||
if(argc <= 1) {
|
depth = argc <= 1 ? 1 : std::atoi(argv[1]);
|
||||||
cin >> depth;
|
|
||||||
root = new Block(depth, {0, 0, SCREEN, SCREEN});
|
root = new Block(depth, {0, 0, SCREEN, SCREEN});
|
||||||
}
|
|
||||||
else
|
|
||||||
load_state(&root, turn, time, argv[1]);
|
|
||||||
|
|
||||||
Rectangle play_area = root->getRect(turn);
|
Rectangle play_area = root->get_rect({});
|
||||||
|
|
||||||
Renderer renderer;
|
Renderer renderer(root, time, play_area);
|
||||||
renderer.prepare_screen(root, time, play_area);
|
|
||||||
int board_size = renderer.update_board_size(depth);
|
int board_size = renderer.update_board_size(depth);
|
||||||
|
|
||||||
bool end = false;
|
bool end = false;
|
||||||
|
@ -121,38 +49,39 @@ int main(int argc, char** argv) {
|
||||||
float start_x = ((float)GetScreenWidth()-board_size)/2;
|
float start_x = ((float)GetScreenWidth()-board_size)/2;
|
||||||
float start_y = ((float)GetScreenHeight()-board_size)/2;
|
float start_y = ((float)GetScreenHeight()-board_size)/2;
|
||||||
|
|
||||||
root->updateRect({start_x, start_y, (float)board_size, (float)board_size});
|
root->update_rect({start_x, start_y, (float)board_size, (float)board_size});
|
||||||
play_area = root->getRect(pturn);
|
play_area = root->get_rect(pturn);
|
||||||
|
|
||||||
// Move
|
// Move
|
||||||
Vector2 touch = GetMousePosition();
|
Vector2 touch = GetMousePosition();
|
||||||
turn = to_deque({touch.x - start_x, touch.y - start_y}, depth, board_size);
|
deque<int> turn = to_deque({touch.x - start_x, touch.y - start_y}, depth, board_size);
|
||||||
if(IsMouseButtonPressed(0) && CheckCollisionPointRec(touch, play_area) && valid(root, play_area, turn)) {
|
if( IsMouseButtonPressed(0) &&
|
||||||
|
CheckCollisionPointRec(touch, play_area) &&
|
||||||
|
valid(root, play_area, turn))
|
||||||
switch(root->play(turn, act(time))) {
|
switch(root->play(turn, act(time))) {
|
||||||
case CHANGE:
|
case CHANGE:
|
||||||
end = true;
|
end = true;
|
||||||
break;
|
break;
|
||||||
case OKAY:
|
case OKAY:
|
||||||
update(root, time, turn);
|
time++;
|
||||||
|
turn.erase(turn.begin());
|
||||||
|
int rval_2 = root->play(turn, pas(time));
|
||||||
|
for(int i = 0; i <= rval_2; i++)
|
||||||
|
turn.pop_back();
|
||||||
|
|
||||||
pturn = turn;
|
pturn = turn;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Key presses
|
|
||||||
if(IsKeyPressed(KEY_X))
|
|
||||||
save_state(root, time, turn), end = true;
|
|
||||||
else if(IsKeyPressed(KEY_Z))
|
|
||||||
{} // TODO undo
|
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
renderer.render_all(root, time, play_area, turn);
|
renderer.render_all(root, time, play_area, turn);
|
||||||
|
|
||||||
if(end)
|
if(IsKeyDown(KEY_Q))
|
||||||
|
|
||||||
|
if(end || IsKeyDown(KEY_Q))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitTime(10);
|
|
||||||
CloseWindow();
|
CloseWindow();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue