jjzjj

微信小程序游戏开发│石头剪刀布游戏(附源码)

TiAmo zhang 2023-04-12 原文

 石头剪刀布游戏功能中一方是电脑,另一方是玩家。游戏时电脑一直快速切换出拳显示,当玩家选择底部的剪子、石头、布后,则电脑出拳停止,并在紫色方块中显示用户的出拳图片。游戏判断出输赢结果,记录玩家赢的次数。对战一局后可以单击“再来!”按钮重新一局。运行效果如图1所示。

 

                (a)玩家出拳前                                                                              (b)玩家出拳后

■ 图1  石头剪刀布游戏运行效果

01、程序设计的思路

1. 控制剪子、石头、布的快速切换

猜拳游戏的核心就是快速切换剪子、石头、布三个图像,电脑的出拳一直是动态切换的,一直到用户选择剪子、石头、布的图片后才停止。这里将这三个图像文件名存储在一个srcs数组中,并使用定时器快速从这个数组中依次循环获取图像文件名,并将该文件名指定的图像显示到image组件中即可。

data: {
    srcs: [
      '/images/shitou.png',
      '/images/jiandao.png',
      '/images/bu.png',
    ] ,
    imgAi: '', // 电脑随机显示的图片
    imgUser: '/images/wenhao.png', // 用户选中的图片
  },
  //设置电脑每间隔0.2s随机显示石头剪刀布
  timerGo() {
    timer = setInterval(this.change, 200); //200毫秒
  },
  //设置电脑随机显示石头剪刀布,0对应石头,1对应剪刀、2对应布
  change() {
    this.setData({
      imgAi: this.data.srcs[parseInt(Math.random() * 3)],
    })
  },

这里涉及到两个主要变量:srcs(图片数组)和imgAi(电脑出拳),这两个都定义在data对象中。

本游戏对石头、剪子、布进行编号,其中0对应石头,1对应剪刀、2对应布。所以电脑随机出拳就是产生0~2之间的随机自然数。

这里使用了Math中的parseInt()函数和Math中的random()函数,其中random()函数会产生0~1之间的小数,当Math.random() * 3时,random函数就会生成0~3之间的一个随机小数,然后通过parseInt()函数进行取整处理得到0~2之间的随机自然数。接着通过this.data.srcs[parseInt(Math.random()*3)]就完成了使电脑随机选择石头剪刀布中的一种情况。

2. 用户出拳

用户出拳比较简单,这里提供3个图像组件(image)供用户单击选择。对此3个图像组件分别绑定单击事件,单击事件获取并识别那个image图像组件,从而得知玩家用户的出拳。

02、程序设计的步骤

新建一个微信小程序后,在app.json中修改原有的"window"值,实现导航条标题文字为"石头剪刀布游戏",具体如下:

"window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "石头剪刀布游戏",
    "navigationBarTextStyle": "black"

1. 游戏布局

猜拳游戏的布局是纵向显示4个文本组件(text)、5个图像组件(image)和1个按钮组件(button)。在创建小程序工程时,默认建立了两个页面:index和logs。我们不需要管logs,在这个例子中只需修改和index页面相关的文件,index是小程序第一个显示的页面,其中index.wxml文件是index页面的布局文件。

按猜拳游戏的布局修改index.wxml文件如下:

<!--pages/index/index.wxml-->
<view class="container">
<text class="win-text">你已经获胜了</text>
<text class="win-num">{{winNum}}次</text>
<view class="result">
<image src="{{imgAi}}" class="imgAi"></image>
<text class="notice">{{notice}}</text>
<image src="{{imgUser}}" class="imgUser"></image>
</view>
<view class="test">
<text class="notice-punches">出拳吧,少年~</text>
<view class="imageGroup">
<image type="primary" class="btn" bindtap="btnclick" data-choose="0" src="/images/shitou.png" class="image"></image>
<image type="primary" class="btn" bindtap="btnclick" data-choose="1" src="/images/jiandao.png" class="image"></image>
<image type="primary" class="btn" bindtap="btnclick" data-choose="2" src="/images/bu.png" class="image"></image>
</view>
</view>
<button class="btn-again" bindtap="again">再来!</button>
</view>

