上篇已经生成了数独题目,这篇是关于react-native界面实现的部分,说实在的,react-native对于复杂界面的实现还是有点困难,当然这个还不算太复杂,可能是因为本身与安卓原生的设计思路是有很大的不同,然后个人不习惯吧
github源码地址
界面比较简单,进去就是三个菜单,分别对应不同的难度,其实就是扣掉不同数量的数字,达到难度的划分。扣掉的数字,填上0。另外关于数独题目的问题,其实这个出题是不科学的,因为随机扣掉数字,并不能保证出的题目一定有唯一解,甚至不一定有解,本身需要倒退去完成这道数独,验证之后才能是完成,这个太复杂,市面上的数独游戏其实都是有题库的,不可能在手机上出题的,题外话。
先看react-native实现的网格布局,用来填充数独的题目。
_renderBoard(id, position, num, ViewId) {
if (num.type != 0) {
return (
<View style={[Styles.Board, position]} key={id}>
<Text style={Styles.Text}>
{this._showNum(num.num)}
</Text>
</View>
)
} else {
return (
<View style={[Styles.Board, position, this._chosen(ViewId)]} key={id}>
<Text style={[Styles.Text, {color: 'green'}]}
onPress={()=>this._click(ViewId)}>
{this._showNum(num.num)}
</Text>
</View>
)
}
}
先画好单个格子,比较简单,每个控件需要有一个key,这个地方满坑的,其实这个key没用到,但是如果不传,就会报错,传重复的也会报错。我直接i++传进去的。num会有两个值type是用来判断这个值是不是需要填写的,题目里的数字是不能填写的,就用这个来判断。
//获取数独题目
export function _getSudoku(hard) {
let Sudoku = _calculateData();
for (let x = 0; x < 9; x++) {
for (let y = 0; y < 9; y++) {
Sudoku[x][y] = {num: Sudoku[x][y], type: 1}
}
}
for (let i = 0; i < hard; i++) {
let x = Math.floor(Math.random() * 9);
let y = Math.floor(Math.random() * 9);
if (Sudoku[x][y].type == 0) {
i--
} else {
Sudoku[x][y] = {num: 0, type: 0};
}
}
console.log(Sudoku);
return Sudoku;
}
position就是用来排列的位置,这个不多说了,看我的源码吧。
//循环添加每个格子
_renderAll() {
let result = [];
let i = 0;
for (let row = 0; row < SIZE; row++) {
for (let col = 0; col < SIZE; col++) {
// 位置
let position = {
left: col * BOARDSIZE,
top: row * BOARDSIZE,
}
position = this._boardBGC(row, col, position)
let ViewId = [row, col]
let num = this.state.Sudoku[row][col]
result.push(this._renderBoard(i++, position, num, ViewId));
// console.log("position=>>>(" + position.left + "," + position.top + ")")
}
}
return result;
}
然后绘制下面的键盘,如法炮制,一个是格子,不同的是它有间隔。
键盘点击会有一个动画,这边我觉得react-native的动画用起来不是很舒服,不太好理解。
先在state里初始化10个动画,就是对应十个键
constructor(props) {
super(props);
let animated = new Array(10);
for (var i = 0; i < animated.length; i++) {
animated[i] = new Animated.Value(0);
}
this.state = {animated};
}
用Animated.View带上动画效果
//数字及取消
_renderKey(id, position, num) {
return (
<Animated.View
key={id}
style={[Styles.Key, position]}
onStartShouldSetResponder={() => this._clickNum(id, num)}>
<Text style={Styles.Num}>{num}</Text>
</Animated.View>
)
}
然后按键点击后播放动画,就是start
//点击数字键
_clickNum(id, num) {
let animated = this.state.animated[id];
animated.setValue(1.5);
Animated.spring(
animated,
{
toValue: 1,
friction: 3,
}
).start();
this.props.Num(num);
}
其他关于逻辑上的处理没有什么难度了,一些样式处理之类。
虽然东西不多,但是界面还是花了差不多一整天时间,如果用原生开发根本用不了这么多时间,而且效果也会更好,当然主要还是对react-native不是很熟悉,写多了可能会好一点。
毕竟拥抱新技术嘛,虽然坑还是不少。