效果最接近《羊了个羊》(卡牌堆叠游戏)的开源代码,有数据库和关卡。
我写的程序是指 卡牌堆叠游戏 ,效果与羊了个羊一致。本教程有两个版本
PHP 使用 PHP + H5 + CSS + JS + MySql 实现。
H5 使用 H5 + CSS + JS 实现 。
MieGame_C_Core 代码链接:
Github:https://github.com/MR-XieXuan/MieGame_C_Core
CandyMieGame_PHP(注意获取V0.0.0版本的代码):
Github: https://github.com/MR-XieXuan/CandyMieGame_PHP
CandyMieGame_H5(注意获取V0.0.0版本的代码):
Github: https://github.com/MR-XieXuan/CandyMieGame_H5
微信小程序版本 :
https://blog.csdn.net/apple_53792700/article/details/128041151
目录
逻辑实现我最先是使用 C++ 进行的,后面迁移到了 JS 。C++ 实现的牌堆代码已开源,并且注释写的也很明确,有问题可以在网站底部联系我,我很乐于回答你们的问题。
好的,回到问题。我的牌堆实现思路如下:
n 种牌z 张相同的牌可以被抵消N = kz (k属于正整数) 张牌F 格,满了即被消除1 - Nx 距离内,小号牌为暗牌 牌的大小为 2xx,y,t,a ) [位置与类型与亮暗]有些规则可能后面我会有所改动,但是我都会一一讲解。实在有疑问也可以联系我。
MieGame_C_Core 代码链接: https://github.com/MR-XieXuan/MieGame_C_Core
不要忘记了 Star 和 Fork 哦,还有关注和爱心。
MieGame 方法定义 :
class MieGame {
public :
// 放置一张牌
uint8_t place_a_poker(int x, int y, uint8_t type);
// 拿走一张牌
uint8_t takeaway_a_poker(int number); // 通过编号拿走
uint8_t takeaway_a_poker(int x, int y); // 通过位置拿走
// 更新亮暗状态
void refresh_poker_a();
// 获取亮暗状态
uint8_t get_poker_a(int n);
uint8_t get_poker_x(int n);
uint8_t get_poker_y(int n);
uint8_t get_poker_t(int n);
private:
int amount = 0; // 牌的总数
uint8_t pokerBitmap[63] = {0}; // 最多容纳 504 张牌
int pokerPosition[504][4] = {0}; // [牌号][位置x,位置y,类型t,亮暗a]
char Get_bit( uint8_t * st , char num ){
return ( st[(int)(num/8)] & (0x01 << (num % 8) ) ) > 0 ? 1 : 0 ;
}
void Set_bit( uint8_t * st , char num ){
st[(int)(num/8)] |= (0x01 << (num % 8) ) ;
}
void Res_bit( uint8_t * st , char num ){
st[(int)(num/8)] &= ~(0x01 << (num % 8) ) ;
}
};
牌的总数 , 每放置一张牌都会加一,但是拿走一张牌却不会减。
bitmap 牌是否被拿走,是一个bitmap列表,被拿走为0,没有被拿走为1
牌的信息 [牌号][位置x,位置y,类型t,亮暗a]
uint8_t place_a_poker(int x, int y, uint8_t type);
在指定位置放置一张指定类型的卡牌
uint8_t takeaway_a_poker(int number);
以编号的形式拿走一张牌,返回值是 。。。好像没有写,到时候更新。
uint8_t takeaway_a_poker(int x, int y);
以位置的形式拿走一张牌,比如一张牌大小为 4*4 位置在 (2,2) 则输入的是(1,1)也可以拿走这张卡牌,只要卡牌覆盖了这个位置且卡牌为亮牌。返回值为这张牌的类型,如果没有拿走牌,则返回 0 。
void refresh_poker_a();
刷新牌堆的亮暗状态。
uint8_t get_poker_a(int n);
uint8_t get_poker_x(int n);
uint8_t get_poker_y(int n);
uint8_t get_poker_t(int n);
获取 编号为 n 的牌的 a(亮暗状态) x(x位置) y(y位置) t(Type类型)。
位操作,通过位操作来操作与获取bitmap的内容 ,Get是获取指定位 ,Set是把指定位变为1,Res是把指定位变为0。这是一个很简单的操作,基础不好的可以多看几遍。也不是太难理解的,我这里讲解一下 Res_bit 的实现,看懂了Res_bit 其他的都很好理解。
void Res_bit( uint8_t * st , char num ){
st[(int)(num/8)] &= ~(0x01 << (num % 8) ) ;
}
Res_bit 需要传入两个参数,第一个是stbitmap的首位地址,第二个num是需要操作的位置。
我们假设我们的num是12 st传入了一个bitmap,数据为 0b1011111111111111 是从低位往高位读,不要读反了(从右往左)。
从右往左分析,0x01 也就是 16进制的1,<< 左移 , (num%8) 操作的位置除以8取余数也就是 4 。 0x01<<(num%8) 也就是1<<4 也就是二进制的00010000(现在计算机最小的单位是8个字一个字节,也就是8位二进制),~ 取反 也就变成了11101111。
st[(int)(num/8)] C语言强制类型转换是去掉小数部分,只保留整数部分的,也就是说(int)(12/8)就为 1 。 把 st[1] &= 0b11101111 (0b是二进制的意思,但是一般编程语言不支持直接这样子操作二进制)展开也就是 st[1] = st[1] & 0b11101111 。
也就是让 0b10111111 与 0b11101111 做并操作 得 st[1] = 0b10101111 。
最后结果就是 传入的这个bitmap从 0b1011111111111111 变成了 0b1010111111111111 第 12位变成了0。
更多关于Bitmap的可以去我的主页搜索Bitmap获取
你需要再你的服务器中创建 Mysql 库 ,库的结构在 文件 SQL.md 中。
并且在文件index.php中填写入你访问数据库的账号与密码
$sqlname = "";
$sqlpassword = "";
并且运行文件 SQL.md中的命令。
打开index.html文件后,打开开发者工具,并且切换到设备仿真模式选中iphone SE,然后刷新。
如果你的控制台输出了 :
Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported. at cut_img_loding
请使用 file协议 再次打开浏览器 。
使用file协议打开浏览器的方式如下:
CMD 运行
chrome.exe --allow-file-access-from-files index.html
chrome.exe 替换成自己电脑中 chrome.exe 的路径 ,index.html 替换成自己下载好后 CandyMieGame_H5 中index.html 中的路径 。
在写完地图(json文件)后,把文件放在map\level\文件夹下并且
需要在数据库 miegame 中表 level 中添加字段 代码如下:
INSERT INTO `level` (`id`, `address`, `level`, `trytasnum`, `tasnum`) VALUES ([第几关], [json存放路径], 4, 0, 0);
在写完地图(json文件)后,把文件放在map\level\文件夹下
命名为 【level】 + 【第几关】+ 【.json】
修改setup.js文件中window.level_amount的值为最新的关卡数。
直接访问程序即可,此地址:CandyMieGame: https://game.mrxie.xyz
我服务器用的CF的CDN,所以速度较慢,且配置拉跨。首次加载时间较长。需要等待一会儿。
(PS:我经常需要加载25s左右)
电脑请切换到 设备仿真模式 iphone SE 下使用。
MieGamePoker主要控制牌堆的处理逻辑。
该对象内的成员变量有:MIEGAME_POKERAMOUNT_MAX牌堆的最大容量,POKERTYPE_AMOUNT现牌堆有牌类型的数量,POKER_REMOVE_NUM已经被取走的牌的数量,POKER_SIZE扑克牌在地图中的边长(正方形),amount现牌堆有牌类型的数量,residue除去被被拿走的,剩余牌的数量,pokerBitmap牌是否被拿走的列表(bitmap),pokerPosition牌的信息。
该对象内的方法有:
place_a_poker放置牌,takeaway_a_poker拿走牌,refresh_poker_a刷新牌堆亮暗信息,get_poker_a获取牌的亮暗信息,get_poker_x获取牌的x位置,get_poker_y获取牌的y位置,get_poker_t获取牌的类型,get_poker_have获取牌是否被拿走,Set_bitBitmap置位1,Res_bitBitmap置位0,Get_bit获取Bitmap的位。
其中外部主要用到的方法有前3个,分别为place_a_poker放置牌,takeaway_a_poker拿走牌,refresh_poker_a刷新牌堆亮暗信息。
具体的实现代码可以查看miegame.js文件。
MieGamePoker主要控制消除区的处理逻辑。
该对象内的成员变量有:
pokerMap现在消除区有的牌列表,pokerAmount现在消除区有的牌的数量。
该对象内的方法有:
place_a_poker放置一张牌到消除区,eliminate_pokers对消除区的牌进行消除,get_poker_fall获取消除区的牌是否已经堆满。
其中外部主要用到的方法有前3个,分别为place_a_poker放置牌,takeaway_a_poker拿走牌,refresh_poker_a刷新牌堆亮暗信息。
具体的实现代码可以查看miegame.js文件。
整个游戏都在一个 convas 画布上工作,要让这个画布充满屏幕,就应该把body的边框全部设为0;
<body onload="" onclick="" onmousemove="" style="border: 0; margin: 0; touch-action: none;">
<div id="canvas_div">
</div>
</body>

