Public Access
Minesweeper on 20 x 9 with 28 mines, laid at the first dig and never under or next to it, with flags and the open-around-a-number dig; 2048 on 4 x 4, a tile merging once a move. Seeded, host-tested. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0162FokPdvY2KsS4NBfwyWPk
57 lines
2.3 KiB
C++
57 lines
2.3 KiB
C++
#pragma once
|
|
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
|
|
#include "game_rng.h"
|
|
|
|
namespace roro::games {
|
|
|
|
// Minesweeper (issue #101's follow-up): a field of 20 x 9 with 28 mines, cells big enough to read
|
|
// on this screen. The mines are laid at
|
|
// the first dig, never under it or next to it, so the first dig always opens something. Digging
|
|
// an open number whose flags are all placed opens what is left around it. The clock runs from the
|
|
// first dig to the end.
|
|
class Mines {
|
|
public:
|
|
static constexpr int kCols = 20, kRows = 9, kMines = 28; // the classic "intermediate" share: one cell in six or seven
|
|
|
|
enum Event : uint8_t { Opened = 1, Flagged = 2, Boom = 4, Won = 8 };
|
|
enum class Phase : uint8_t { Fresh, Running, Lost, Won };
|
|
|
|
explicit Mines(uint32_t seed) : rng_(seed) { start(); }
|
|
void start();
|
|
uint8_t dig(int col, int row);
|
|
uint8_t flag(int col, int row); // put on a closed cell, or taken off
|
|
void tick(uint32_t ms); // the clock, while the game runs
|
|
|
|
Phase phase() const { return phase_; }
|
|
bool open(int col, int row) const { return cells_[at(col, row)] & kOpen; }
|
|
bool flagged(int col, int row) const { return cells_[at(col, row)] & kFlag; }
|
|
bool mine(int col, int row) const { return cells_[at(col, row)] & kMine; }
|
|
int around(int col, int row) const { return cells_[at(col, row)] & kCount; } // mines next to it
|
|
int minesLeft() const { return kMines - flags_; } // by the flags placed, right or wrong
|
|
uint32_t seconds() const { return elapsedMs_ / 1000; }
|
|
// For the tests: the mines put where one wants them, before any dig.
|
|
void lay(const uint16_t* where, int count);
|
|
|
|
private:
|
|
static constexpr uint8_t kCount = 0x0F, kMine = 0x10, kOpen = 0x20, kFlag = 0x40;
|
|
static size_t at(int col, int row) { return static_cast<size_t>(row * kCols + col); }
|
|
static bool inside(int col, int row) { return col >= 0 && col < kCols && row >= 0 && row < kRows; }
|
|
void layAwayFrom(int col, int row);
|
|
void count();
|
|
uint8_t reveal(int col, int row);
|
|
uint8_t settle(uint8_t events);
|
|
|
|
Rng rng_;
|
|
std::array<uint8_t, kCols * kRows> cells_{};
|
|
Phase phase_ = Phase::Fresh;
|
|
bool laid_ = false;
|
|
int flags_ = 0, opened_ = 0;
|
|
uint32_t elapsedMs_ = 0;
|
|
};
|
|
|
|
} // namespace roro::games
|