实验目的
- 巩固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实现数字华容道游戏的基本流程及操作步骤,收获较大。