CandyMieGame 游戏界面(左图)分为 5 个区,分别为 head头 , map地图区 , fre释放牌区 ,props 道具区 。 因为用户设备的屏幕大小不确定,所以我们的布局也要按照用户的设备来自适应。
if (wh >= 0.45 && wh <= 0.5){
window.headerSize = [window.prW * 0.9, window.prW * 0.1];
window.headerPosition = [window.prW * 0.05, window.prW * 0.05 + prH * 0.05];
window.mapSize = parseInt((prW) * 0.9);
window.mapPosition = [parseInt((prW - mapSize) / 2), parseInt((headerPosition[1] + headerSize[1]) + prH * 0.03)];
window.frePosition = [parseInt(mapPosition[0]), parseInt((mapPosition[1] + mapSize) + prH * 0.03)];
window.freSize = [parseInt(mapSize), parseInt(prH * 0.1)];
window.canPosition = [parseInt(0), parseInt((frePosition[1] + freSize[1]) + prH * 0.02)];
window.canSize = [parseInt(mapSize), parseInt(mapSize / 7)];
window.canPosition[0] = (parseInt(prW - window.canSize[0]) / 2);
window.propsPosition = [parseInt(mapPosition[0]), parseInt((canPosition[1] + canSize[1]) + prH * 0.03)];
window.propsSize = [parseInt(mapSize), parseInt(prH * 0.1)];
}
在程序的最开始就按照用户操作界面的chan宽比开始分配这些区应该在哪些位置,大小应该是多少。
如下图,在长宽比不同时,各个区会以不同的方式展示在用户的屏幕上,这样子不仅可以保证用户良好观感外还能改善用户的操作体验,比如细长的屏幕就要将地图放的更靠下。方形的屏幕可以将道具区放到右边,释放牌区放到左边。

