avatar
文章
51
标签
75
分类
31

Archives
Tags
Categories
Link
About
Hiyoung'blog
搜索
Archives
Tags
Categories
Link
About

Hiyoung'blog

C和C++中引用
发表于2023-02-04|更新于2025-05-21|学习笔记C++

C的指针和C++中引用和函数参数类型

如果你说的是函数的形参,那么

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void foo(int ptr);

是传值调用,比如你这么调用
int a;
int pValue = &a;
foo(pValue);
//
这样的情况下,pValue的值是不能被函数foo改变的,也就是pValue肯定是指向a的
但是如果你这么声明:
void foo(int& ptr);
则是传递引用,那么如果你函数里面:
void foo(int& ptr)
{
ptr = NULL;
}
//
这样调用过之后,pValue就变成了NULL。而第一种情况pValue是不能被改变的。
引用是C++带来的很重要一个特性,他在很多情况下避免了使用指针。
而且,在C++里面,引用是不可以捏造的,比如C你可以很容易弄一个NULL的指针,而引用这不存在NULL引用。
上面的foo函数如果要用C来实现,则必须用指针的指针:
//
void foo(int pptr)
{
ptr = NULL;
}

调用的时候要
foo(&pValue)
//
这种技术很多用在比如定义一个安全删除指针的函数,所谓安全就是,
只有当指针为零的时候才执行删除,删除之后,立刻把指针赋值为NULL。
//

template<typename T>
inline safe_delete(T& ptr)
{
if (ptr)
{
delete ptr;
ptr = NULL;
}
}

通过下面代码可以更清楚理解两者区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>

int main() {
int x = 42;
int* px = &x; // px是指向x的指针
int** ppx = &px; // ppx是指向指针px的指针

std::cout << "&x: " << &x << std::endl;
std::cout << "x: " << x << std::endl;
std::cout << "px: " << px << std::endl;
std::cout << "*px: " << *px << std::endl; // 解引用指针px,获取x的值
std::cout << "**ppx: " << **ppx << std::endl; // 解引用指向指针px的指针,获取x的值

int& rx = x; // rx是x的引用
int* prx = &rx; // prx是指向引用rx的指针

std::cout << "rx: " << rx << std::endl;
std::cout << "*prx: " << *prx << std::endl; // 解引用指针prx,获取rx的值
std::cout << "&*prx: " << &*prx << std::endl; // 获取指针prx的地址

return 0;
}


在C++里面,能不用指针都应该尽量避免,STL里面就大量使用引用。

C++C
VsCode配置C语言环境
发表于2022-12-15|更新于2025-05-21|编程环境配置C/C++

VsCode只是一个纯文本编辑器,不是IDE(集成开发环境),不含编译器和许多其它功能,所以编译器要自己装好

第一步:在vscode官网下载软件,链接:Visual Studio Code – Code Editing. Redefined

第二步:我们需要下载一个编译器,C语言使用gcc,链接:MinGW-w64 – for 32 and 64 bit Windows download | SourceForge.net,选最新版本中的 x86_64-posix-seh 即可,网站下载可能较慢,下面给出百度网盘链接

