用React实现数字华容道游戏

实验目的

  • 巩固ReactNative相关知识;
  • 学习ReactNative开发;
  • 训练ReactNative编程思维。

实验内容

  • 实现数字华容道游戏,要求如下:
    • 通过点击移动空白附近的按钮,将乱序排列变成有序排列;
    • 能判断任务是否完成;
    • 包含一个重新开始的按钮,随机初始化棋盘;
    • 支持多个难度级别(选做)。
  • 填写核心代码,上传截图(截图中显示作者信息)
  • 游戏界面如下:

实验环境

  • Windows10
  • Visual Studio Code
  • React Native
  • MUMU模拟器

实验步骤:
1、打开模拟器

2、连接模拟器并创建项目UnblockMe

3、进入项目路径,启动VScode

4、在命令界面窗口运行该指令,yarn add @react-native-picker/picker,从外部增加该条件

5、yarn android运行

6、效果图,可选择难度系数
 

7、重排之后

部分关键源代码如下:
index.js

/**
 * @format
 */

import {AppRegistry} from 'react-native';
import Unblock from './Unblock';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => Unblock);

Unblock.js

/* eslint-disable no-array-constructor */
import {Picker} from '@react-native-picker/picker';
import React from 'react';
import {View, Text, TouchableHighlight, StyleSheet, Button} from 'react-native';

class Square extends React.Component {
  render() {
    const title = this.props.value === 0 ? ' ' : this.props.value;
    const style =
      this.props.value === 0
        ? [styles.square]
        : [styles.square, styles.squareNumber];
    return (
      <TouchableHighlight onPress={() => this.props.onClick()}>
        <View style={style} width={this.props.width} height={this.props.height}>
          <Text style={styles.squareText}>{title}</Text>
        </View>
      </TouchableHighlight>
    );
  }
}

export default class Unblock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {dim: 3, squares: [1, 2, 3, 4, 5, 6, 7, 8, 0]};
    this.initBoard = this.initBoard.bind(this);
    this.setSelectedValue = this.setSelectedValue.bind(this);
    this.clickSquare = this.clickSquare.bind(this);
  }
  componentDidMount() {
    this.initBoard();
  }
  initBoard() {
    const dim = this.state.dim;
    for (let i = 0; i < 1000; i++) {
      let p0 = this.getPosition(0);
      let r = this.getRndInteger(0, 4);
      if (r === 0 && this.inRange({x: p0.x - 1, y: p0.y})) {
        this.moveTo({x: p0.x - 1, y: p0.y}, p0);
      }
      if (r === 1 && this.inRange({x: p0.x + 1, y: p0.y})) {
        this.moveTo({x: p0.x + 1, y: p0.y}, p0);
      }
      if (r === 2 && this.inRange({x: p0.x, y: p0.y - 1})) {
        this.moveTo({x: p0.x, y: p0.y - 1}, p0);
      }
      if (r === 3 && this.inRange({x: p0.x, y: p0.y + 1})) {
        this.moveTo({x: p0.x, y: p0.y + 1}, p0);
      }
    }
    this.setState({dim: dim, squares: this.state.squares});
  }
  getRndInteger(min, max) {
    return Math.floor(Math.random() * (max - min)) + min;
  }
  getPosition(value) {
    const dim = this.state.dim;
    for (let i = 0; i < dim * dim; i++) {
      if (this.state.squares[i] === value) {
        return {x: parseInt(i / dim, 10), y: i % dim};
      }
    }
  }
  isSuccess() {
    const squares = this.state.squares;
    const dim = this.state.dim;
    for (let i = 0; i < dim * dim - 1; i++) {
      if (squares[i] !== i + 1) {
        return false;
      }
    }
    return squares[dim * dim - 1] === 0;
  }

  inRange({x, y}) {
    const dim = this.state.dim;
    if (x < 0 || x >= dim) {
      return false;
    }
    if (y < 0 || y >= dim) {
      return false;
    }
    return true;
  }

  moveTo(p1, p2) {
    const dim = this.state.dim;
    if (this.inRange(p2) && this.state.squares[p2.x * dim + p2.y] === 0) {
      [
        this.state.squares[p1.x * dim + p1.y],
        this.state.squares[p2.x * dim + p2.y],
      ] = [
        this.state.squares[p2.x * dim + p2.y],
        this.state.squares[p1.x * dim + p1.y],
      ];
      return true;
    }
    return false;
  }

  clickSquare(value) {
    const {x, y} = this.getPosition(value);
    if (this.moveTo({x, y}, {x: x - 1, y})) {
    } else if (this.moveTo({x, y}, {x: x + 1, y})) {
    } else if (this.moveTo({x, y}, {x, y: y - 1})) {
    } else if (this.moveTo({x, y}, {x, y: y + 1})) {
    }
  }

  clickHandle(value) {
    if (!this.isSuccess()) {
      this.clickSquare(value);
    }
    this.setState({squares: this.state.squares});
  }

  setSelectedValue(dim) {
    const squares = new Array();
    for (let i = 1; i < dim * dim; i++) {
      squares.push(i);
    }
    squares.push(0);
    this.setState({dim: dim, squares: squares});
  }

  render() {
    const status = this.isSuccess() ? '恭喜,您成功了!' : '请继续…';
    return (
      <View style={styles.container}>
        <Picker
          style={styles.Picker}
          selectedValue={this.state.dim}
          onValueChange={(itemValue, itemIndex) =>
            this.setSelectedValue(itemValue)
          }>
          <Picker.Item label="3" value="3" />
          <Picker.Item label="4" value="4" />
          <Picker.Item label="5" value="5" />
          <Picker.Item label="6" value="6" />
        </Picker>
        <Button title="重新开始" onPress={this.initBoard} />
        <View style={styles.board}>
          {this.state.squares.map((value, index) => (
            <Square
              key={index}
              value={value}
              onClick={() => this.clickHandle(value)}
              width={360 / this.state.dim - 10}
              height={360 / this.state.dim - 10}
            />
          ))}
        </View>
        <Text>{status}</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  squareNumber: {
    backgroundColor: '#cccccc',
  },
  square: {
    margin: 5,
    alignItems: 'center',
    justifyContent: 'center',
  },
  squareText: {
    fontSize: 24,
    fontWeight: 'bold',
  },
  board: {
    width: 370,
    height: 370,
    flexDirection: 'row',
    flexWrap: 'wrap',
    borderStyle: 'solid',
    borderWidth: 5,
    margin: 10,
  },
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  Picker: {
    width: 150,
    height: 50,
    backgroundColor: '#ccc',
    margin: 10,
  },
});

心得体会:开启本次实验之前,我们需要想清楚怎么样去布局整个棋盘,在进行点击方块的处理时,点击方块之后它便会向着空白处移动,如果周围没有空白处则无效移动,先自定义一个函数,通过一维数组知道该点的位置坐标,尝试向上移动,位置坐标x变成了x-1,y不变,若成功了则该函数执行完成,若失败再考虑其它方向位置移动。打乱棋盘是整体打乱并不是单纯的两两交换位置。最后运行看效果。通过本次实验,掌握了用react实现数字华容道游戏的基本流程及操作步骤,收获较大。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值