在这段代码中,image和text组件的内容都需要动态改变,所以image组件的src属性和text组件的文本值(夹在<textclass="win-num">和</text>之间的部分)都分别于一个变量绑定,这是小程序的一个重要特性。在改变组件的属性值时,并不需要直接获取该组件的实例,而只需将该属性与某个同类型的变量绑定,一旦该变量的值改变,属性值也就会随之改变了,绑定变量的格式是“{{变量名}}”。

下面2个<image>是显示电脑出的拳图片和玩家选择的拳图片。

<view class="result">
<image src="{{imgAi}}" class="imgAi"></image>
<text class="notice">{{notice}}</text>
<image src="{{imgUser}}" class="imgUser"></image>
</view>

 以下三个<image>是供玩家选择的出拳图片。bindtap绑定单击事件,data-choose用于单击时识别那个<image>。

<image type="primary" class="btn" bindtap="btnclick" data-choose="0" src="/images/shitou.png" class="image"></image>
<image type="primary" class="btn" bindtap="btnclick" data-choose="1" src="/images/jiandao.png" class="image"></image>
<image type="primary" class="btn" bindtap="btnclick" data-choose="2" src="/images/bu.png" class="image"></image>

 对应样式文件index.wxss如下:

.win-text {
  text-align: center;
}
.win-num {
  color: red;
  text-align: center;
}
.result {
  height: 160rpx;
  display: inline-block;
}
.notice {
  width: 100rpx;
  color: red;
  /*height:140rpx;*//*line-height:140rpx;*/
  text-align: center;
  display: inline-block;
  padding-top: 0rpx;
}
.imgAi {
  width: 140rpx;
  height: 140rpx;
  padding: 10rpx 0 10rpx 10rpx;
}
.imgUser {
  width: 140rpx;
  height: 140rpx;
  padding: 10rpx 0 10rpx 10rpx;
}
.notice-punches {
  text-align: center;
  display: block;
  padding-top: 20rpx;
}
image {
  width: 100px;
  height: 100px;
  border-radius: 50%;
}

 并在小程序工程根目录建立一个images目录,将剪子、石头和布三个图片文件和一个wenhao.png放到该目录中。对应图片下图2所示。

 ■ 图2  石头剪刀布图片

2. 游戏脚本

