Coding【C#】List排序的方法List.Sort的使用

最近准备做一个回合制战斗的游戏,在游戏设计时,考虑到需要将所有可操作角色按照他们的速度进行排序,以来确定攻击顺序,用到了List.Sort方法,经过查看MSDN文档搞明白了怎么用,进行记录并分享。

List.Sort在默认不带参数的情况下,可以对String和Int等进行排序,而我的List中是一个类,我需要将List按照类中的Speed属性进行排序,具体方法是我们用到List.Sort 方法 (IComparer)来进行排序。

首先我们需要写一个继承自ICompare的排序函数:

/// <summary>
/// 一个针对IActItem的排序,按照Speed从大到小排序。
/// </summary>
public class SortBySpeed : IComparer<IActItem>
{
    /// <summary>
    /// 对比函数,名字不需要进行修改
    /// </summary>
    /// <param name="a">进行对比的左项</param>
    /// <param name="b">进行对比的右项</param>
    /// <returns>返回一个整形,这个整形代表左项需要移动的位置,列表顺序从左向右,-1为向左移(排在前面),1为向右移(排在后面),0为不移动</returns>
    public int Compare(IActItem a, IActItem b)
    {
        if (a == null)
        {
            if (b == null)
            {
                //如果两个都为null,则不进行排序
                return 0;
            }
            else
            {
                //a为null,b不是null,则b>a,将a向右移动1个位置
                return 1;
            }
        }
        else
        {
            if (b == null)
            {
                //b为null,a不是null,则a>b,将a向左移动1个位置
                return -1;
            }
            else
            {
                //如果a和b都不为null,则进行Speed属性对比
                if (a.Speed > b.Speed)
                {
                    //a的速度更快,排在b前面
                    return -1;
                }
                else
                {
                    //a的速度慢,则排在b后面
                    return 1;
                }
            }
        }
    }
}

之后我们只需要进行Sort调用即可:

SortBySpeed sbs = new SortBySpeed();
actList.Sort(sbs);

这样我们就完成对actList的排序,速度越大的排在越前面,按照顺序进行攻击。

更详细的使用方法可以查看MSDN文档

CodingWordPress后台无法登录的解决办法

新买的主机,装上wordpress后,有时会出现无法登录的问题。一直没有找到原因,今天实在受不了了,分析了一下wordpress的登录代码,最终找到了解决办法。

现象:

在网址后输入 wp-admin 后,跳转到登录也,输入用户名和密码,密码正确,提交后,刷新当前页面,不进入后台(仪表盘)。

解决办法:

在博客根目录下,有一个文件 wp-login.php ,这个文件是实现登录的。在我们输入 /wp-admin 这个网址后,会默认跳到 wp-login.php 以实现登录。问题就出在这里。

用编辑器(记事本也可)打开 wp-login.php 文件,找到以下代码:

<input type="hidden" name="redirect_to" value="<?phpecho esc_attr($redirect_to);?>" />

在这行代码之前,有一行代码:

