Created
October 4, 2015 17:15
-
-
Save yumetodo/19676e2b3ee585b81df2 to your computer and use it in GitHub Desktop.
C++14でありきたりなじゃんけんプログラム。静的if文ください
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdint> | |
#include <iostream> | |
#include <exception> | |
#include <stdexcept> | |
#include <type_traits> | |
#include <limits> | |
#include <algorithm> | |
#include <climits> | |
#include <random> | |
#include <cstdlib> | |
#include <functional> | |
typedef uint8_t choise_t;//choise_t 0:ぐー, 1:チョキ, 2:パー | |
namespace console { | |
namespace detail { | |
//http://melpon.org/wandbox/permlink/QS601FVgmVSqGKbR | |
template <typename T> struct ask_cast_impl {//copyright(c) 江添亮 2015 | |
template < typename U > static T do_it(U && u) { | |
return static_cast<T>(u); | |
} | |
}; | |
template <> struct ask_cast_impl<bool> {//copyright(c) 江添亮 2015 | |
template <typename U> static bool do_it(U && u) { | |
static_assert(std::is_floating_point<U>::value, "ask_cast_impl error : floating_point is not supported"); | |
return u != false; | |
} | |
}; | |
} | |
template <bool Con, class Then, class Else> struct IF; | |
template <class Then, class Else> struct IF<true, Then, Else> { typedef Then type; }; | |
template <class Then, class Else> struct IF<false, Then, Else> { typedef Else type; }; | |
template<typename T_> using int8_conv_buf_t = typename IF< | |
1 != sizeof(T_), | |
T_, | |
typename IF< | |
std::is_signed<T_>::value, | |
int, | |
unsigned int | |
>::type | |
>::type; | |
template<typename T_> using limit = std::numeric_limits<T_>;//create new type. C++11:alias declaration | |
template<typename T_> T_ input(const char* echo_str, const T_ max = limit<T_>::max(), const T_ min = limit<T_>::lowest()) noexcept { | |
static_assert(std::is_arithmetic<T_>::value, "unexpected type T_");//T_が整数か浮動小数点型でないならばコンパイルエラーを出す | |
int8_conv_buf_t<T_> buf; | |
try { | |
if (nullptr == echo_str) throw std::invalid_argument("echo_str is unexpected input");//エラー対策 | |
if ('\0' != echo_str[0]) std::cout << echo_str << std::endl;//文字列が空じゃなければ出力 | |
std::cin >> buf;//入力を受ける | |
if (max < buf || buf < min) throw std::out_of_range("input is iligal");//範囲チェック | |
} | |
catch (std::exception& er) { | |
std::cerr << er.what() << std::endl;//エラーメッセージ表示 | |
return input("再入力してください。", max, min);//エラー時は再帰する方向で | |
} | |
return detail::ask_cast_impl<T_>::do_it(buf); | |
} | |
} | |
namespace winconsole { | |
void clear() { | |
#ifdef _MSC_VER | |
std::system("cls"); | |
#else | |
std::system("clear"); | |
#endif | |
} | |
} | |
uint8_t winner_judge(const choise_t p1, const choise_t p2) {//0: あいこ, 1: p1's win, 2: p2's win | |
return (p1 == p2) ? 0 : (p1 < p2) ? (p2 - p1 == 1U) ? 1 : 2 : (p1 - p2 == 1U) ? 2 : 1; | |
} | |
class cpu_chose { | |
public: | |
cpu_chose() : dist_(0, 2){ | |
std::random_device rnd;// ランダムデバイス | |
std::vector<std::uint_least32_t> v(10);// 初期化用ベクタ | |
std::generate(v.begin(), v.end(), std::ref(rnd));// ベクタの初期化 | |
std::seed_seq seq(v.begin(), v.end()); | |
this->engine_ = std::mt19937(seq);// 乱数エンジン | |
} | |
cpu_chose(const cpu_chose&) = delete; | |
cpu_chose(cpu_chose&&) = default; | |
choise_t operator()() { | |
return static_cast<choise_t>(this->dist_(this->engine_)); | |
} | |
private: | |
std::mt19937 engine_; | |
std::uniform_int_distribution<uint16_t> dist_; | |
}; | |
uint8_t turn(const char* message, cpu_chose&& cpu_chose_f = cpu_chose()) { | |
static const char* string_table[]{ "CPUの勝ち", "あなたの勝ち" }; | |
if (nullptr == message) throw std::invalid_argument("echo_str is unexpected input");//エラー対策 | |
if ('\0' != message[0]) std::cout << message << std::endl;//文字列が空じゃなければ出力 | |
const auto cpu_s = cpu_chose_f(); | |
const auto user_s = console::input<uint8_t>("0: ぐー, 1: チョキ, 2: パー", 2U, 0U); | |
winconsole::clear(); | |
const auto re = winner_judge(cpu_s, user_s); | |
if (re == 0) return turn("あいこで...", std::move(cpu_chose_f)); | |
std::cout << string_table[re - 1] << std::endl; | |
return re; | |
} | |
int main() { | |
try { | |
turn("じゃんけん..."); | |
} | |
catch (const std::exception& er) { | |
std::cerr << er.what() << std::endl; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
はやく私に静的if文をください。
static_if
とかconstexpr_if
とかそれとなんでVSだと
std::uniform_int_distribution<uint8_t> dist_;
が通らないの?規格書には
とあるから整数型ならなんでもOKだと思うんですが、
char / signed char / unsigend char
は整数型ではないとでも?