React Native中如何从表格渲染随机对象?(记忆游戏洗牌需求)
Hey there! Let's get your memory game's shuffle functionality working properly, and also clean up some key issues in your current code that are holding you back.
First, let's address the problems in your existing setup:
- Your
cardsstate is a string ("[...card]") instead of an actual array of card data. We need to store your card values/objects in a proper array to shuffle them. - Using duplicate
ref="card"won't work—refs need unique identifiers, and more importantly, we should use data-driven rendering instead of relying on refs for your cards. - Your placeholder shuffle function needs a tailored implementation for memory game cards (which usually require matching pairs) that deviates from the standard JS shuffle.
Step 1: Implement a Custom Non-Standard Shuffle Function
You mentioned avoiding the "standard JS shuffle"—let's use a modified Fisher-Yates (Knuth) shuffle that adds an extra layer of randomness, plus builds paired card data perfect for a memory game:
// Custom shuffle with extra randomization twist _shuffleCards = () => { // Create paired card values (adjust quantity/values as needed) const cardValues = [1, 2, 3, 4, 1, 2, 3, 4]; let shuffled = [...cardValues]; for (let i = shuffled.length - 1; i > 0; i--) { // Standard Fisher-Yates swap const j = Math.floor(Math.random() * (i + 1)); [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; // Extra random swap 30% of the time for non-standard behavior if (Math.random() < 0.3) { const k = Math.floor(Math.random() * (i + 1)); [shuffled[i], shuffled[k]] = [shuffled[k], shuffled[i]]; } } return shuffled; };
Step 2: Refactor Your Component for Data-Driven Rendering
We'll rewrite your component to use the shuffled card array to render the grid dynamically, instead of hardcoding rows. This makes shuffling and updating cards trivial:
import React from 'react' import { StyleSheet, View, Text, TouchableOpacity } from 'react-native' import { Col, Row, Grid } from "react-native-easy-grid"; export default class App extends React.Component { constructor(props) { super(props); this.state = { color: "red", cards: [] // Empty array to hold shuffled card data } } // Custom shuffle function with extra randomization _shuffleCards = () => { const cardValues = [1, 2, 3, 4, 1, 2, 3, 4]; let shuffled = [...cardValues]; for (let i = shuffled.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; // Extra random swap to deviate from standard shuffle if (Math.random() < 0.3) { const k = Math.floor(Math.random() * (i + 1)); [shuffled[i], shuffled[k]] = [shuffled[k], shuffled[i]]; } } return shuffled; } componentDidMount() { // Initialize shuffled cards when component loads this.setState({ cards: this._shuffleCards() }); } _test = () => { this.setState({ color: this.state.color === "red" ? "blue" : "red" }); } // Helper to render rows dynamically from card data renderRows = () => { const { cards } = this.state; const rows = []; // Split cards into individual rows (matches your 1-column grid) for (let i = 0; i < cards.length; i++) { rows.push( <Row key={i}> <TouchableOpacity onPress={this._test} style={styles.card}> <Text style={styles.cardText}>{cards[i]}</Text> </TouchableOpacity> </Row> ); } return rows; } render() { return ( <View style={styles.container}> <Grid> <Col> {this.renderRows()} </Col> </Grid> <View style={styles.colorIndicator}> <Text style={{ color: this.state.color }}>XXX</Text> </View> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', padding: 20, }, card: { flex: 1, justifyContent: 'center', alignItems: 'center', borderWidth: 1, borderColor: '#ccc', margin: 5, padding: 15, borderRadius: 8, }, cardText: { fontSize: 18, fontWeight: '500', }, colorIndicator: { marginTop: 20, fontSize: 24, }, });
Key Improvements Explained:
- Data-Driven Rendering: Rows are generated dynamically from the shuffled
cardsarray, so shuffling only requires updating the state array—no messy refs needed. - Custom Shuffle: The extra random swap step makes this implementation different from the standard Fisher-Yates shuffle, as you requested.
- Clean State: We store actual card data in the state instead of strings, making the component far more maintainable.
- Better Styling: Added basic card styling to make the game board more intuitive.
If you want to expand the game (e.g., add card images, unique IDs, or flip functionality), you can modify the cardValues array to hold objects instead of numbers (like [{ id: 1, value: '🍎' }, { id: 2, value: '🍎' }, ...]).
内容的提问来源于stack exchange,提问作者Roland Doe