(百度网盘链接:链接: https://pan.baidu.com/s/17FYT_Y-s-I2yajFc2MICqw 提取码: ewis )

第三步:将E:\mingw64\bin 添加到系统变量中(盘符根据自己编译器安装的位置)

以Win11为例:打开设置->系统->关于->高级系统设置->环境变量->系统变量->点击Path->编辑 -> 浏览 -> 把对应文件加入即可

第四步:

按Win+R,运行cmd(不要跳这一步),输入gcc,应该会提示 no input files 而不是“不是内部命令或外部命令”或者“无法将 “gcc” 项识别为 cmdlet、函数、脚本文件或可运行程序的名称”。如果是“不是内部命令或外部命令”,说明gcc在的文件夹没有在环境变量的Path中,要加进去才行。如果加了还是这样,重启(不要忘记重启)。如果重启了还不行,那就是你自己进行的操作有问题。

输gcc -v可以显示出gcc的版本。如果显示出来的版本与你刚下的不同/更老,说明Path里原本有老版本的编译器,可能是安装其它IDE时装上的。则需要去掉Path里原来的那一个gcc的路径。

这两项验证一定要符合,否则必须修改环境变量。小心别错删了。

第五步:现在打开vscode,下载相关插件

第六步:我们需要写两个json文件,下面依次是launch.json和tasks.json(两个文件名也必须是 launch.json 和 tasks.json ) 注意看代码注释,两个文件都有几处地方需要将路径改为自己编译器的路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "gcc.exe - 生成和调试活动文件",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}\\bin\\${fileBasenameNoExtension}.exe",//这里意思生成的二进制代码会放入当前文件的bin文件夹中,我们需要自己新建一个bin文件夹
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "E:\\mingw64\\bin\\gdb.exe",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: gcc.exe 生成活动文件"
}
]
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: gcc.exe 生成活动文件",
"command": "E:\\mingw64\\bin\\gcc.exe",//改成自己的文件路径
"args": [
/*"${fileDirname}\\*.c",
"-o",
"${fileDirname}\\bin\\${fileBasenameNoExtension}.exe",
"-g"//多文件编译*/
"-g",
"${file}",
"-o",
"${fileDirname}\\bin\\${fileBasenameNoExtension}.exe"//这里意思生成的二进制代码会放入当前文件的bin文件夹中,我们需要自己新建一个bin文件夹
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"echo": true,
"reveal": "always", // 执行任务时是否跳转到终端面板,可以为always,silent,never。具体参见VSC的文档
"focus": true, // 设为true后可以使执行task时焦点聚集在终端,但对编译C/C++来说,设为true没有意义
"panel": "shared" // 不同的文件的编译信息共享一个终端面板
},
"detail": "调试器生成的任务。"
},
{
"type": "cppbuild",
"label": "(多文件)gcc.exe - 生成和调试活动文件",
"command": "E:\\mingw64\\bin\\gcc.exe",//改成自己的文件路径
"args": [
"${fileDirname}\\*.c",
"-o",
"${fileDirname}\\bin\\${fileBasenameNoExtension}.exe",//这里意思生成的二进制代码会放入当前文件的bin文件夹中,我们需要自己新建一个bin文件夹
"-g"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"echo": true,
"reveal": "always", // 执行任务时是否跳转到终端面板,可以为always,silent,never。具体参见VSC的文档
"focus": true, // 设为true后可以使执行task时焦点聚集在终端,但对编译C/C++来说,设为true没有意义
"panel": "shared" // 不同的文件的编译信息共享一个终端面板
},
"detail": "调试器生成的任务。"
}
],
"version": "2.0.0"
}

至此设置工作基本结束

C/C++配置环境
next主题的一些设置
发表于2022-11-20|更新于2025-05-21|前端网站建设

Hexo默认 主题的config优先级高于Hexo的config

基于Hexo 6.2 和hexo-theme-next-8.12.1 不同版本设置可能不一样

以下为next主题config设置:

一.网站图标设置

  1. 侧边栏链接图标设置:此版本使用的是 https://fontawesome.com/icons 图标库

next主题设置1

  1. 在social下可以添加链接和图标 e.g Bilibili: 链接地址 || 图标库名称
    tips:有些是fa fa-XXXX 有些是fab fa-XXXX

next主题设置2

  1. 网站站点的图标在本地Hexo\public\images中,在主题favicon中设置

next主题设置3

生成文章默认生成属性

categories有点类似tags,写在文章属性之中,所以需要在文章生成时添加categories属性。
编辑hexo/scaffolds/post.md,在最下面添加一行categories

1
2
3
4
5
6
---
title: {{ title }}
date: {{ date }}
tags:
categories:
---

添加小功能

添加本站运行时间

修改Hexo/themes/next/layout/_partials/footer.njk(footer.swig)文件,在末尾加入如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</br>  //换行
<!-- 网站运行时间的设置 -->
<span id="timeDate">载入天数...</span>
<span id="times">载入时分秒...</span>
<script>
var now = new Date();
function createtime() {
var grt= new Date("04/21/2019 15:54:40");//此处修改你的建站时间或者网站上线时间
now.setTime(now.getTime()+250);
days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days);
hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum); hnum = Math.floor(hours);
if(String(hnum).length ==1 ){hnum = "0" + hnum;} minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum);
mnum = Math.floor(minutes); if(String(mnum).length ==1 ){mnum = "0" + mnum;}
seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);
snum = Math.round(seconds); if(String(snum).length ==1 ){snum = "0" + snum;}
document.getElementById("timeDate").innerHTML = "本站已安全运行 "+dnum+" 天 ";
document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒";
}
setInterval("createtime()",250);
</script>


参考资料:
Hexo官方文档
Next主题文档说明

next
正则表达式
发表于2022-11-06|更新于2025-05-21|学习笔记正则表达式

简介

  1. 定义
    正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为”元字符”)组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配
  2. 为什么使用正则
  • 测试字符串内的模式
    例如,可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式。这称为数据验证

  • 替换文本
    可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它

  • 基于模式匹配从字符串中提取子字符串
    可以查找文档内或输入域内特定的文本

语法

普通字符

普通字符包括没有显式指定为元字符的所有可打印和不可打印字符。这包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号

