一时兴起,想试试能不能用perl实现字符贪吃蛇,算法如下:

  定义2个数组@bg、@snake,@bg用来显示整个界面,@snake从蛇头开始保存蛇的坐标点。

  蛇每移动一次,新的坐标点放到@snake头部,并去除最后一个元素,再改变@bg对应坐标的值。

  通过控制台窗口不断清屏再打印,使蛇“看起来在移动”。

  简单的速度控制实现:每次移动后sleep 若干秒。

  感觉原来的make_food算法不够好,修改如下:

sub make_food{
if(@snake < $full){
my @empty_points=();
foreach(..$#bg){
my $y=$_;
foreach(..$#{$bg[0]}){
push @empty_points,[$y,$_] if($bg[$y][$_] eq '.');
}
} # 找出所有空的坐标点,存入@empty_points数组
until($food){
my $num=int( rand( scalar(@empty_points) ) ); # 随机取出@empty_points下标
my ($y,$x)=@{ $empty_points[$num] }[,];
$bg[$y][$x]='O';
$food=;
}
}
}

  一个要解决的问题:无阻塞获取按键。通过度娘找到模块Term::ReadKey,新的问题产生了:批量输入方向,蛇会依次按照输入移动,暂时想不到好办法解决。

  使用Time::HiRes的sleep,实现毫秒级等待,use 5.01 支持given...when语法。

  使用 w a s d 控制移动,代码如下:

use strict;
use 5.01;
use Time::HiRes qw/sleep/;
use Term::ReadKey;
use constant {WIDTH=>,HEIGHT=>,DEBUG=>};
my @bg=();
my @snake=();
my ($score,$food,$speed,$alive)=(,,,); # 长度、食物、速度、存活
my $full=WIDTH*HEIGHT;
my %direct=( UP=>[-,],
DOWN=>[,],
LEFT=>[,-],
RIGHT=>[,], ); # 移动方向
my $head='RIGHT'; # 初始移动方向 &init;
while($alive){
$speed=($speed<)?(+int($score/)):; # 速度控制
if(@snake==$full){
print "congratulations!\n"; # 蛇占满游戏区时显示
}
else{
&move;
&check_head;
&show if $alive;
sleep (-$speed*0.1);
}
} sub init{
my $y=int(HEIGHT/);
@bg=map{my $x=$_;[map{$bg[$x][$_]='.'}..WIDTH-]}..HEIGHT-;
@{$bg[$y]}[,]=('#','@'); # 初始蛇身位置
@snake=( [$y,],[$y,], ); # 保存蛇身坐标
&make_food; # 产生食物
}
sub show{
system("cls");
print "your score : $score\n";
print "current speed : ",$speed,"\n\n";
print @$_,"\n" foreach(@bg);
}
sub move{
ReadMode ;
my ($key,$cur);
$key=ReadKey(-);
$key=~tr/a-z/A-Z/ if $key;
given($key){
# 不允许反向移动
when('W'){
if($head eq 'DOWN'){
$cur='DOWN';
}
else{
$cur=$head='UP';
}
}
when('A'){
if($head eq 'RIGHT'){
$cur='RIGHT';
}
else{
$cur=$head='LEFT';
}
}
when('S'){
if($head eq 'UP'){
$cur='UP';
}
else{
$cur=$head='DOWN';
}
}
when('D'){
if($head eq 'LEFT'){
$cur='LEFT';
}
else{
$cur=$head='RIGHT';
}
}
default { $cur=$head; }
}
unshift @snake,[$snake[][]+$direct{$cur}[],$snake[][]+$direct{$cur}[]];
}
sub make_food{
if(@snake < $full){
until($food){
my ($x,$y)=(int(rand(WIDTH)),int(rand(HEIGHT)));
if($bg[$y][$x] eq '.'){
$bg[$y][$x]='O';
$food=;
}
}
}
}
sub check_head{
# 蛇身超出范围
if($snake[][] < || $snake[][] > HEIGHT-
|| $snake[][] < || $snake[][] > WIDTH-){
$alive=;
}
# 蛇吃到自己
if(@snake>){
foreach(..$#snake){
if($snake[][] == $snake[$_][] && $snake[][] == $snake[$_][]){
$alive=;
}
}
}
# 移动
if($bg[$snake[][]][$snake[][]] eq '.'){
$bg[$snake[][]][$snake[][]]='@';
}
# 吃到食物
if($bg[$snake[][]][$snake[][]] eq 'O'){
$bg[$snake[][]][$snake[][]]='@';
$score++;
$food=;
&make_food;
push @snake,[$snake[-][],$snake[-][]]; # 新的蛇身放在尾部
}
$bg[$snake[-][]][$snake[-][]]='.'; # 先清除尾巴显示
pop @snake; # 去掉尾巴
map{$bg[$snake[$_][]][$snake[$_][]]='#'}..$#snake; # 其他蛇身显示
}

  游戏界面:

  