拥有各个区的大小以后,我们要将用户界面和游戏地图联系起来,游戏地图大小为(12*12), 而用户界面的大小却为 (420,420).所以我们需要创建一个方法来建立游戏界面与用户界面的联系
window.communicate = new CanvasCommunicatGame(
window.gameJson.mapSizeW,
window.gameJson.mapSizeH,
mapSize,
mapSize
);
CanvasCommunicatGame 对象我定义在文件 miegame.js 中 。
里面共有4个方法。cw_to_gw界面x转游戏x,ch_to_gh界面y转游戏y,gw_to_cw游戏x转界面x,gh_to_ch游戏y转界面y。
有4个方法以后就可以轻易的让用户界面与游戏核心建立联系,。
在设计时,设置的用户放地图的界面为正方形的,所以地图设计也应该为正方形的,这样子打印出来以后,地图才不会变型。
miegame_put_background(); 函数会将除游戏以外的元素展现到用户的界面上。再把地图打印在应有的位置上。同时,箭头用户鼠标按下的动作,并且对应实现操作。
document.getElementById("botton_canvas").addEventListener("click", function (event) {
get_mouse_pos(document.getElementById("botton_canvas"), event);
});
这个版本的程序并没有加入过多动画,如果需要加入动画的话,就应该实时刷新画布,而不是在用户有操作后再刷新画布。
实际上我这个服务层的设计是草草了事的,很多东西都没有做。这里主要讲解一下 PHP 与 MySQL 数据库的交互。
服务器获取Post表单的数据,ask为必须要有的数据 , 他表示现在如果没有 就默认为 ask = "main" 处理。
当ask为 main时返回地区的星星数量。为level时为关卡地图请求。为newgame时为新游戏请求。
如果你的服务器没有经过DNS服务,那么用最简单的方法就可以了。$ip = $_SERVER['REMOTE_ADDR']但是我的服务器经过了CloudFlare简称CF的DNS服务。那么久不可以通过上面的那个代码来获取用户的IP地址了,否者获取到的IP地址就是CF的DNS服务器的地址了。因为CF的IP报文可能不一定,Key有几种可能,所以我们为了使用方便,封装成了一个函数:
function GET_IP()
{
global $ip;
if ($_SERVER['HTTP_CF_CONNECTING_IP'])
$ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
else if ($_SERVER['REMOTE_ADDR'])
$ip = $_SERVER['REMOTE_ADDR'];
else if ($_SERVER['HTTP_X_FORWARDED_FOR'])
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
else if ($_SERVER['HTTP_CLIENT_IP'])
$ip = $_SERVER['HTTP_CLIENT_IP'];
else
$ip = "Unknow";
return $ip;
}
这样子调用 GET_IP 方法就可以获取到用户的IP了。
因为 IPV4 是动态分配的,所以不可以通过IP直接来确定用户的地理位置,只能通过IP数据库来获取。但是IP库又是一直更新的,维护起来特别麻烦。所以我们采用调用百度的API来实现;
function get_city($star)
{
$ip = GET_IP();
//获取用户IP
if (empty($ip)) {
return 0;
}
$url = 'https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?query=' . $ip . '&co=&resource_id=6006&t=&ie=utf8&oe=gbk&cb=op_aladdin_callback&format=json&tn=baidu&cb=&_=';
//调用了百度接口
$str = file_get_contents($url);
$encode = mb_detect_encoding($str, array("ASCII", 'UTF-8', "GB2312", "GBK", 'BIG5'));
$str = mb_convert_encoding($str, 'UTF-8', $encode);
//转化编码
$str = json_decode($str);
//转换为json类型
$str = $str->data[0]->location;
/*
//取出数据
foreach ($star as $value) {
if (!(stripos($str, $value["name"]) === FALSE)) {
return $value['id'];
}
}
*/
return 0;
}
我们通过 baidu 的 API 获取IP的地理位置,并且与我们的数据库的市名称逐条比对,如果获取到的IP地理位置里存在我们数据库的市名称的话,那么他所在的市就是那一条。
我们要从MySQL数据库获取信息,第一步肯定是连接数据库了。
//从函数外引入数据库账号密码等
global $servername, $sqlname, $sqlpassword, $sqldatabase;
// 连接数据库
$mysql = new mysqli($servername, $sqlname, $sqlpassword);
// 转换字符集
$mysql->set_charset('utf8');
// 打开数据库
if (!SQL\usebase($mysql, $sqldatabase) == true) {
// 如果打开失败则程序直接死亡
$mysql->close();
die();
}
因为我连接数据库是写在方程里的,而数据库账号密码等均在函数外,所以第一步是从函数外引入数据库账号密码等。global 【需要引入的变量】;。引入后调用 mysqli 对象mysqli(【服务器】, 【账号】, 【密码】)连接。如果是本地服务器那么服务器就是localhost。把字符集设置为UTF-8,如果你是别的就设置成别的。最后一步是打开数据库,这里我使用的是我自己写的MYSQL库,过一段时间我完善后就会公开完整代码。本项目使用到的在项目里面都导入了。
下面的代码演示了 查询 level 表中的 address 条件是 id 要等于 要查的id。
// 查询 level 表 中的 address 条件是 id 要等于 要查的id
$yon = SQL\selectsql($mysql, "`level`", "address", "id", $id);
if (!$yon == true) {
die();
$mysql->close();
}
$map["address"] = mysqli_fetch_array($yon)[0];
当然我们也可以全部都查询比如在获取所有地区的星星数量的时候我们就使用了下面的代码。
查询 表 star 的 *所有 信息 没有条件 所以star的后面要加上 -- 。 不要漏了任何一个空格。这个写法很丑,实际上是因为我库没有完善。当然你叶可以直接通过 mysqli 的内置方法来查询。
// 查询 表 star 的 所有信息 没有条件
$yon = SQL\selectsql($mysql, "`star` -- ", "*", "", "");
// 星星列表
$star = [];
// 把查询到的的信息全部都添加到 star 列表里面
while ($row = $yon->fetch_assoc()) //这里不能直接使用$row
{
array_push($star, $row);
}
通过数据库获取到关卡文件存放的路径以后,就要读取出来并且打乱卡牌了。
// 通过路径读取出文件,并且将文件转换成字符串
$mapJson = file_get_contents($map["address"]);
// 调用打乱方法
$mapJson = replay_map($mapJson);
// 打乱方法的实现
function replay_map($json, $random = true)
{
// decode 解码 JSON
$json = json_decode($json, true);
// 扑克牌类型列表
$pokerType = [];
// 别管
if ($random) {
// 给 pokerType 列表随机添加牌
// 如果 i 小于 扑克总数则继续添加
for ($i = 0; $i < $json["pokerAmount"];) {
// 生成随机的一种牌的类型,类型要在 扑克类型总数以内
$type = mt_rand(1, $json['pokerTypeNum']);
// 在pokerType列表后面添加3个这个牌的类型
array_push($pokerType, $type, $type, $type);
// i = i + 3
$i += 3;
}
// 打乱 pokerType 列表
shuffle($pokerType);
// 给 地图 的扑克按照pokerType列表的顺序修改扑克类型
for ($i = 0; $i < $json["pokerAmount"]; $i++) {
$json["pokerList"][$i][2] = $pokerType[$i];
}
/* *************** 跳过阅读 ***************** */
} else {
$type = [];
for ($i = 0; $i < $json['pokerTypeNum']; $i++) {
$type[$i] = $i + 1;
}
shuffle($type);
for ($i = 0; $i < $json["pokerAmount"]; $i++) {
$json["pokerList"][$i][2] = $type[$json["pokerList"][$i][2] - 1];
}
}
/* *************** 继续阅读 ***************** */
// 返回 编码后的 JSON 地图
return json_encode($json);
}
如果你要发送HTTP请求的话,你需要创建一个 XMLHttpRequest (Chrome为内核的浏览器)对象
然后通过调用 open 方法来设置请求方法与请求列表。
可以使用 setRequestHeader来设置请求头 , 例如 把 content-type 设置成 urlencoded 。
// 创建 XML HTTP 对象
var xhr = new XMLHttpRequest;
// 请求为 POST 请求 ,请求地址为 '/'
xhr.open("POST",'/',true);
// 设置 Content-Type 为 application/x-www-form-urlencoded
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 设置回调函数 发送后的信息都由这个回调函数获得
xhr.onreadystatechange = function(){ console.log(xhr.readyState); };
// 发送请求 ask = 1 , num = 2
xhr.send("ask=1&num=2");
这样子就可以发送 HTTP 请求了。
如果细心的人可以发现 控制台会输出4次数字。这代表 xhr.onreadystatechange 被调用了4次。
这 4 次 分别是
xhr.onreadystatechange 函数里面添加判断该语句 判断 当前的状态。switch( xhr.readyState ) {
case 0 :
console.log("现在还没有被初始化");
break;
case 1 :
console.log("正在加载");
break;
case 2 :
console.log("请求已发送");
break;
case 3 :
console.log("交互中");
break;
case 4 :
console.log("加载完毕");
break;
}
为了方便发送表单,我们把这个过程封装成函数
并且为了兼容其他浏览器,我们也要使用判断方法。
function SERVER(url,postList) {
// POST
var xhr;
if (window.XMLHttpRequest) { // Mozilla, Safari...
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
xhr = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) { }
}
}
if (xhr) {
xhr.onreadystatechange = onReadyStateChange;
xhr.open('POST', url , true);
// 设置 Content-Type 为 application/x-www-form-urlencoded
// 以表单的形式传递数据
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
let msg = "";
for (let i in postList) {
msg = msg + i + "=" + postList[i] + "&";
}
xhr.send(msg);
}
// onreadystatechange 方法
function onReadyStateChange() {
// 该函数会被调用四次
console.log(xhr.readyState);
if (xhr.readyState === 4) {
// everything is good, the response is received
if (xhr.status === 200) {
// 当请求的返回值是 200 成功 的话就打印回复的报文
console.log(xhr.responseText);
} else {
console.log('There was a problem with the request.');
}
} else {
// still not ready
console.log('still not ready...');
}
}
}
利用这个方法我们就可以用简单的两句来实现 发送API 请求啦:
var url = "https://mrxie.xyz/"
var form = {
ask: "h"
};
var server = SERVER(url,form);
地图的文件格式是 Json ,里面一定得包括以下参数:
pokerAmount 扑克牌总数mapSizeW 地图宽mapSizeH 地图高pokerSize 扑克牌的边长pokerTypeNum 扑克类型总数pokerList 扑克列表现版本仅支持正方形地图,也就是说,mapSizeW 要等于 mapSizeH。
{
"pokerAmount" : 18 ,
"mapSizeW" : 120,
"mapSizeH" : 120,
"pokerSize" : 10 ,
"pokerTypeNum" : 1,
"pokerList" : [
[10,10,1],
[10,11,1],
[10,12,1]
]
}
pokerList是存放每张扑克的数据的地方,按照 大号压小号 的规则编写。比如上面的例子中,[10,12,1]就压住了[10,10,1] 。 这3个数据的意思分别是 扑克的 [x 坐标 ,y 坐标 ,t 种类] 。坐标均为 中心坐标 。
普通的关卡地图均放在 ./map/level/文件夹下,以 level 加关卡数 加文件类型 .json 命名。例如 ./map/level/level1.json。
如果 CandyMieGame_PHP 、 CandyMieGame_H5 任意一项的 fork 超过 50 我就会发布 兼容 微信小程序的版本。
虽然没有达成目标 但是还是 : https://blog.csdn.net/apple_53792700/article/details/128041151
✍️本文作者为 > 【谢玄.】 Mr-XieXuan < 于 2022/10/11/3:00 发布于 CSDN 。
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru
我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur
前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源
嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来
文章目录git常用命令(简介,详细参数往下看)Git提交代码步骤gitpullgitstatusgitaddgitcommitgitpushgit代码冲突合并问题方法一:放弃本地代码方法二:合并代码常用命令以及详细参数gitadd将文件添加到仓库:gitdiff比较文件异同gitlog查看历史记录gitreset代码回滚版本库相关操作远程仓库相关操作分支相关操作创建分支查看分支:gitbranch合并分支:gitmerge删除分支:gitbranch-ddev查看分支合并图:gitlog–graph–pretty=oneline–abbrev-commit撤消某次提交git用户名密码相关配置g
打印1:defsum(i)i=i+[2]end$x=[1]sum($x)print$x打印12:defsum(i)i.push(2)end$x=[1]sum($x)print$x后者是修改全局变量$x。为什么它在第二个例子中被修改而不是在第一个例子中?类Array的任何方法(不仅是push)都会发生这种情况吗? 最佳答案 变量范围在这里无关紧要。在第一段代码中,您仅使用赋值运算符=为变量i赋值,而在第二段代码中,您正在修改$x(也称为i)使用破坏性方法push。赋值从不修改任何对象。它只是提供一个名称来引用一个对象。方法要么是破坏性