HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Sketch of Chutes and Ladders game

Submitted by: @import:stackexchange-codereview··
0
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

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:

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.