Perl字符贪吃蛇的更多相关文章

  1. C字符贪吃蛇

    算法参照Perl字符贪吃蛇,源码: #include <stdio.h> #include <windows.h> #define WIDTH 12 // 宽 #define ...

  2. Perl看完这个,再不敢说自己会玩贪吃蛇

    某天闲逛时看见一副动图: 真的是非常贪吃,各种拐弯各种吃,感觉十分有趣. 用Perl来实现自动吃满,蓄谋已久,之前的字符贪吃蛇.深度优先算法.A*算法,都是为此篇做铺垫. 那么,怎样让蛇不吃到自己呢? ...

  3. 字符界面的贪吃蛇--链表--C++

    前天看了下链表,由于平时对链表的使用不多,所以对链表的应用也没什么了解,所以想来想去,就想用链表实现一下贪吃蛇. 下面言归正传,先看效果图,再看代码,其他没有了! 图1: 图2: 代码: #inclu ...

  4. 基于AT89C51单片机的贪吃蛇电子游戏(仿真)

    有关贪吃蛇的历史发展可以看一下这个网址,贪吃蛇最初的设计和现在并不相同..http://www.techweb.com.cn/internet/2013-02-21/1278055.shtml 该项目 ...

  5. C语言之贪吃蛇

    利用链表的贪吃蛇,感觉自己写的时候还是有很多东西不熟悉, 1.预编译 2.很多关于系统的头文件也不是很熟悉 3.关于内存 第一个是.h头文件 #ifndef _SNAKE_H_H_H #define ...

  6. 【BZOJ-4213】贪吃蛇 有上下界的费用流

    4213: 贪吃蛇 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 58  Solved: 24[Submit][Status][Discuss] Desc ...

  7. 小项目特供 贪吃蛇游戏(基于C语言)

    C语言写贪吃蛇本来是打算去年暑假写的,结果因为ACM集训给耽搁了,因此借寒假的两天功夫写了这个贪吃蛇小项目,顺带把C语言重温了一次. 是发表博客的前一天开始写的,一共写了三个版本,第一天写了第一版,第 ...

  8. 多线程的Python 教程--“贪吃蛇”

    本指南的里代码可以在这里下载:  threadworms.py ,或者从  GitHub.代码需要  Python 3 或 Python 2 ,同时也需要安装  Pygame . 点击查看大版本图片 ...

  9. [010]转+修正---C++的贪吃蛇程序(未用面向对象封装)

    在网上看到一段贪吃蛇程序,自己心痒下了下来又稍微做了一点修改. 没有用面向对象的方式来进行封装,下次准备试试. 需要在windows环境下进行编译 #include<iostream> # ...

随机推荐

  1. HashMap的put()与扩容

    1. put() final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { HashMap.Nod ...

  2. java web编程 servlet

    先从请求的信息里面获取协议,版本协议如果是1.1结尾的就报错,也就是我们常见的405报错: 405是协议请求方式错误,所以要重写doget或者dopost方法,直接调用父类的get和post方法是会报 ...

  3. 修改CentOS的YUM源

    CentOS配置本地yum源/阿里云yum源/163yuan源并配置yum源的优先级 1.查看本地yum源 2.把默认yum源备份 mkdir /opt/centos-yum.bak mv /etc/ ...

  4. java--Annotation实现

    Annotation实现 在java中一共提供了三个annotation:@Override,@Deprecated,@SupperessWarnings 代码范例:使用Annotation pack ...

  5. 搭建React项目环境【1】

    1.安装NodeJS6.0以上自带npm依赖包管理工具 2.webstrom 2019.2 工具 1.在cmd输入node -v就可以看到node的当前版本 2.在输入node进入node环境 3.查 ...

  6. git rebase 版本。。变基

    git rebase,顾名思义,就是重新定义(re)起点(base)的作用,即重新定义分支的版本库状态.要搞清楚这个东西,要先看看版本库状态切换的两种情况: 我们知道,在某个分支上,我们可以通过git ...

  7. 检查SQL Server数据库各个库表空间使用的方法

    /*创建一张表:表名Data,列名:表名,列数,预留空间,数据占用空间,索引占用空间,剩余空间*/ CREATE TABLE Data ( 表名 ), 列数 ), 预留空间 ), 数据占用空间 ), ...

  8. awk命令笔记

    awk是啥? awk(奥克)是linux中一个强大的分析工具,linux面试必考 [root@rainbol ~]# awk Usage: awk [POSIX or GNU style option ...

  9. 神经网络(8)---如何求神经网络的参数:cost function的表达

    两种分类问题: binary & multi-class 下面的是两种类型的分类问题(一种是binary classification,一种是multi-class classificatio ...

  10. [Svelte 3] Render HTML directly into a component in Svelte 3

    Disclaimer: please use this feature carefully. <script> let stringToRender = "<h1>H ...