一直想利用微信公告平台提供的接口开发一个文字类型游戏,但是苦于没有什么点子,知道看到redraiment在OSChina上托管的微信游戏--开窗,让我觉得我也可以完成此类文字游戏的开发.redraiment利用的是Emacs Lisp脚本语言完成的,可惜我对这个脚本完全没有了解,而且我的微信接口环境是基于PHP的,所以就没办法参考他的源码了,好在游戏模式十分简单,不必利用redrainment提供的框架也可以完成这样一款文字游戏.
游戏规则很简单,1个5x5(或者其他规格)的棋盘,每改变其中一个棋子的状态(每个棋子都有两种对应的状态,用两种不同的颜色表示),其上,下,左,右四个位置的棋子状态也会跟着改变,如果你能将所有棋子的状态都变成其相对的状态,游戏就结束了.
首先说整个游戏本身,我选择了利用0和1的字符来表示棋子的两种状态,每个棋盘都是1个含有0和1的25个字符(暂时是基于5x5棋盘),写了一个translate函数专门将这个长度未25的字符串转换成表示特殊的棋子(以下代码都是基于PHP)
01 |
function translateLight( $string ) |
02 |
{ |
03 |
$blue = "◼️" ; |
04 |
$purple = "◻️" ; |
05 |
06 |
$strArray = array_chunk ( str_split ( $string ),5); |
07 |
$newStr = "" ; |
08 |
for ( $i = 0; $i < 5; $i ++) |
09 |
{ |
10 |
for ( $j = 0; $j < 5; $j ++) |
11 |
{ |
12 |
if (! strcmp ( $strArray [ $i ][ $j ], "0" )) |
13 |
{ |
14 |
$newStr .= $blue ; |
15 |
} |
16 |
elseif (! strcmp ( $strArray [ $i ][ $j ], "1" )) |
17 |
{ |
18 |
$newStr .= $purple ; |
19 |
} |
20 |
else |
21 |
{ |
22 |
23 |
} |
24 |
} |
25 |
$newStr .= "\r\n" ; |
26 |
} |
27 |
return $newStr ; |
28 |
} |
上述代码中的作为棋子的特殊字符是Mac下的特殊字符,其非标准的ASCII字符,但是在微信上可以显示出如下效果,图中的绿色和紫色圆圈就是代码中的$blue和$purple中保存的字符.
有了基本的状态字符,同时我就需要将状态保存到数据库,每次用户发来指定的游戏消息(本例中游戏指定是数字,只要用户回复了数字类型,就是开始这个游戏),就会从数据库中将这个用户之前的游戏状态取出,然后根据其数字指令区处理整个棋盘的状态,将处理后的棋盘状态再发送给用户.
01 |
function turnLight( $keyword , $fromUsername ) |
02 |
{ |
03 |
$header = "" ; |
04 |
$footer = "" ; |
05 |
$sql = "select nick_name,best_score,says from wx_turnlight where best_score = (select min(best_score) from wx_turnlight);" ; |
06 |
$result = execSql( $sql ); |
07 |
$rownum = mysql_num_rows( $result ); |
08 |
$response = "" ; |
09 |
if ( $rownum != 0) |
10 |
{ |
11 |
$row = mysql_fetch_array( $result ); |
12 |
$header = $header . "擂主:" . $row [ 'nick_name' ]. "\r\n总步数:" . $row [ 'best_score' ]. "\r\n擂主宣言:" . $row [ 'says' ]; |
13 |
} |
14 |
15 |
/*全局命令,keyword的长度为1 |
16 |
*2:结束游戏 |
17 |
*1:开始游戏 |
18 |
*/ |
19 |
if ( strlen ( $keyword ) == 1) |
20 |
{ |
21 |
if (! strcmp ( $keyword , "1" )) |
22 |
{ |
23 |
$str = getLightState( $fromUsername ); |
24 |
$response = translateLight( $str ); |
25 |
} |
26 |
else if (! strcmp ( $keyword , "2" )) |
27 |
{ |
28 |
$str = "1111111111111111111111111" ; |
29 |
setLightState( $fromUsername , $str ); |
30 |
setScore( $fromUsername ,0); |
31 |
return "游戏已退出,所有灯的状态恢复初始状态!" ; |
32 |
} |
33 |
} |
34 |
else if ( strlen ( $keyword ) == 2) |
35 |
{ |
36 |
$str = getLightState( $fromUsername ); |
37 |
$str = processLight( $str , $keyword ); |
38 |
39 |
$score = getScore( $fromUsername ); |
40 |
$newScore = (int) $score + 1; |
41 |
$footer = "\r\n当前步数:$score" ; |
42 |
setScore( $fromUsername , $newScore ); |
43 |
//检查是否成功 |
44 |
if (isWin( $str )) |
45 |
{ |
46 |
$footer .= "\r\n你赢了!恭喜你!请回复您的昵称,格式如下:\r\n昵称 你的大名" ; |
47 |
setBestScore( $fromUsername , $newScore ); |
48 |
$str = "1111111111111111111111111" ; |
49 |
setLightState( $fromUsername , $str ); |
50 |
setScore( $fromUsername ,0); |
51 |
} |
52 |
setLightState( $fromUsername , $str ); |
53 |
$response = translateLight( $str ); |
54 |
} |
55 |
return $header . "\r\n" . $response . $footer ; |
56 |
57 |
} |
状态的更改算法很简单,又一个二维数组存储棋子的状态,根据用户所给坐标来改变所有5个点的值就可以了.
01 |
function processLight( $str , $order ) |
02 |
{ |
03 |
//将字符串转换为数组 |
04 |
$array = array_chunk ( str_split ( $str ),5); |
05 |
06 |
if ( strlen ( $order ) != 2) |
07 |
{ |
08 |
return "命令有误,必须是两位数字" ; |
09 |
} |
10 |
$ord_array = str_split ( $order ); |
11 |
12 |
$x = (int) $ord_array [0]; |
13 |
$y = (int) $ord_array [1]; |
14 |
15 |
$newStr = "" ; |
16 |
for ( $i = 0; $i < 5; $i ++) |
17 |
{ |
18 |
for ( $j = 0; $j < 5; $j ++) |
19 |
{ |
20 |
21 |
if (( $j == $x -1) && ( $i == $y )) |
22 |
{ |
23 |
$newStr .= zero2one( $array [ $i ][ $j ]); |
24 |
} |
25 |
elseif (( $j == $x +1) && ( $i == $y )) |
26 |
{ |
27 |
$newStr .= zero2one( $array [ $i ][ $j ]); |
28 |
} |
29 |
elseif (( $j == $x ) && ( $i == $y -1)) |
30 |
{ |
31 |
$newStr .= zero2one( $array [ $i ][ $j ]); |
32 |
} |
33 |
elseif (( $j == $x ) && ( $i == $y +1)) |
34 |
{ |
35 |
$newStr .= zero2one( $array [ $i ][ $j ]); |
36 |
} |
37 |
elseif (( $j == $x ) && ( $i == $y )) |
38 |
{ |
39 |
$newStr .=zero2one( $array [ $i ][ $j ]); |
40 |
} |
41 |
else |
42 |
{ |
43 |
$newStr .= $array [ $i ][ $j ]; |
44 |
} |
45 |
} |
46 |
} |
47 |
return $newStr ; |
48 |
} |
这里面同时还需要几个数据库连接的函数,用来将棋盘状态存放进数据库以及从数据库中读取状态,若干函数如下:
01 |
function execSql( $sql ) |
02 |
{ |
03 |
$sqluser = "*****" ; |
04 |
$sqlpwd = "******" ; |
05 |
$con = mysql_connect( "localhost" , $sqluser , $sqlpwd ); |
06 |
if (! $con ) |
07 |
{ |
08 |
return 'Could not Connect: ' .mysql_error(); |
09 |
} |
10 |
mysql_select_db( "wordpress" , $con ); |
11 |
$result = mysql_query( $sql ); |
12 |
mysql_close( $con ); |
13 |
return $result ; |
14 |
} |
15 |
16 |
function getLightState( $fromUsername ) |
17 |
{ |
18 |
$sql = "select state from wx_turnlight where open_id = '$fromUsername';" ; |
19 |
$result = execSql( $sql ); |
20 |
$rownum = mysql_num_rows( $result ); |
21 |
$state = "" ; |
22 |
if ( $rownum != 0) |
23 |
{ |
24 |
$row = mysql_fetch_array( $result ); |
25 |
$state = $row [ 'state' ]; |
26 |
|