字符 描述
[ABC] 匹配 [...] 中的所有字符,例如 [aeiou] 匹配字符串 "google runoob taobao" 中所有的 e o u a 字母
[^ABC] 匹配除 [...] 中的所有字符
[A-Z]/[a-z] [A-Z] 表示一个区间,匹配所有大写字母,[a-z] 表示所有小写字母
. 匹配除换行符(\n、\r)外的所有单个字符, 相当于[^\n\r]
[\s] [\S] \s是匹配所有空白符,包含换行 \S匹配非空白符,不包括换行 [\s\S]是匹配所有
\w 匹配字母、数字、下划线。等价于 [A-Za-z0-9_]

非打印字符

字符 描述
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。注意 Unicode 正则表达式会匹配全角空格符。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。

特殊字符

若要匹配这些特殊字符,必须首先使字符”转义”,即,将反斜杠字符\ 放在它们前面。

特别字符 描述
$ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$。
( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。
* 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。
+ 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。
. 匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \. 。
[ 标记一个中括号表达式的开始。要匹配 [,请使用 \[。
? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。
\ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("。
^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,当该符号在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合。要匹配 ^ 字符本身,请使用 \^。
{ 标记限定符表达式的开始。要匹配 {,请使用 \{。
| 指明两项之间的一个选择。要匹配 |,请使用 \|。

限定符

限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。

字符 描述
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于 {0,}。
+ 匹配前面的子表达式一次或多次。例如,zo+ 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
?

匹配前面的子表达式零次或一次。例如,do(es)? 可以匹配 "do" 、 "does"、 "doxy" 中的 "do" 。? 等价于 {0,1}。

{n} n 是一个非负整数。匹配确定的 n 次。例如,o{2} 不能匹配 "Bob" 中的 o,但是能匹配 "food" 中的两个 o。
{n,} n 是一个非负整数。至少匹配n 次。例如,o{2,} 不能匹配 "Bob" 中的 o,但能匹配 "foooood" 中的所有 o。o{1,} 等价于 o+。o{0,} 则等价于 o*。
{n,m} m 和 n 均为非负整数,其中 n <= m。最少匹配 n 次且最多匹配 m 次。例如,o{1,3} 将匹配 "fooooood" 中的前三个 o。o{0,1} 等价于 o?。请注意在逗号和两个数之间不能有空格。

  1. Example:

以下正则表达式匹配一个正整数,[1-9]设置第一个数字不是 0,[0-9]* 表示任意多个数字:


2. <strong>* 和 + 限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个 ? 就可以实现非贪婪或最小匹配</strong> 

    贪婪:下面的表达式匹配从开始小于符号 (<) 到关闭 h1 标记的大于符号 (>) 之间的所有内容。
```<.*>
非贪婪:如果只需要匹配开始和结束 h1 标签,下面的非贪婪表达式只匹配 < h1 >

<.*?>

通过在 *、+ 或 ? 限定符之后放置 ?,该表达式从”贪婪”表达式转换为”非贪婪”表达式或者最小匹配。


定位符

字符 描述
^ 匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与 \n 或 \r 之后的位置匹配。
$ 匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与 \n 或 \r 之前的位置匹配。
\b 匹配一个单词边界,即字与空格间的位置。
\B 非单词边界匹配。

注意:不能将限定符与定位符一起使用。由于在紧靠换行或者单词边界的前面或后面不能有一个以上位置,因此不允许诸如 ^* 之类的表达式。

若要匹配一行文本开始处的文本,在正则表达式的开始使用 ^ 字符。不要将 ^ 的这种用法与中括号表达式内的用法混淆(ABC表示除[…]中的所有字符)

若要匹配一行文本的结束处的文本,则在正则表达式的结束处使用 $ 字符。

正则
游戏叙事技巧
发表于2022-10-23|更新于2025-05-21|游戏制作

1. 冲突

冲突是游戏故事的燃料,也是游戏玩法的燃料,冲突就是故事的核心。 “故事就是冲突(的集合)”

就故事而言,冲突就是:某人想要或需要某物,但其他人或者其他无造成了障碍

冲突是 想要/但 的模式

想要是角色的行动动力,“但” 是玩家所面临的障碍背后的事务,游戏的关卡和任务就是冲突所产生的障碍的实体表现

冲突是必须的,但是冲突的规模并不一定要大,更重要的是与某个角色产生了感情上的联系(共情)

2. 三幕结构

  1. 开始/铺陈

    (故事发生的世界介绍)冲突发生之前的人物、地点、事件

    为了理解故事的任何变化,我们需要对变化之前和之后的情况都有清晰的认识(前后对比)

    我们要理解主角为什么要面对冲突,开始有一个特别重要的因素是诱发事件,这是介绍主角面对主要冲突的活动、事件或行动。通过这个事件让主角意识到冲突的存在

    第一幕和第二幕分割点:主角开始完全致力于解决冲突开始

  2. 中间/对抗

    故事的”精髓”

    第二幕从主角决定致力于解决冲突开始

    第二幕包括:

    • 兑现第一幕设置的内容

    • 铺陈第三幕最终解决冲突的解决方法

    第二幕和第三幕的分割点:主角已经克服许多困难,但仍面临抉择,主角有所顿悟,明白自己需要做什么,但困难在于能否做到

  3. 结尾/解决

3. 原型与故事结构

3.1原型

1. 主角
2. 信使

  • 主要是向主角传递主要冲突(或者潜在冲突),俗称“谜语人”
  • 游戏中可能为NPC或者UI等
    3. 导师型角色
  • 提供知识、技能、建议等
  • 赠与礼物、任务向导(存疑)
  • 为主角提供解决主要冲突的方法或者动机(一般会通过某种方式:死亡、重伤等,来强迫和证明主角成长
    4. 最终BOSS下的主角前期面对的敌人\阻碍
  • 在与最终BOSS决战前阻碍主角前进的敌人\阻碍
  • 可能会转变为主角盟友
  • 帮助主角成长
    5. 搞笑艺人(搞笑担当)
  • 为故事注入喜剧色彩和轻松氛围
  • 即使是严肃紧张的故事也需要某些角色来舒缓气氛
  • (游戏中常用主角的好朋友或者没头脑担当)
    6. 中立角色(左右摇摆)
  • 类似与灰色的、不确定的角色,不值得信任、不能依靠、可能会背叛主角的角色
  • 可能是盟友变敌人,也可能是敌人变盟友,提供反转情节(类似幕后操作)
    7. 反派\最终BOSS

3.2故事结构

1. 平常世界

  • 介绍故事背景,主角日常生活,直面冲突之前生活

2. 引出主要冲突

3. 拒绝\不接受主要冲突

  • 这里主要是在认识到世界的真相(主要冲突)后不愿接受现实
  • 需要导师角色(或某事)来帮助主角改变主意

4. 遇到导师型角色

  • 获取初始道具和新手教程等

5. 开始面对主要冲突

  • 故事正式开始
  • 类似三幕结构的第一幕和第二幕过渡

6. 考验、盟友、敌人

  • 开始深入故事之中

7. 深入面对主要冲突

  • 到达解决主要冲突的地点、时间或者是直面主要冲突之前
  • 通常是个特殊的时间节点或者宏大的建筑

8. 直面主要冲突

  • 全故事最高潮,解决主要冲突

9. 获得解决冲突奖励

10. 回归

  • 解决了主要冲突但平常世界仍有问题亟待解决,带着奖励回到平常世界

11. 英雄归来(复活)

  • 在某些情况下可能会出现主角“失败死亡”的情况,在某种神秘力量作用下主角复活回归打败反派
  • 制造反转

12. 平常世界改善

  • 主角解决主要冲突,平常世界得到改变,反派得到惩罚
  • 主角成长,罪有应得,故事结束

4. 角色和角色弧

主角的描写

  • 玩家要与主角共情,玩家即是主角
  • 主角开始是不完美的、有缺陷的
  • 主角随着故事的发展要有所成长
  • 主角的成长要用行动来反映,要主动的采取行动,不能总是被动的接受命令,发挥主观能动性,否则会导致玩家共情下降,主角塑造失败
  • 吸引玩家,让玩家关心正发生在主角身上的事(可能并不关心主角,但关心发生在他旁边是事)
  • 主角承担解决冲突所要面对的代价(类似于魂类游戏的死亡惩罚),或者在故事中要失去的某些人或物

反派的描写

  • 反派的核心功能是直接或简介的创造主要冲突,将其作为更大目标的一部分
  • 弱小的反派意味着弱小的主角
  • 反派和主角一样,是有自身想法、欲望、想念和计划的角色,他并不是简单的给主角设置障碍的机器
  • 反叛的“坏”是因为他在实现自己欲望的道路上所做的事——为了达到自己的目标,甘愿伤害或者毁灭一切

角色弧(角色发展)

定义:冲突的对抗以及随之而来的角色潜在性格和/或处境的变化称之为弧

  • 任何故事中最明显、最具戏剧性的角色弧几乎总是属于主角的,主角的成长和变化——他的弧——是主角的决定性特征
  • 弧也是由开始、中间、结尾(铺陈、对抗、解决)组成的
    1. 成长弧:记录了一个角色的价值观、他所代表的价值以及他是谁的深刻变化称为成长弧
    2. 处境弧:即使某个人物在故事发展中没有成长或者改变但他的处境发生了变化

5. 阐述

定义:观众理解和欣赏故事所需的信息

  • 处理这些信息最好的办法是用行动去表达出来而不是去说出来,大段的文字对白会导致玩家失去注意力甚至烦躁。要用适当的演出去传达这些信息
  • 最好的方法是让玩家去做,其实是看,最差是直接叙述

播种

  • 叙事的过程应当是有节奏的,循序渐进的

    • 玩家接受信息需要时间去消化,尤其是在故事开始的阶段有大量信息需要玩家去接收,所以在故事开始的时候最忌讳的是:向玩家抛出大量信息
    • 给需要传递的信息给予一个优先级,分批分时机的向玩家传递或者根本不传递
    • 对于一个需要传递的信息,是否暂时保留不传递取决于它能否让玩家感到有趣(留下伏笔,保持神秘感)
  • 对于需要传达的信息可以分为三类

    • 需要知道的,前情提要等
    • 可以等待的,是需要知道的但在当下并不是必要,需要等待时机变为“需要知道的”
    • 次要的,对于整个故事的完整性来说相对不重要的,可能起到锦上添花的作用但去掉也无关紧要的信息
  • 要在适当的时间点补完完前文未交代的信息

植入

在故事中,植入就是确立一些特定的东西,这些东西会在以后变得很重要

  • 从最终的目标开始,然后回溯到过去去完成铺垫
  • 成功植入的关键在于
    1. 以一种无害的方式引入想要植入的内容,同时不会引起不必要的注意
    2. 在铺垫和回收之间留出足够长的时间,最好让观众忘记一开始植入的东西(给人一种恍然大悟的感觉)

伏笔

暗示故事后期会发生或变得更清晰、更重要的事情

  • 伏笔通常是故事的增强元素,而不是核心元素
  • 伏笔和植入相似,但伏笔最初呈现的信息是模糊的,但在后来会变得清晰(类似现在说的竖旗)

6. 故事可信度

故事可信度的关键是说服玩家/观众去相信你创造的虚拟世界和人物,更进一步来说是增强沉浸感不让玩家出戏(保持“搁置怀疑”的状态)

一致性

观众期待任何故事都具有一定的内在逻辑和一致性:世界一致性和角色一致性

  1. 世界一致性
    无论故事中的世界是完全虚拟的、科幻的还是贴近现实的,都应该要使发生在其中的事符合其自身的物理规则,使得能够逻辑自洽。与观众一起制定世界规则,然后遵守这些规则,保持一致性

  2. 角色一致性
    让故事中的角色成为一个真正的人,他所做的所有事都是对他来说有意义的事情,应该是“他接下来会做什么”而不是“接下来我需要让什么事发生”

巧合

  • 用巧合让角色陷入困难是好的,但用巧合让他们摆脱困难是糟糕的
  • 让观众注意不到的巧合是良性的巧合

  • 处理巧合

    1. 改变情节,消除巧合
    2. 回溯翻新,在不该剧情大体走向情况下去改进故事适得他不那么凑巧
    3. 淡化巧合

出其不意

故事的发展应当是意料之外,情理之中,没人会喜欢一眼就能看到结局的故事

  • 创造一个精彩的惊喜
  • 你知道故事会发展到哪里,但不知道故事会怎么发展到那里

奇观

奇观就是大场面,能给人最直观的感官刺激,但一味的追求奇观会导致故事崩坏

7. 个人感悟

人物前进的逻辑关系

人物要获得成长要在前文做一定铺垫,不能让人物成长过于突兀,成长动力不一定是冲突,可以结合人物性格精神等方面,发出类似于普通人想要获得自我突破和成长的想法(激发人内在的、潜意识的向好或向恶)

游戏制作,游戏叙事
装机软件下载网址
发表于2022-10-08|更新于2025-10-15|软件PC

装机软件下载网址

个人常用软件列表,重装系统下软件真的麻烦…

应用类:

TIM:https://tim.qq.com/download.html

火绒:https://www.huorong.cn/

网易云音乐:https://music.163.com/#/download

WeChat:https://weixin.qq.com/

Steam:https://store.steampowered.com/about/

Epic:https://store.epicgames.com/zh-CN/?lang=zh-CN

百度网盘:https://pan.baidu.com/download

Audacity:https://www.audacityteam.org/download/

Mkvtoolnix:https://mkvtoolnix.download/downloads.html#windows

qBittorrent:https://sourceforge.net/projects/qbittorrent/

qBittorrent-Enhanced-Edition:https://github.com/c0re100/qBittorrent-Enhanced-Edition

7-zip:https://www.7-zip.org/

Koodo reader:https://github.com/troyeguo/koodo-reader

Potplayer:https://potplayer.daum.net/

Telegram:https://desktop.telegram.org/

Chrome:Google Chrome

MarkText:https://github.com/marktext/marktext(markdown编辑器)

NeeView:https://bitbucket.org/neelabo/neeview/downloads/(漫画、图片浏览器)

Audacity:https://www.audacityteam.org/(音频剪辑软件)

DaVinCi:https://www.blackmagicdesign.com/products/davinciresolve(视频剪辑)

blivechat:https://github.com/xfgryujk/blivechat(B站直播弹幕工具)

everything:https://www.voidtools.com/(查找文件)

exhentai-manga-manager:https://github.com/SchneeHertz/exhentai-manga-manager(E站漫画管理)

SumatraPDF:https://github.com/sumatrapdfreader/sumatrapdf

Office Tool Plus:https://otp.landian.vip/en-us/(office办公套件破解)

PowerToys:https://github.com/microsoft/PowerToys/tree/(微软官方工具集)

honeyview:https://en.bandisoft.com/honeyview/(看图软件)

工具类:

Vscode:https://code.visualstudio.com/Download

IntelliJ IDEA:https://www.jetbrains.com/zh-cn/idea/download/

Xshell:https://www.xshell.com/zh/xshell-download/

tabby:https://github.com/Eugeny/tabby

Xftp:https://www.xshell.com/zh/xftp-download/

Wireshark:https://www.wireshark.org/#download

Python:https://www.python.org/downloads/

Live2D:https://www.live2d.com/zh-CHS/

Vmware:https://www.vmware.com/products/workstation-player.html

waifu2x-caffe:https://github.com/lltcggie/waifu2x-caffe(二次元画面优化)

Ultimate Vocal Remover:https://github.com/Anjok07/ultimatevocalremovergui(分离人声和伴奏)

aria2:https://github.com/aria2/aria2/releases/

nodejs:https://nodejs.org/en/

Git:https://git-scm.com/downloads

renpy:https://www.renpy.org/(galgame制作软件)

calibre:https://calibre-ebook.com/download(电子书制作)

blender:https://www.blender.org/

geek:https://geekuninstaller.com/download

驱动类:

Epson打印机驱动:https://www.epson.com.cn/services/guidedrive.html

显卡、CPU等驱动:https://tool.pc.wiki/

装机软件
服务器部署Komga漫画阅读器
发表于2022-09-13|更新于2025-05-21|实用工具教程

前言

本地本子存太多了,突发奇想想搭建一个在线看漫画的服务,遂找到了Komga。
下面记录一下如何在服务器的docker上部署

安装步骤

  1. 服务器端需要安装Java环境,至少在JDK17及以上
    • Centos为例:
      1
      2
      3
      4
      5
      6
      7
      8
      #查看云端yum库中目前支持安装的jdk软件包
      yum search java|grep jdk

      #选择版本安装jdk
      yum install -y java-17-openjdk

      #安装完成后,验证是否安装成功
      java -version
  2. Komga的GitHub地址,下载最新版本的jar文件,上传到服务器即可

  3. 在 CentOS 安装

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 在komga中创建子目录
    mkdir config
    mkdir data

    # 创建文件
    cd config
    touch database.sqlite

    # 运行komga,版本号具体而论
    java -jar komga-***.jar
  4. 运行
    在浏览器中输入 http://服务器IP:8080,就能看到主界面了,登录即可
    如果有其它服务在使用8080端口会导致安装失败,把另一个服务暂时关闭即可

  5. docker运行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    docker create \
    --name=komga \
    --user 1000:1000 \
    -p 3080:8080 \ #我这里选择3080端口映射
    --mount type=bind,source=/path/to/config,target=/config \ #/path/to/config 是刚才创建的文件
    --mount type=bind,source=/path/to/data,target=/data \ #/path/to/data 也是刚才创建的文件
    --restart unless-stopped \
    gotson/komga

    #启动docker
    docker start komga

内容部分来自互联网

comic,Komga
IEEE浮点表示(IEEE 754)
发表于2022-09-12|更新于2025-05-21|学习笔记计算机组成原理

简介

浮点数是我们在程序里常用的数据类型,它在内存中到底是怎么样的形式存在的呢?

现代计算机中,一般都以IEEE 754标准存储浮点数,IEEE标准用: V=(-1)^s x M x 2^E 来表示一个浮点数

  • 符号: s决定这个数是正数还是负数
  • 尾数: M是一个二进制小数
  • 阶码: E是对浮点数进行加权,权重是2的E次幂
    符号 阶码 尾数
    sign exponent fraction

对于不同长度的浮点数,阶码与小数位分配的数量不一样,如下:

精度 数符 阶码 尾数 总位数 偏移值
单精度(C中的float) 1 8 23 32 127
双精度(C中的double) 1 11 52 64 1023

对于32位的单精度浮点数,数符分配是1位,阶码分配了8位,尾数分配了是23位。

根据这个标准,我们来尝试把一个十进制的浮点数转换为IEEE 754标准表示。

规格化的值

最普遍的情况,当exp的位模式不全为0(数值0),也不全为1(单精度255,双精度2047)
例如:178.125

  1. 先把浮点数分别把整数部分和小数部分转换成2进制

    1. 整数部分用除2取余的方法,求得:10110010

    2. 小数部分用乘2取整的方法,求得:001

    3. 合起来即是:10110010.001

    4. 转换成二进制的浮点数,即把小数点移动到整数位只有1,即为:1.0110010001 * 2^111,111是二进制,由于左移了7位,所以是111

  2. 把浮点数转换二进制后,这里基本已经可以得出对应3部分的值了

    1. 数符:由于浮点数是正数,故为0.(负数为1)

    2. 阶码 : 阶码的计算公式:阶数 + 偏移量, 阶码是需要作移码运算,在转换出来的二进制数里,阶数是111(十进制为7),对于单精度的浮点数,偏移值为01111111(127)[偏移量的计算是:2^(e-1)-1, e为阶码的位数,即为8,因此偏移值是127],即:111+01111111 = 10000110

    3. 尾数:小数点后面的数,即0110010001

    4. 最终根据位置填到对位的位置上:

      | 数符 | 阶码 | 尾数 |
      |:——:|:——:|:——:|
      |0|1 0 0 0 0 1 1 0|0 1 1 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0|

      阶码与尾数之间隐含小数点

可能有个疑问:小数点前面的1去哪里了?由于尾数部分是规格化表示的,最高位总是“1”
我们将尾数定义为M=1+f,小数字段被描述为小数值f,其中0<=f<1,其二进制表示为:
IEEE浮点表示
也就是二进制小数点在最高有效位的左边。
我们也可以把M看成一个二进制表达式为下图的数字,也总能调整阶码使得尾数M的范围在1到2之间。
IEEE浮点表示_2

既然第一位总是1,那就可以直接隐藏不需要显示出来,同时也能够获得一个额外的精度位。

非规格化的值

当阶码全为0时,所表示的数非规格化的形式。这种情况下,阶码的值是1-Bias,尾数M=f,也就是小数字段的值,不包含隐含开头的1。
非规格化有两个用途:

  • 一是提供一种表示数值0的方法,因为使用规格化的数我们必须使M>=1,无法表示0。
  • 二是表示那些非常接近0的数。

拓展

乘2取整法

考虑一个十进制小数0.123,我们可以用“乘10取整”法得到它的每一位小数:第一位小数是0.123 10=1.23,取整数1;第二位小数:0.23 10=2.3,取整数2

上面的方法供你直观理解,下面我们从数学的角度分析其中的原理。

现在有一个十进制小数为0.625,要把它转换为二进制小数,我们需要找到它的每一位。记这个二进制小数点后第1位是$a_1$,第二位是$a_2$,……,那么这个小数的值就是$ a_1 \ast {\frac{1}{2}}^{-1}+a_2 \ast {\frac{1}{2}}^{-2}+a_3 \ast {\frac{1}{2}}^{-3}+… $ 。现在我们的目标是根据0.625找到对应的$ a_1,a_2,a_3$ ,…使得$ 0.625=a_1 \ast {\frac{1}{2}}^{-1}+a_2 \ast {\frac{1}{2}}^{-2}+a_3 \ast {\frac{1}{2}}^{-3}+… $

在等式两边同时乘以2,得到$1.25=a_1 \ast {\frac{1}{2}}^{0}+a_2 \ast {\frac{1}{2}}^{-1}+a_3 \ast {\frac{1}{2}}^{-2}+…$

我们发现,左边的整数部分1对应右边的$a_1$,也就是二进制小数的第一位,于是$a_1=1$,对于剩下的部分:

$0.25=a_2 \ast {\frac{1}{2}}^{-1}+a_3 \ast {\frac{1}{2}}^{-2}+…$

我们再次乘以2,得到$0.5=a_2 \ast {\frac{1}{2}}^{0}+a_3 \ast {\frac{1}{2}}^{-1}+… $于是$a_2=0$

再乘以2,得到$1=a_3 \ast {\frac{1}{2}}^{0}+…$, 于是$a_3=1$,到这里,所有的数都消耗完了,我们找到了0.625对应的二进制小数:0.101

参考文章:浮点数的二进制表示(IEEE 754标准)

IEEE,浮点数
VsCode配置Java环境
发表于2022-09-07|更新于2025-05-21|编程环境配置Java

安装Java

安装最新版(最新版VsCode安装jdk1.8会弹窗警告,所以不如使用最新版)
下载地址:Java

Tips: 如果你需要运行java程序,只需安装JRE就可以了。如果你需要编写java程序,需要安装JDK。
有关两者关系也可以查看官方文档

选择对应系统的版本即可:

  • Compressed Archive版本是单独的JDK包

  • Installer版本是Java安装包,包含了Java运行程序,第一次配置Java环境最好下载这个

VsCode配置Java环境_1

配置Java环境变量

1. 打开系统环境变量

  • 方法1:选中我的电脑 —> 键盘按下 Alt + Enter —> 高级系统设置 —> 环境变量
  • 方法2:键盘按下 win + r —> 输入 sysdm.cpl —> 高级 —> 环境变量
  • 方法3:win10系统下,工具栏有搜索图标,点击后直接搜索”环境变量”

2. 设置环境变量

在 “系统变量” 中设置 3 项属性,JAVA_HOME、PATH、CLASSPATH(大小写无所谓),若已存在则点击”编辑”,不存在则点击”新建”。

变量设置参数如下:

1
2
3
4
5
6
变量名:JAVA_HOME
变量值:C:\Program Files (x86)\Java\jdk1.8.0_91 // 要根据自己的实际路径配置
变量名:CLASSPATH
变量值:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar; //记得前面有个"."
变量名:Path
变量值:%JAVA_HOME%\bin; //如果安装了jre需要添加个%JAVA_HOME%\jre\bin;

3. 测试是否配置成功

1. "Win+R",键入"cmd";

2. 键入命令: java -version、java、javac 几个命令,出现以下信息,说明环境变量配置成功

VsCode配置Java环境_2

Vscode配置

  1. 下载对应Java插件
    这里使用Extension Pack for Java 里面包含6个可能会用的到插件(Java11以下版本的jdk会弹出警告)

VsCode配置Java环境_3

  1. 设置java路径
    打开vscode设置(Ctrl + ,) —> 搜索设置输入 javahome —> 点击 Java: Home下的在settings.json中编辑,如下:
    其中,第一行是JAVA_HOME的路径,记得把 “ \ “ 改成 “ \ \ “

VsCode配置Java环境_4

调试运行

新建hello.java,输入代码,测试运行即可

1
2
3
4
5
6
// Hello.java
public class Hello {
public static void main(String[] args) {
System.out.print("I am Hello Class, which is a main class");
}
}

参考文章:
Visual Studio Code (vscode) 配置 Java 环境

Java 开发环境配置

配置环境Java
在虚拟机中设置静态Ip(centos为例)
发表于2022-09-03|更新于2025-05-21|学习笔记Linux

一、虚拟机设置

在菜单栏选择编辑→ 虚拟网络编辑器,打开虚拟网络编辑器对话框,选择Net网络连接方式,随意设置子网IP,点击NAT设置页面,查看子网掩码和网关,后面修改静态IP会用到。

在VMnet8模式下选择nat连接,并且取消DHCP服务。

设置静态IP_
点击NAT设置,记录下此时的网关

设置静态IP_2

在系统的网络设置处,检查VMnet8的网络配置

设置静态IP_3

二、Liunx主机设置

  1. 在root权限下输入命令 cd /etc/sysconfig/network-scripts 进入该文件夹,输入命令 ls 浏览该文件夹下的文件,找到ifcfg-en***文件,如下图所示:

设置静态IP_4

  1. vim ifcfg-en***打开文件

  1. 将BOOTPROTO=”dhcp”改为BOOTPROTO=”static”、ONBOOT=”no”改为ONBOOT=”yes”

并在下方添加

1
2
3
4
5
6
7
8
9
10

IPADDR=*your ip*(静态IP地址)

NETMASK=*your netmask*(子网掩码,一般为255.255.255.0)

GATEWAY=*your gateway*(网关地址)

DNS1=8.8.8.8(国内外公共DNS即可)

DNS2=8.8.4.4

  1. 最后输入:wq退出即可
Linux网络配置
1…3456
avatar
Hiyoung
若无闲事挂心头,便是人间好时节
文章
51
标签
75
分类
31
Follow Me
公告
网站破后重生,变得更加花哨!
最新文章
飞牛NAS备忘录2025-10-20
安卓实用软件记录2025-10-15
github pages 使用自定义域名2025-05-21
hexo引用站内文章2025-05-21
MacOS上配置Hexo教程2025-05-21
分类
  • 二次元1
    • 《路人女主的养成方法》1
  • 前端11
    • CSS2
    • 网站建设9
  • 学习笔记8
    • C++2
    • Linux2
标签
nas飞牛OS路人女主的养成方法霞之丘诗羽完结读评加藤惠完结后有感丸户史明游戏制作,游戏叙事CppC++CcppSTLstring字符串HexohexoMacOSMarkdown
归档
  • 十月 20252
  • 五月 20253
  • 一月 20251
  • 十二月 20246
  • 十月 20241
  • 七月 20241
  • 三月 20242
  • 一月 20241
网站资讯
文章数目 :
51
已运行时间 :
本站总字数 :
96.2k
最后更新时间 :
©2020 - 2026 By Hiyoung
Love from nobody!
搜索
数据库加载中