patterncppMinor
Sketch of Chutes and Ladders game
Viewed 0 times
chutesladderssketchgameand
Problem
The classic Chutes and Ladders game has a grid of 100 squares with various "chutes" (which send a player backwards) and "ladders" (which promote a player forward). The goal here was to randomly create a series of these chutes and ladders such that the net effect is that there are 50 more squares that may be lost than gained. I had considered finishing this off to a complete and playable game, but it doesn't seem to be a sufficiently interesting game to warrant the small additional effort.
Here's a screenshot of the result:
distrib.cpp
```
#include
#include
#include
#include
#include
#include
#include "distrib.h"
int makeDeltaValues(std::vector &chutes, std::vector &ladders, int target)
{
std::random_device rd;
std::mt19937 gen(rd());
std::weibull_distribution<> d{2.0, 20};
auto badvalue = [](int a){ return (aboxcount*2/3);};
auto next{[&](){ int m; do { m=d(gen)+2; } while(badvalue(m)); return m;}};
int iterations = 0;
do {
++iterations;
std::generate(ladders.begin(), ladders.end(), next);
std::generate(chutes.begin(), chutes.end(), next);
int lsum = std::accumulate(ladders.begin(), ladders.end(), 0);
int csum = std::accumulate(chutes.begin(), chutes.end(), 0);
// lsum must always be smaller or equal
if (lsum > csum) {
std::swap(csum, lsum);
std::swap(chutes, ladders);
}
int delta = target - csum+lsum;
// need to add delta distributed over chutes
for (auto &v : chutes) {
if (!badvalue(v+delta)) {
v += delta;
delta = 0;
}
}
// force remainder into first element (usually zero)
chutes.front() += delta;
} while (badvalue(chutes.front()));
return iterations;
}
std::vector> createLinks()
{
std::vector ladders(9);
std::vector chutes(9);
std::vector> links;
links.reserve(ladders.size() + chutes.size());
makeDeltaVa
Here's a screenshot of the result:
distrib.cpp
```
#include
#include
#include
#include
#include
#include
#include "distrib.h"
int makeDeltaValues(std::vector &chutes, std::vector &ladders, int target)
{
std::random_device rd;
std::mt19937 gen(rd());
std::weibull_distribution<> d{2.0, 20};
auto badvalue = [](int a){ return (aboxcount*2/3);};
auto next{[&](){ int m; do { m=d(gen)+2; } while(badvalue(m)); return m;}};
int iterations = 0;
do {
++iterations;
std::generate(ladders.begin(), ladders.end(), next);
std::generate(chutes.begin(), chutes.end(), next);
int lsum = std::accumulate(ladders.begin(), ladders.end(), 0);
int csum = std::accumulate(chutes.begin(), chutes.end(), 0);
// lsum must always be smaller or equal
if (lsum > csum) {
std::swap(csum, lsum);
std::swap(chutes, ladders);
}
int delta = target - csum+lsum;
// need to add delta distributed over chutes
for (auto &v : chutes) {
if (!badvalue(v+delta)) {
v += delta;
delta = 0;
}
}
// force remainder into first element (usually zero)
chutes.front() += delta;
} while (badvalue(chutes.front()));
return iterations;
}
std::vector> createLinks()
{
std::vector ladders(9);
std::vector chutes(9);
std::vector> links;
links.reserve(ladders.size() + chutes.size());
makeDeltaVa
Solution
-
I'm a little bothered by the piecemeal conversion from rectangular to polar coordinates. I think I'd rather wrap them up into a little neater package:
It's open to some argument that it would be better still to define a
-
You've used copy initialization syntax a few places for no particularly good reason I can see. For example:
I'd generally prefer something like:
Depending on the overloaded ctors
-
You've defined
I'm a little bothered by the piecemeal conversion from rectangular to polar coordinates. I think I'd rather wrap them up into a little neater package:
std::pair r2p(float cx, float cy) {
auto len = std::sqrt(cx * cx + cy * cy);
auto angle = atan2(cy, cx)*180/M_PIl - 90;
return {len, angle};
}It's open to some argument that it would be better still to define a
polar_coordinate class (and probably a rectangular coordinate class as well), with each providing a constructor from the other (or a conversion operator to the other) so the compiler can help a little bit in enforcing type safety.-
You've used copy initialization syntax a few places for no particularly good reason I can see. For example:
sf::Text t = sf::Text(std::to_string(i), m_font);I'd generally prefer something like:
sf::Text t {std::to_string(i), m_font};Depending on the overloaded ctors
sf::Text provides, this can change the meaning though. If you run into that, I'd use auto instead:auto t = sf::Text(std::to_string(i), m_font);-
You've defined
Grid::indexOf, and Grid::centerOf, but in Grid::load, you duplicate the logic of indexOf exactly, and could probably use centerOf to simplify the logic for setting the text location as well (although this isn't quite as precise of duplication).Code Snippets
std::pair<float, float> r2p(float cx, float cy) {
auto len = std::sqrt(cx * cx + cy * cy);
auto angle = atan2(cy, cx)*180/M_PIl - 90;
return {len, angle};
}sf::Text t = sf::Text(std::to_string(i), m_font);sf::Text t {std::to_string(i), m_font};auto t = sf::Text(std::to_string(i), m_font);Context
StackExchange Code Review Q#132587, answer score: 5
Revisions (0)
No revisions yet.