<?php } else { ?>

将其修改为:

<?php
} else {
if (!strpos($redirect_to,'index.php')){
$redirect_to = $redirect_to.'index.php';
}
?>

保存,备份原文件,将修改后的文件上传覆盖即可。

————————————————————————————————————————

以下之前在百度搜出来的解决办法,试用后无效。

登陆后台目录 打开文件/wp-includes/pluggable.php ,修改wp_set_auth_cookie函数 在pluggable.php文件找到以下代码:
setcookie($auth_cookie_name, $auth_cookie, $expire, ADMIN_COOKIE_PATH, COOKIE_DOMAIN, $secure, true);
把它替换成: setcookie($auth_cookie_name, $auth_cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN, $secure, true);

 

CodingLua中协同程序coroutine与yield用法详解

Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

而现在很多地方都会用到Lua语言,例如魔兽插件、剑网三插件、各种其他程序扩展、热更新等,所以这几天正在学习一下Lua语言,做技术储备。

而在Lua的学习过程中,大部分都很容易理解,唯独协同程序Coroutine一直理解不了。于是上网查了很多人的解释,加上测试,最终明白了其用法,分享出来,与大家交流。

本文只解释一下遇到的问题,所以你需要看过基本的Lua语法,了解基本的协程运作方式。

首先看下面的代码:

function foo (a)
    print("foo 函数输出", a)
    return coroutine.yield(2 * a) -- 返回  2*a 的值
end
 
co = coroutine.create(function (a , b)
    print("第一次协同程序执行输出", a, b) -- co-body 1 10
    local r = foo(a + 1)
     
    print("第二次协同程序执行输出", r)
    local r, s = coroutine.yield(a + b, a - b)  -- a,b的值为第一次调用协同程序时传入
     
    print("第三次协同程序执行输出", r, s)
    return b, "结束协同程序"                   -- b的值为第二次调用协同程序时传入
end)
        
print("main", coroutine.resume(co, 1, 10)) -- true, 4
print("--分割线----")
print("main", coroutine.resume(co, "r")) -- true 11 -9
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- true 10 end
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine
print("---分割线---")

在协程coroutine中,当调用coroutine.yield方法时,协程coroutine会挂起,当下一次调用coroutine时会从yeild的地方继续执行。而其中让我摸不着头脑的地方,便是resume时和yield时的参数传递了。

如果coroutine.create里的函数有参数的话,那么第一次在resume中传递的参数,便是给create中函数传递的参数。

之后会执行到return coroutine.yield(2 * a),这时需要注意:协程coroutine被挂起,print会输出协程coroutine的执行结果,而且会输出coroutine.yield(2 * a)的结果。所以第一次分割线之前的输出是这样的:

第一次协同程序执行输出	1	10
foo 函数输出	2
main	true	4

之后,虽然有local r = foo(a + 1),但foo函数中的return并没有将coroutine.yield中的参数(或者说返回给resume的执行结果)返回,所以2 * a并没有赋值给r。而赋值给r的其实是第二次调用resume时传递的参数。

在第二次调用resume时,除了co还传递了一个字符串参数"r",而这个参数将会成为foo函数的返回值,并被赋值给r。resume时可以传递多个参数进去,但之前的yield中只有一个参数,其余的参数会被忽略。如果在resume时不传递参数,而yield中有参数,那么返回值则为nil,则r为nil。在这一次的yield中有两个参数,a+b和a-b,a和b是第一次调用时传递进来的参数,所以会返回他们计算的结果。

当传递参数为"r"时,第二次分割线之前的输出是这样的:

第二次协同程序执行输出	r
main	true	11	-9

搞懂了这两次的输出,后面的也就不难理解了。

当创建协程coroutine时,默认会挂起,只有在调用resume时才会被执行,当yield时会被再次挂起。第一次传递的参数会被传入create的函数中,而之后的参数传递,都是传递给yield的。并且yield中的参数会加入到resume的返回结果。

上面代码的所有输出如下:

第一次协同程序执行输出	1	10
foo 函数输出	2
main	true	4
--分割线----
第二次协同程序执行输出	r
main	true	11	-9
---分割线---
第三次协同程序执行输出	x	y
main	true	10	结束协同程序
---分割线---
main	false	cannot resume dead coroutine
---分割线---

以上分享为个人理解,如有错误欢迎指正。希望对大家有所帮助。

CodingPHP中Apache的虚拟目录设置

之前做PHP,一直用的UwAmp这种工具,傻瓜式的创建虚拟目录,一直没看过到底是怎样一回事。好久没玩PHP了,今天更换了XAMPP,于是看了一下虚拟目录的生成,发现挺简单的。

httpd.conf最后加入如下代码即可:

<VirtualHost *:81>
# Generate Virtual Host
	DocumentRoot "C:\wwwroot\"
	ServerName "localhost"
</VirtualHost>

CodingGit教程:本地代码推送至Git服务器

有时候我们不只是会在Git@OSC或者Github上新建项目,然后clone到本地,也有可能是本地已经用Git提交过,然后需要推送至服务器上,这边文章会告诉你该怎么做。

首先,我们需要生成SSH-KEY,在Git Bash中,输入ssh-keygen,然后输入保存地址以及密码。

生成的.pub文件,用记事本打开,复制里面的内容,添加到Git平台的SSH公钥中,具体方法参考各平台说明。

这里假设,你已有本地仓库,且已提交过,并且在Git平台上已创建项目,那么开始添加远程地址:

git remote add origin https://github.com/yourID/repoName.git

红色字代表你的远程仓库地址

然后如果Git平台给你智能生成过gitignore文件的话,那需要先用下面命令pull一次

git pull origin master

之后,就可以push了

git push -u origin master

这样,你本地的代码仓库就会同步至Git平台了

CodingUEditor中JS代码(script标签)被过滤的解决办法

作为一个程序员的博客,在文章中经常会插入各种代码,大部分代码都不会发生问题,但Div和Script标签是经常会被使用到的。

而在之前的文章编写过程中,插入JS代码后,第一次文章会显示正常,而之后在后台编辑器中便只会显示执行过的JS代码,相当于JS代码被过滤掉了。今天研究了一下这个问题,发现解决办法很简单。

我们在插入代码后,源码模式下,看起来是正常的,但是为什么保存完之后,数据库中正常,但是编辑器中不正常呢?

很多富文本编辑器都有两种初始化方式,以UEditor为例,一种是textarea标签,一种是script标签。

textarea方式:

<textarea id="container" name="content">
    这里写你的初始化内容
</script>
<script type="text/javascript" src="ueditor.config.js"></script>
<script type="text/javascript" src="ueditor.all.js"></script>
<script type="text/javascript">
    var ue = UE.getEditor('container');
</textarea>

script方式:

<script id="container" name="content" type="text/plain">
    这里写你的初始化内容
</script>
<script type="text/javascript" src="ueditor.config.js"></script>
<script type="text/javascript" src="ueditor.all.js"></script>
<script type="text/javascript">
    var ue = UE.getEditor('container');
</script>

两种方式的区别也只在于容器,我之前一直使用的是textarea方式,因为当时UEditor的script方式有一些小问题。

在今天寻找过滤问题的解决办法时,想了很多办法,看别人的配置文件等,但终究没解决。在不断搜索中,打开UEditor之前的帮助文档,现在官网已经去除了该旧文档的链接,在该文档中看到了这样一个问题:

大部分编辑器的容器都使用textarea,为什么UEditor采用了很特殊的script标签?

答:首先要说明一点的是,UEditor也支持textarea标签作为编辑器的外围容器,只要将对应的标签名字换成textarea即可。除此之外,UEditor还支持使用div和script标签作为其容器。之所以要这样做,只是为了尽最大可能去满足和适应用户的各种不同需求。官方推荐使用script标签的原因是textarea会在提交数据的时候自动对里面的部分html文本进行一次特殊字符转义,从而导致有些不熟悉的用户在再编辑的时候出现编码混乱的问题。而使用script标签可以很好地克服这个缺点。

里面提到了“官方推荐使用script标签的原因是textarea会在提交数据的时候自动对里面的部分html文本进行一次特殊字符转义”,看到这句话后豁然开朗,一切问题的根源都在于容器标签而已,将容器标签修改为script后,一切都正常了。

Coding【C#】使用Split将字符串分割为数组

在编码中,我们经常会将数组组成字符串保存。而将字符串在分割为数组,同样常用。

今天正好用到了Split方法来分割字符串,于是记录下来。

1. 单个字符分割字符串

string text = "abc,def,ghi";

,分割这个字符串,使用String.Split 方法 (Char[])即可,代码如下:

string[] result = text.Split(new Char[] { ',' });

2. 使用字符串分割字符串

string text = "abcrndefrnghi";

我们需要使用rn分割此字符串,而rn本身就是字符串,并非单个字符,所以就要用到String.Split 方法 (String[], StringSplitOptions)

第二个参数StringSplitOptions拥有两个值,分别为RemoveEmptyEntriesNone

RemoveEmptyEntries代表分割后,删除空元素;None代表不删除空元素。

我们并不删除空元素,所以使用如下代码进行分割:

string[] result = text.Split(new string[] { "rn" }, StringSplitOptions.None);

两种方法都很简单易懂、易于使用。

Coding【C#】获取网页内容及HTML解析器HtmlAgilityPack的使用

最近经常需要下载一些东西,而这个下载地址又会经过层层跳转,每个页面上都有很多广告,烦不胜烦,所以做了一个一键获得最终下载地址的小工具。使用C#,来获取网页内容,然后通过HtmlAgilityPack获取某a标签的href,不断循环,层层跳转,最后获得最终下载地址。

下面,介绍HtmlAgilityPack的使用方法,这个方法也是从网上很多篇文章中拼凑摸索出来的,因为找了一大圈根本找不到HtmlAgilityPack的文档……

首先,using HtmlAgilityPack;

代码片段:

string url = "http://www.baidu.com/";
HtmlWeb htmlweb = new HtmlWeb();
HtmlDocument htmldoc = htmlweb.Load(url);
HtmlNodeCollection hnc = htmldoc.DocumentNode.SelectNodes("//div[@class='s_btn_wr']//input[@class='s_btn']");
string text = hnc[hnc.Count - 1].Attributes["value"].Value;

要点:

htmlweb.Load:参数为url地址,功能是加载url页面内容到htmldoc这个对象中。

HtmlNodeCollection:是一个集合,包含多个节点,它有count属性,可以获取数量,获取最后一个节点使用hnc[hnc.Count – 1]。

htmldoc.DocumentNode.SelectNodes:选择所有匹配的节点,参数为XPath语法,可以搜索W3CShool的语法说明,我这里的意思是获取包含class等于s_btn_wr的div下面的class等于s_btn的input节点。

hnc[hnc.Count – 1].Attributes["value"].Value:获取最后一个节点的value的属性值。

基本了解了上面的内容之后,我想你已经基本能够完成你想做的功能了。

Coding对Typecho的附件上传至七牛云存储的改造

七牛云存储是个好东西,免费的量很多,所以就把自己博客的图片都上传至了七牛,加速访问。

但是最近考虑换成 typecho,由于空间是在国外买的,速度并不快,所以决定将附件上传至七牛,加速访问。(目前还在SAE)

对 typecho 不太熟,所以研究了很久,而且使用的是非常笨拙的方法。

先将七牛sdk的qiniu文件夹复制到 typecho 中的 var 目录下。

修改 var/Widght/Upload.php 文件:

在 if (isset($file['tmp_name'])) { 这一行(大约118)上面添加:

$qn_filename = "";

在 if (isset($file['tmp_name'])) { 这一行下面添加:

require_once("qiniu/io.php");

require_once("qiniu/rs.php");

$bucket = "Bucket名称";

$accessKey = '你的AK';

$secretKey = '你的SK';

$qn_filename = date("Ymd")."/".  (string)time() . (string)rand(11111, 99999);

Qiniu_SetKeys($accessKey, $secretKey);

$putPolicy = new Qiniu_RS_PutPolicy($bucket);

$upToken = $putPolicy->Token(null);

$putExtra = new Qiniu_PutExtra();

$putExtra->Crc32 = 1;

Qiniu_PutFile($upToken, $qn_filename, $file['tmp_name'] , $putExtra);

$qn_filename 定义的是上传后的文件的名字,你可以根据你自己的需要修改。

最后将返回的数组中的 path 改为 'path' => $qn_filename, 即可。

同时,由于 typecho 会自动在返回的文件名前加上当前域名,所以还需要修改添加进文章时的URL。但是我找不到这个URL到底从哪里传入的,没有找到好的办法,所以通过一个比较笨的办法解决。

打开 admin/editor-js.php 文件,在265行插入以下代码:

url = url.replace(/localhost/g,"trlanfeng-website.qiniudn.com");

注:localhost为你的域名

当添加完成后,js会自动修改需要插入的URL,至此,typecho上传附件至七牛云存储就改造完成了,但这是一个本办法,如果有谁有更好的办法,欢迎分享。

CodingPHPStorm8与Xdebug配合断点调试php程序

PHPStorm是一个非常强大的PHP IDE,而Xdebug是目前使用最广泛的php调试工具。

通过PHPStorm和Xdebug配合,能够非常方便的调试php程序。

声明:部分图片及内容来源于 http://my.oschina.net/pureboys/blog/69485 (似乎是所有的),配置步骤也是通过此篇博客学习的。

基本环境:

WampServer 2.5

PHPStorm 8

最终效果图:

配置步骤:


一、配置php.ini,完成后重启Wamp

[xdebug]

;显示默认的错误信息  

xdebug.remote_enable = on

xdebug.profiler_enable = off

xdebug.profiler_enable_trigger = off

xdebug.profiler_output_name = cachegrind.out.%t.%p

xdebug.profiler_output_dir = "f:/wamp/tmp"

xdebug.remote_handler=dbgp

;设置xdebug的端口为9001

xdebug.remote_port = 9001

;设置idekey

xdebug.idekey="PHPSTORM"

二、