vue3项目 / 三子棋
参考:
https://blog.csdn.net/iron_nini/article/details/130369453
App.vue
<template><div class="box"><div style="margin-bottom: 10px; font-size: 32px">{{ status }}</div><div class="board-row"><squareComponentv-for="(item, index) in squareValues":key="index":text="item"@on-click="handleClick(index)"/></div><button id="again"@click="handleAgain">Again</button></div>
</template><script setup>
import { ref, watchEffect } from 'vue';
import squareComponent from './squareComponent';const squareValues = ref(Array(9).fill(''));
const xIsNext = ref(true);
const status = ref('');const calculateWinner = (squares) => {const lines = [[0, 1, 2],[3, 4, 5],[6, 7, 8],[0, 3, 6],[1, 4, 7],[2, 5, 8],[0, 4, 8],[2, 4, 6]];for(let i = 0; i < lines.length; i++) {const [a, b, c] = lines[i];if(squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {return squares[a];}}return null;
}watchEffect(() => {if(calculateWinner(squareValues.value)){status.value = 'Winner: ' + calculateWinner(squareValues.value) + ' ! ';}else if(!squareValues.value.filter(item => item === '').length){status.value = 'Draw !';}else{status.value = 'Next player is ' + (xIsNext.value ? 'X' : 'O');}
});const handleClick = (index) => {if(squareValues[index] || calculateWinner(squareValues.value)) {return;}if(xIsNext.value) {squareValues.value[index] = 'X';}else {squareValues.value[index] = 'O';}xIsNext.value = !xIsNext.value;
}const handleAgain = () => {squareValues.value = Array(9).fill('');xIsNext.value = true;
}
</script><style scoped>
.box {width: 100%;height: 100vh;display: flex;flex-direction: column;align-items: center;justify-content: center;background: lightgreen;}
.board-row {display: grid;grid-template-columns: repeat(3, minmax(0,1fr));
}
#again {font-size: 32px;font-family:'Times New Roman', Times, serif;margin-top: 20px;
}
</style>
squareComponent.vue
<template><button class="square" @click="handleClick">{{ text }}</button>
</template><script>
export default{name: 'squareComponent',props:{text:{type: String,default: ''}},emits: ['on-click'],setup(props, context){const handleClick = () =>{context.emit('on-click', props.text);};return {handleClick};},
};
</script><style scoped lang="less">
.square{box-sizing: border-box;width: 100px;height: 100px;margin: 10px;border-radius: 50%;background: pink;color: black;font-weight: 700;font-family: 'Times New Roman', Times, serif;font-size: 32px;
}
</style>
效果预览