Witam, proszę o ocene kodu źródłowego. Czy testy jednostkowe są wystarczające?
Treść zadania:
Pierwsza linia wejścia zawiera liczbę całkowitą, oznaczającą liczbę zestawów danych.
Pierwsza linia każdego zestawu zawiera jedną liczbę całkowitą, oznaczającą liczbę wskazówek - par określających kierunek i ilość kroków do wykonania.
Kolejne linie składą się z liczb a i b (0 ≤ a ≤ 3; 1 ≤ b ≤ 10000), które oznaczają pojedynczą wskazówkę.
Każda para a i b jest pojedynczą wskazówką, gdzie pierwsza liczba w wierszu oznacza kierunek, w którym należy iść, a druga ilość kroków, które trzeba wykonać w tym kierunku.
Kierunki te są zakodowane następująco:
0 - północ
1 - południe
2 - zachód
3 - wschód
Dla każdego zestawu danych należy wypisać najkrótszą drogę, lub słowo studnia, jeśli skarb znajduje się w obecnym położeniu.
Drogę oznaczamy przez pary kierunek i ilość kroków w tym kierunku wypisanych w jednej linii.
Jeśli do skarbu prowadzi prosta droga, należy wypisać tylko jedną linię z kierunkiem i ilością kroków.
Jeśli droga musi skręcać, to wtedy kroki wykonywać w orientacji północ-południe, a dopiero gdy znajdziemy się na odpowiedniej wysokości w tej orientacji, zacząć robić kroki w orientacji wschód-zachód.
Main.cpp
#include "TreasureFinder.h"
#include <iostream>
#include <sstream>
void writeTreasureFinderResult(std::ostream& os);
int main()
{
std::stringstream ss;
unsigned dataSetsCount;
std::cin >> dataSetsCount;
for (unsigned i = 0; i < dataSetsCount; i++) {
writeTreasureFinderResult(ss);
ss << std::endl;
}
std::cout << ss.str();
}
void writeTreasureFinderResult(std::ostream& os)
{
TreasureFinder tf;
unsigned tipsAmount;
std::cin >> tipsAmount;
for (unsigned i = 0; i < tipsAmount; i++) {
unsigned direction;
std::cin >> direction;
int stepsCount;
std::cin >> stepsCount;
tf.addTip(direction, stepsCount);
}
tf.writeResult(os);
}
TreasureFinder.h
#pragma once
#include <ostream>
class TreasureFinder {
public:
void addTip(unsigned direction, int stepsCount);
bool isInPlaceTreasure() const { return verticalSteps == 0 && horizontalSteps == 0; }
bool isNorthDirectionTreasure() const { return verticalSteps > 0; }
bool isSouthDirectionTreasure() const { return verticalSteps < 0; }
bool isWestDirectionTreasure() const { return horizontalSteps > 0; }
bool isEastDirectionTreasure() const { return horizontalSteps < 0; }
void writeResult(std::ostream& os) const;
private:
enum Direction { NORTH, SOUTH, WEST, EAST };
bool shouldAddEndlineToResult() const;
int verticalSteps = 0;
int horizontalSteps = 0;
};
inline bool TreasureFinder::shouldAddEndlineToResult() const
{
return
(isNorthDirectionTreasure() || isSouthDirectionTreasure()) &&
(isWestDirectionTreasure() || isEastDirectionTreasure());
}
TreasureFinder.cpp
#include "TreasureFinder.h"
#include <string>
void TreasureFinder::addTip(unsigned direction, int stepsCount)
{
switch (direction) {
case NORTH:
verticalSteps += stepsCount;
break;
case SOUTH:
verticalSteps -= stepsCount;
break;
case WEST:
horizontalSteps += stepsCount;
break;
case EAST:
horizontalSteps -= stepsCount;
break;
}
}
void TreasureFinder::writeResult(std::ostream& os) const
{
if (isInPlaceTreasure()) {
const std::string inPlaceTreasureMessage("studnia");
os << inPlaceTreasureMessage;
return;
}
if (isNorthDirectionTreasure())
os << NORTH << ' ' << verticalSteps;
else if (isSouthDirectionTreasure())
os << SOUTH << ' ' << -verticalSteps;
if (shouldAddEndlineToResult())
os << std::endl;
if (isWestDirectionTreasure())
os << WEST << ' ' << horizontalSteps;
else if (isEastDirectionTreasure())
os << EAST << ' ' << -horizontalSteps;
}
TreasureFinderTest.cpp
#include <CppUnitTest.h>
#include "../TreasureFinder/TreasureFinder.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace Test {
TEST_CLASS(TreasureFinderTest)
{
public:
TEST_METHOD(testInPlaceTreasure)
{
TreasureFinder tf;
std::stringstream ss;
tf.addTip(0, 5);
tf.addTip(1, 5);
tf.addTip(2, 5);
tf.addTip(3, 5);
tf.writeResult(ss);
Assert::IsTrue(tf.isInPlaceTreasure());
Assert::AreEqual("studnia", ss.str().c_str());
}
TEST_METHOD(testNorthDirectionTreasure)
{
TreasureFinder tf;
std::stringstream ss;
tf.addTip(0, 5);
tf.writeResult(ss);
Assert::IsTrue(tf.isNorthDirectionTreasure());
Assert::AreEqual("0 5", ss.str().c_str());
}
TEST_METHOD(testSouthDirectionTreasure)
{
TreasureFinder tf;
std::stringstream ss;
tf.addTip(1, 5);
tf.writeResult(ss);
Assert::IsTrue(tf.isSouthDirectionTreasure());
Assert::AreEqual("1 5", ss.str().c_str());
}
TEST_METHOD(testWestDirectionTreasure)
{
TreasureFinder tf;
std::stringstream ss;
tf.addTip(2, 5);
tf.writeResult(ss);
Assert::IsTrue(tf.isWestDirectionTreasure());
Assert::AreEqual("2 5", ss.str().c_str());
}
TEST_METHOD(testEastDirectionTreasure)
{
TreasureFinder tf;
std::stringstream ss;
tf.addTip(3, 5);
tf.writeResult(ss);
Assert::IsTrue(tf.isEastDirectionTreasure());
Assert::AreEqual("3 5", ss.str().c_str());
}
TEST_METHOD(testNorthWestDirectionTreasure)
{
TreasureFinder tf;
std::stringstream ss;
tf.addTip(0, 5);
tf.addTip(2, 5);
tf.writeResult(ss);
Assert::IsTrue(tf.isNorthDirectionTreasure());
Assert::IsTrue(tf.isWestDirectionTreasure());
Assert::AreEqual("0 5\n2 5", ss.str().c_str());
}
TEST_METHOD(testNorthEastDirectionTreasure)
{
TreasureFinder tf;
std::stringstream ss;
tf.addTip(0, 5);
tf.addTip(3, 5);
tf.writeResult(ss);
Assert::IsTrue(tf.isNorthDirectionTreasure());
Assert::IsTrue(tf.isEastDirectionTreasure());
Assert::AreEqual("0 5\n3 5", ss.str().c_str());
}
TEST_METHOD(testSouthWestDirectionTreasure)
{
TreasureFinder tf;
std::stringstream ss;
tf.addTip(1, 5);
tf.addTip(2, 5);
tf.writeResult(ss);
Assert::IsTrue(tf.isSouthDirectionTreasure());
Assert::IsTrue(tf.isWestDirectionTreasure());
Assert::AreEqual("1 5\n2 5", ss.str().c_str());
}
TEST_METHOD(testSouthEastDirectionTreasure)
{
TreasureFinder tf;
std::stringstream ss;
tf.addTip(1, 5);
tf.addTip(3, 5);
tf.writeResult(ss);
Assert::IsTrue(tf.isSouthDirectionTreasure());
Assert::IsTrue(tf.isEastDirectionTreasure());
Assert::AreEqual("1 5\n3 5", ss.str().c_str());
}
};
}