-
Notifications
You must be signed in to change notification settings - Fork 0
/
App.js
105 lines (93 loc) · 2.34 KB
/
App.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { useReducer } from 'react';
import make2dArray from './make2dArray';
import Board from './Board';
import copy2dArray from './copy2dArray';
import computeTicTacToeResult from './computeTicTacToeResult';
import GameDescription from './GameDescription';
import getPlayerToMove from './getPlayerToMove';
const BOARD_SIZE = 3;
function reducer(state, action) {
switch (action.type) {
case 'make-move': {
if (state.isGameOver) {
return state;
}
const newBoard = copy2dArray(state.board);
newBoard[action.rowIndex][action.columnIndex] = getPlayerToMove(
state.moveCount,
);
const { isGameOver, winner } = computeTicTacToeResult(newBoard);
return {
...state,
board: newBoard,
moveCount: state.moveCount + 1,
isGameOver,
winner,
};
}
case 'new-game': {
return makeInitialState();
}
}
return state;
}
function makeInitialState() {
return {
board: make2dArray(BOARD_SIZE, BOARD_SIZE, null),
moveCount: 0,
isGameOver: false,
winner: null,
};
}
export default function App() {
const [state, dispatch] = useReducer(reducer, undefined, makeInitialState);
return (
<View style={styles.container}>
<Text style={styles.title}>Tic-Tac-Toe</Text>
<Board
board={state.board}
isGameOver={state.isGameOver}
dispatch={dispatch}
/>
<GameDescription
winner={state.winner}
isGameOver={state.isGameOver}
moveCount={state.moveCount}
/>
{state.isGameOver && (
<TouchableOpacity
onPress={() => dispatch({ type: 'new-game' })}
style={styles.newGameButton}
>
<Text style={styles.newGameButtonText}>New Game</Text>
</TouchableOpacity>
)}
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
gap: 8,
},
newGameButton: {
position: 'absolute',
bottom: 100,
padding: 12,
borderRadius: 8,
backgroundColor: 'blue',
},
newGameButtonText: {
fontSize: 20,
color: 'white',
},
title: {
fontSize: 24,
},
});