// pages/index/index.js
var timer; //定时器
Page({
  data: {
    srcs: [
      '/images/shitou.png',
      '/images/jiandao.png',
      '/images/bu.png',
    ],
    imgAi: '', //电脑随机显示的图片
    imgUser: '/images/wenhao.png', //用户选中的图片
    notice: '', //猜拳对比结果
    winNum: wx.getStorageSync('winNum'), //用户猜拳赢的次数
    btnpunches: false, //用户是否单击出拳,false表示未出拳
  },
  onLoad: function () {
    this.timerGo();
  },
  //设置电脑每间隔0.2s随机显示石头剪刀布
  timerGo: function () {
    timer = setInterval(this.change, 200); //200毫秒
  },
  //设置电脑随机显示石头剪刀布
  change: function () {
    this.setData({
      imgAi: this.data.srcs[parseInt(Math.random() * 3)],
    })
  },

btnclick:function(e)主要用来处理单(点)击事件,其中e是方法的回调,当我们触发了单击事件,小程序会调用该方法并传入一个Object对象,这个Object对象主要存储了单击事件的一些信息。其中当玩家单击剪刀的时候,在Object对象e的target下有个dataset中有个choose记录了玩家的选择。例如用户选择的石头,this.setData({imgUser: '/images/shitou.png'})将用户选择的石头图片设置给imgUser变量从而更新页面的显示。同时clearInterval(timer)清除计时器,这样相当于停止电脑方的剪子、石头、布三个图像切换,并在imgAi记录电脑方的出拳图片。

后面根据玩家的选择和电脑的出拳情况判断出输赢。

//当用户单击下面方框的石头剪刀布,将用户数据设置为对用的图片
  btnclick:function (e) {
    if (this.data.btnpunches == true) { //用户已出拳,直接返回
      return;
    }
    var num = this.data.winNum; //用户赢的次数
    this.setData({ //先假设的值
      notice: '你输了',
      btnpunches: true,
    })
    //以下是赢的情况
    if (e.target.dataset.choose == 0) { //用户选择石头
      this.setData({
        imgUser: '/images/shitou.png', //将用户选择的石头图片设置给imgUser变量
      })
      //清除计时器
      clearInterval(timer);
      if (this.data.imgAi == '/images/jiandao.png') { //电脑是刀
        num++;
        wx.setStorageSync('winNum', num)
        this.setData({
          notice: '你赢了',
          winNum: num,
        })
      }

    } else if (e.target.dataset.choose == 1) { //用户选择剪刀
      this.setData({
        imgUser: '/images/jiandao.png', //将用户选择的剪刀图片设置给imgUser变量
      })
      //清除计时器
      clearInterval(timer);
      if (this.data.imgAi == '/images/bu.png') { //电脑是布
        num++;
        wx.setStorageSync('winNum', num) //本地缓存赢的次数
        this.setData({
          notice: '你赢了',
          winNum: num,
        })
      }

    } else { //用户选择布
      this.setData({
        imgUser: '/images/bu.png', //将用户选择的布图片设置给imgUser变量
      })
      //清除计时器
      clearInterval(timer);
      if (this.data.imgAi == '/images/shitou.png') { //电脑是石头
        num++;
        wx.setStorageSync('winNum', num)
        this.setData({
          notice: '你赢了',
          winNum: num,
        })
      }
    }
    //以下是平局的情况
    if (this.data.imgAi == this.data.imgUser) {
      this.setData({
        notice: '平局',
      })
      //清除计时器
      clearInterval(timer);
    }
  },

 again()是再来按钮事件,电脑重新启动猜拳。

again() {
    if (this.data.btnpunches == false) { //用户还未出拳,不能再来
      return;
    }
    this.timerGo(); //电脑启动猜拳,每间隔0.2s随机显示石头剪刀布
    this.setData({
      btnpunches: false, //设置为用户未出拳状态
      imgUser: '/images/wenhao.png',
      notice: ' ',
    })
  },
})

 至此完成剪刀石头布游戏。

 

有关微信小程序游戏开发│石头剪刀布游戏(附源码)的更多相关文章

  1. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  2. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  3. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  4. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  5. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  6. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  7. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  8. UE4 源码阅读:从引擎启动到Receive Begin Play - 2

    一、引擎主循环UE版本:4.27一、引擎主循环的位置:Launch.cpp:GuardedMain函数二、、GuardedMain函数执行逻辑:1、EnginePreInit:加载大多数模块int32ErrorLevel=EnginePreInit(CmdLine);PreInit模块加载顺序:模块加载过程:(1)注册模块中定义的UObject,同时为每个类构造一个类默认对象(CDO,记录类的默认状态,作为模板用于子类实例创建)(2)调用模块的StartUpModule方法2、FEngineLoop::Init()1、检查Engine的配置文件找出使用了哪一个GameEngine类(UGame

  9. 微信小程序通过字典表匹配对应数据 - 2

    前言一般来说,前端根据后台返回code码展示对应内容只需要在前台判断code值展示对应的内容即可,但要是匹配的code码比较多或者多个页面用到时,为了便于后期维护,后台就会使用字典表让前端匹配,下面我将在微信小程序中通过wxs的方法实现这个操作。为什么要使用wxs?{{method(a,b)}}可以看到,上述代码是一个调用方法传值的操作,在vue中很常见,多用于数据之间的转换,但由于微信小程序诸多限制的原因,你并不能优雅的这样操作,可能有人会说,为什么不用if判断实现呢?但是if判断的局限性在于如果存在数据量过大时,大量重复性操作和if判断会让你的代码显得异常冗余。wxswxs相当于是一个独立

  10. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

随机推荐