C 猜猜猜😀文字小游戏
前言 - 随机性
没啥事情, 写了个猜猜猜(猜数字)小游戏. 遇到猜的部分, 那肯定会用到随机函数. 我们为了多平台行为一致, 就统一
整合一个伪随机函数实现方案, 让随机更随机. 一开始看下接口设计 rand.h
#ifndef _RAND_H
#define _RAND_H #include <stdint.h>
#include <assert.h> //
// 传承(抄袭)不灭(创新) rand 库
// 大体思路
// { r | r[n+1] = (a*r[n] + c) mod m
// , n >= 0
// , m = 0xFFFFFFFFFFFF = 2 ^ 48
// , a = 0x0005DEECE66D = 0x5DEECE66D,
// , c = 0x000B = 0xB
// }
//
struct rand {
uint32_t x0, x1, x2;
uint32_t a0, a1, a2;
uint32_t c;
}; typedef struct rand rand_t[]; //
// rand_init - 随机函数对象初始化种子
// r : 随机函数对象
// seed : 种子数
// return : void
//
extern void rand_init(rand_t r, int64_t seed); //
// rand_rand - 获取一个随机值
// r : 随机函数对象
// return : 返回 [0, INT32_MAX] 随机数
//
extern int32_t rand_rand(rand_t r); //
// r_rand - 得到 [0, INT32_MAX] 随机数
// r_ranb - 得到 [0, INT64_MAX] (int64 = big int32) 随机数
// r_rang - 得到 range [min, max] 随机数
//
extern int32_t r_rand(void); extern int64_t r_ranb(void); inline int32_t r_rang(int32_t min, int32_t max) {
assert(max >= min);
return r_rand() % (max - min + ) + min;
} #endif//_RAND_H
rand.c
#include "rand.h" #define X0 (0x330E)
#define X1 (0xABCD)
#define X2 (0x1234)
#define A0 (0xE66D)
#define A1 (0xDEEC)
#define A2 (0x0005)
#define C (0x000B) #define N (16)
#define MASK ((1 << N) - 1)
#define LOW(x) ((uint32_t)(x) & MASK)
#define HIGH(x) LOW((x) >> N) //
// rand_init - 随机函数对象初始化种子
// r : 随机函数对象
// seed : 种子数
// return : void
//
inline void
rand_init(rand_t r, int64_t seed) {
r->x0 = X0; r->x1 = LOW(seed); r->x2 = HIGH(seed);
r->a0 = A0; r->a1 = A1; r->a2 = A2;
r->c = C;
} #define CARRY(x, y) ((x + y) > MASK) // 基于 16 位判断二者和是否进位
#define ADDRQ(x, y, z) z = CARRY(x, y); x = LOW(x + y)
#define MUL(m, x, y, z) m = (x) * (y); z##0 = LOW(m); z##1 = HIGH(m) inline void rand_next(rand_t r) {
uint32_t m, p0, p1, q0, q1, s0, s1, c0, c1; MUL(m, r->a0, r->x0, p);
ADDRQ(p0, r->c, c0);
ADDRQ(p1, c0, c1);
MUL(m, r->a0, r->x1, q);
ADDRQ(p1, q0, c0);
MUL(m, r->a1, r->x0, s); m = c0 + c1 + CARRY(p1, s0) + q1 + s1
+ r->a0 * r->x2 + r->a1 * r->x1 + r->a2 * r->x0;
r->x2 = LOW(m);
r->x1 = LOW(p1 + s0);
r->x0 = LOW(p0);
} //
// rand_rand - 获取一个随机值
// r : 随机函数对象
// return : 返回 [0, INT32_MAX] 随机数
//
inline int32_t
rand_rand(rand_t r) {
rand_next(r);
return (r->x2 << (N - )) + (r->x1 >> );
} //
// 想过 - 朵朵浪花, 也不曾看见云彩飘过 :0
//
static rand_t r_r = { { X0, X1, X2 , A0, A1, A2 , C } }; // EXTERN_RUN(r_init) 启动初始化
extern inline void r_init(int64_t seed) {
rand_init(r_r, seed);
} inline int32_t
r_rand(void) {
return rand_rand(r_r);
} inline int64_t
r_ranb(void) {
uint64_t x = ((r_rand() << N) ^ r_rand()) & INT32_MAX;
uint64_t y = ((r_rand() << N) ^ r_rand()) & INT32_MAX;
return ((x << * N) | y) & INT64_MAX;
}
算法层面网上资料很够(redis rand48 原理) . 我这里只聊聊工程实现方面, 可以看出来多线程并发发起 r_rand()
请求是不可控的(非线程安全, 你也不知道内部运行状态是啥). 但如果存在特殊业务需要可窥探随机序列时候,
rand_init 就可以运用上了, 来构建多线程情况下可控的随机函数对象.
对于 r_init 多数使用 time(NULL) 时间量初始化种子, 有没有人觉得不太可靠, 毕竟服务器时间也可以改. 有
没有想过让其更加混乱一点. 这里有个小想法, 提出来可供大家一块参略讨论讨论.
1 //
// EXTERN_RUN - 函数包装宏, 声明并立即使用
// frun : 需要执行的函数名称
// ... : 可变参数, 保留
//
#define EXTERN_RUN(frun, ...) \
do { \
extern void frun(); \
frun (__VA_ARGS__); \
} while() // 此后 :) 随机与你无关 ~
EXTERN_RUN(rand_restrict);
// rand_nationalism - 民族主义, 国家是人民所共有, 各族平等, 团结一致
static void rand_nationalism(void) {
struct timespec s;
(void)timespec_get(&s, TIME_UTC);
EXTERN_RUN(r_init, s.tv_nsec + s.tv_sec);
for (int32_t i = BUFSIZ; i > ; --i) {
(void)timespec_get(&s, TIME_UTC);
EXTERN_RUN(r_init, s.tv_nsec + i);
}
} // rand_democracy - 民权主义, 政治是人民所共管, 选举权、罢免权、创制权和复决权
static void rand_democracy(void) {
int32_t x, y, z, w;
do {
x = r_rand();
y = r_rand();
z = r_rand();
w = r_rand();
} while (!(x > y && y > z && z > w && w > INT16_MAX));
} // rand_livelihood - 民生主义, 利益是人民所共享, 让人像个人
static void rand_livelihood(void) {
for (int32_t i = r_rand(); i >= ; --i)
r_rand();
} // rand_restrict - 三权制衡在随机函数初中运用
void rand_restrict(void) {
thread_async(rand_nationalism);
thread_async(rand_democracy);
thread_async(rand_livelihood);
}
传送门 核心是引入多线程互相竞争制约, 让随机函数你我不知, 模糊不清, 捉摸不透. 这里只是瞎弄一个思路.
大家有更好的想法可以在评论区和我一块交流.
正文 - 猜猜猜
是不是要开始扯闲篇. 那就用上面随机库写个猜猜猜游戏吧 ~
main.c
#include "rand.h"
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> //
// EXTERN_RUN - 函数包装宏, 声明并立即使用
// frun : 需要执行的函数名称
// ... : 可变参数, 保留
//
#define EXTERN_RUN(frun, ...) \
do { \
extern void frun(); \
frun (__VA_ARGS__); \
} while() //
// GUESS_THRESHOLD_INT - 猜数最多次数
// GUESS_TEMPER_INT - 遇到小脾气不再触发提示
// GUESS_MAX_INT - 最大值区间
//
#define GUESS_THRESHOLD_INT (8)
#define GUESS_TEMPER_INT (3)
#define GUESS_MAX_INT (8964) // guess 猜数字游戏对象
struct guess {
int32_t max; // 数字区间上限
int32_t correct; // 正确数值
int32_t use; // 已经猜数次数
int32_t numbers[GUESS_THRESHOLD_INT]; // 用户猜数数组
int32_t now; // 用户当前输入值
}; // guess_run 猜数字游戏开始
void guess_run(struct guess * restrict g);
// guess_guess 猜数字开启猜猜猜
bool guess_guess(struct guess * restrict g);
// guess_end 猜数字游戏结束总结
void guess_end(struct guess * restrict g); // threshold_input - 获取猜数字的范围
static int32_t threshold_input(int argc, char * argv[]) {
int32_t max = GUESS_MAX_INT;
if (argc > ) {
int num = atoi(argv[]);
if (num <= ) {
printf("亲, 别C 猜猜猜😀文字小游戏的更多相关文章
- [第一个自己做的C小程序]丧失求生文字小游戏
丧失求生文字小游戏 编写原因: 我编写这个小程序是为了结合下我学习的知识并且做一个小游戏来看看我自己的能力,目前我已经学完了C语言的编程基础.马上就要学到指针,这个就是我的基础总结项目,希望大家可以都 ...
- 一个简单的猜大小的小游戏 python
初学python,用python写了一个简单的猜大小的小游戏 #!/usr/bin/env python #-*- coding:utf-8 -*- print "------------- ...
- python摇骰子猜大小的小游戏
#小游戏,摇筛子押大小的小游戏玩家初始有1000块钱,可以压大压小作为赌注 import random #定义摇筛子的函数: def roll_dice(number = 3,points = Non ...
- 猜生日 Java小游戏
最近看到一个很有趣的小游戏: 询问朋友5个问题,找到他出生在一个月的哪一天.每个问题都是询问他的生日是否是5个数字集合中的一个. 这5个集合分别是: set1:1 3 5 7 9 11 13 15 1 ...
- 【python27】猜随机数的小游戏
游戏规则: 猜一个随机数,如果猜对了就给出相应的猜成功提示语(自定义文字),如果猜大或者是猜小了,给出对应的提示,但总的猜次数为三次,每猜错一次重新猜时,给用户提示所剩余的猜次数 实现如下: # -* ...
- [GO]猜数字的小游戏
随机生成四位数字,然后用户输入四位数字,然后根据提示一步步猜到随机数 package main import ( "math/rand" "time" &quo ...
- Python基础入门-实现猜数字小游戏
今天呢,我们来通过前面学过的一些知识点来完成一个猜数字大小的游戏程序设计.那么呢,一般人写代码直接上来就干,没有分析,这样的做法是没有产出的,除非你是大牛,今天呢,我会把我学习编程的思路分享给大家,我 ...
- 初学python写个自娱自乐的小游戏
一.摘要 当编写完后的代码执行第一次后达到了目标的预期效果,内心有些许满足,但是当突发情况产生后,程序便不能正常运行,于是准备从简单的版本开始出发,综合考虑使用者的需求,和使用过程中会遇到的问题,一步 ...
- Python小游戏之猜数字
最近师兄师姐毕业,各种酒席,酒席上最常玩的一个游戏就是猜数字,游戏规则如下: 出题人在手机上输入一个0-100之间的数字,其它人轮流猜这个数字,如果你不幸猜中则要罚酒一杯.每次猜数字,出题人都要缩小范 ...
随机推荐
- [SDOI2010]捉迷藏 K-Dtree
[SDOI2010]捉迷藏 链接 luogu 思路 k-dtree模板题 代码 #include <bits/stdc++.h> #define ls (t[u].ch[0]) #defi ...
- 洛谷 P3806 【模板】点分治1-树分治(点分治,容斥版) 模板题-树上距离为k的点对是否存在
P3806 [模板]点分治1 题目背景 感谢hzwer的点分治互测. 题目描述 给定一棵有n个点的树 询问树上距离为k的点对是否存在. 输入格式 n,m 接下来n-1条边a,b,c描述a到b有一条长度 ...
- for循环的嵌套之小星星。
for循环中如何打印出五行五列的小星星呢? 很明显行列的形式需要用到循环嵌套. 外循环控制行: var str = "" ; for(var i= 1; i <= 5; i ...
- Flume 实战,将多台机器日志直接收集到 Kafka
目前我们使用的一个 b 端软件的报错日志分散在集群各处,现在想把它收集到一个地方然后统一丢进 Kafka 提供给下游业务进行消费. 我想到了 flume,之前让同事搭建的这次自己想多了解一些细节于是就 ...
- xss、SQL测试用例小结
xss测试用例小结: <script>alert("跨站")</script> (最常用)<img scr=javascript:alert(&quo ...
- (ACP)敏捷项目管理
第1章 为什么需要敏捷 第2章 敏捷和敏捷项目管理定义 第3章 敏捷项目管理价值和原则 1.我们的最高目标是,通过尽早持续交付有价值的软件来满足客户的需求 2.欢迎对需求提出变更,即使在项目开发后期也 ...
- rabbitmq在linux下单节点部署和基本使用
RabbitMQ是基于erlang开发的消息服务,官网为:https://www.rabbitmq.com,RabbitMQ要依赖erlang运行,所以要先安装erlang环境,rabbitmq可以用 ...
- session与getSession()用法总结
一.session 1.session的过期时间是从什么时候开始计算的?是从一登录就开始计算还是说从停止活动开始计算? 从session不活动的时候开始计算,如果session一直活动,session ...
- Kafka架构与原理
前言 kafka是一个分布式消息队列.具有高性能.持久化.多副本备份.横向扩展能力.生产者往队列里写消息,消费者从队列里取消息进行业务逻辑.一般在架构设计中起到解耦.削峰.异步处理的作用. kafka ...
- sigmoid与softmax 二分类、多分类的使用
二分类下,sigmoid.softmax两者的数学公式是等价的,理论上应该是一样的,但实际使用的时候还是sigmoid好 https://www.zhihu.com/question/29524708 ...