Skip to content

Instantly share code, notes, and snippets.

@yumetodo
Created October 4, 2015 17:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yumetodo/19676e2b3ee585b81df2 to your computer and use it in GitHub Desktop.
Save yumetodo/19676e2b3ee585b81df2 to your computer and use it in GitHub Desktop.
C++14でありきたりなじゃんけんプログラム。静的if文ください
#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;
}
@yumetodo
Copy link
Author

yumetodo commented Oct 4, 2015

はやく私に静的if文をください。static_ifとかconstexpr_ifとか

それとなんでVSだと

std::uniform_int_distribution<uint8_t> dist_;

が通らないの?規格書には

26.5.8.1.1-1(N3225(C++11))
A uniform_int_distribution random number distribution produces random integers i, a ≦ i ≦ b, distributed
according to the constant discrete probability function

とあるから整数型ならなんでもOKだと思うんですが、char / signed char / unsigend charは整数型ではないとでも?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment