-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
jser
committed
Aug 10, 2024
1 parent
12c956e
commit 4f90134
Showing
19 changed files
with
10,986 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
name: tic-tac-toe | ||
on: | ||
push: | ||
branches: | ||
- main | ||
permissions: | ||
contents: write | ||
jobs: | ||
build-and-deploy: | ||
concurrency: ci-${{ github.ref }} # Recommended if you intend to make multiple deployments in quick succession. | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout 🛎️ | ||
uses: actions/checkout@v4 | ||
|
||
- name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. | ||
run: | | ||
yarn install | ||
yarn build | ||
- name: Deploy 🚀 | ||
uses: JamesIves/github-pages-deploy-action@v4 | ||
with: | ||
folder: build # The folder the action should deploy. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
.idea/ | ||
/node_modules/ | ||
/build/ | ||
/.obsidian/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,20 @@ | ||
# tic-tac-toe | ||
# tic-tac-toe | ||
|
||
## Requirement | ||
|
||
This is the case from <https://react.dev/learn/tutorial-tic-tac-toe>. But I implement it without guide from the tutorial. | ||
|
||
## Analyzing procedure | ||
|
||
It's a good way to analyze the procedure of implementation. Just use the mind map to explore uncertain. It will helps you to reduce bug rates. I shared the whole procedure with photo. | ||
|
||
![[/docs/images/react-tic-tac-toe.png]](/docs/images/react-tic-tac-toe.png) | ||
## Implementation | ||
|
||
I uploaded the code to GitHub. See it at <https://github.com/ustinian-wang/tic-tac-toe> | ||
The implementation seems not perfect. I see. I have the plan to optimize code in the next. Just give the time, please. | ||
|
||
## Preview | ||
|
||
You can play it online yourself. See it at <https://ustinian-wang.github.io/tic-tac-toe/> | ||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module.exports = { | ||
watchPlugins: [ | ||
'jest-watch-typeahead/filename', | ||
'jest-watch-typeahead/testname' | ||
] | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,86 @@ | ||
import GridTable from "./components/GridTable"; | ||
import { GameProcess } from "./components/GameProcess"; | ||
import RecordHistory from "./components/RecordHistory"; | ||
import { useState } from "react"; | ||
import { getGrids } from "./business/Grid"; | ||
import { RoleManager } from "./business/RoleManager"; | ||
import { RecordManager } from "./business/RecordManager"; | ||
import { getWinner } from "./business/game"; | ||
|
||
function MyButton() { | ||
return ( | ||
<button> | ||
I'm a button | ||
</button> | ||
); | ||
} | ||
export default function MyApp() { | ||
let grids = getGrids(); | ||
let role = RoleManager.getCurrRole(); | ||
let roles = RoleManager.getRoles(); | ||
let records = RecordManager.getRecords(); | ||
let currRecords = RecordManager.getCurrentRecords(); | ||
// let records = RecordHistory.getRecords(); | ||
const [gridsValue, setGridsValue] = useState(grids); | ||
const [roleValue, setRoleValue] = useState(role); | ||
const [rolesValue, setRolesValue] = useState(roles); | ||
const [recordsValue, setRecordsValue] = useState(records); | ||
const [currRecordsValue, setCurrRecordsValue] = useState(currRecords) | ||
|
||
|
||
|
||
const onClickGrid = (index)=>{ | ||
let grid = grids[index]; | ||
let winner = getWinner(roles, grids); | ||
if(grid.use(role.roleId) && !winner){ | ||
|
||
//交换角色 | ||
role = RoleManager.exchangeRoles(); | ||
setRoleValue(role); | ||
roles = RoleManager.getRoles(); | ||
setRolesValue(roles); | ||
|
||
//增加一条操作记录 | ||
RecordManager.add(role.roleId, grid.gridId); | ||
records = RecordManager.getRecords(); | ||
currRecords = RecordManager.getCurrentRecords(); | ||
setRecordsValue(records); | ||
setCurrRecordsValue(currRecords); | ||
} | ||
setGridsValue(grids); | ||
} | ||
|
||
const onClickRecord = (index)=>{ | ||
RecordManager.changeCursor(index); | ||
|
||
currRecords = RecordManager.getCurrentRecords(); | ||
setCurrRecordsValue(currRecords); | ||
initGridsByCurrRecords(currRecords); | ||
} | ||
|
||
function initGridsByCurrRecords(currRecords){ | ||
const gridsMapById = {}; | ||
grids.forEach(grid=>{ | ||
gridsMapById[grid.gridId] = grid; | ||
grid.clear(); | ||
}) | ||
|
||
currRecords.forEach(record=>{ | ||
let { | ||
roleId, | ||
gridId | ||
} = record; | ||
let grid = gridsMapById[gridId]; | ||
grid.use(roleId); | ||
}) | ||
|
||
setGridsValue(grids); | ||
} | ||
|
||
|
||
return ( | ||
<div> | ||
<h1>Welcome to my app</h1> | ||
<MyButton /> | ||
<div style={{display: 'flex'}}> | ||
<div> | ||
<GameProcess role={roleValue} roles={rolesValue} grids={gridsValue}></GameProcess> | ||
<GridTable grids={gridsValue} role={roleValue} onClickGrid={onClickGrid}/> | ||
</div> | ||
<div> | ||
<RecordHistory records={recordsValue} onClickRecord={onClickRecord}></RecordHistory> | ||
</div> | ||
</div> | ||
|
||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { RoleManager } from "./RoleManager"; | ||
import { isEmptyArr } from "@ustinian-wang/kit"; | ||
import { getUid } from "../utils"; | ||
|
||
const GridStatusDef = { | ||
BLANK: 1, | ||
PLAYED: 2 | ||
} | ||
|
||
export class Grid { | ||
constructor() { | ||
this.status = GridStatusDef.BLANK; | ||
this.roleId = 0; | ||
this.gridId = getUid() | ||
} | ||
|
||
changeSingleStatus( status ) { | ||
if ( status !== GridStatusDef.BLANK ) { | ||
this.status = status; | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
changeStatus( status ) { | ||
this.status = status; | ||
} | ||
|
||
changeRole( roleId ) { | ||
this.roleId = roleId | ||
} | ||
|
||
use(roleId){ | ||
if( this.status===GridStatusDef.BLANK){ | ||
this.roleId = roleId; | ||
this.status = GridStatusDef.PLAYED; | ||
return true; | ||
} | ||
return false; | ||
} | ||
clear(){ | ||
this.status = GridStatusDef.BLANK; | ||
this.roleId = 0; | ||
} | ||
|
||
getGridContent() { | ||
let role = RoleManager.getRole( this.roleId ); | ||
if ( this.status === GridStatusDef.BLANK ) { | ||
return ""; | ||
} else { | ||
if ( role ) { | ||
return role.getName(); | ||
} else { | ||
// console.error( "role should exist" ) | ||
return ""; | ||
} | ||
} | ||
|
||
} | ||
|
||
static getInstance() { | ||
return new Grid(); | ||
} | ||
} | ||
|
||
let list = [] | ||
export function getGrids(){ | ||
if(isEmptyArr(list)){ | ||
for ( let i = 0; i < 9; i++ ) { | ||
let grid = Grid.getInstance(); | ||
list.push( grid ); | ||
} | ||
} | ||
return list; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
|
||
export class Record { | ||
constructor(roleId, gridId) { | ||
this.roleId = roleId; | ||
this.gridId = gridId; | ||
} | ||
|
||
changeRole(roleId){ | ||
this.roleId = roleId; | ||
} | ||
changeGrid(gridId){ | ||
this.gridId = gridId; | ||
} | ||
|
||
static getInstance(roleId, gridId){ | ||
return new Record(roleId, gridId) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { Record } from "./Record"; | ||
|
||
class RecordManagerFactory{ | ||
constructor() { | ||
this.list = []; | ||
this.cursor = -1; | ||
} | ||
|
||
changeCursor(index){ | ||
this.cursor = index; | ||
} | ||
|
||
next(){ | ||
if(this.cursor>this.list.length){ | ||
return; | ||
} | ||
this.cursor++; | ||
} | ||
|
||
prev(){ | ||
if(this.cursor<=0){ | ||
return; | ||
} | ||
this.cursor--; | ||
} | ||
|
||
add(roleId, gridId){ | ||
this.clearRestOfNext() | ||
this.cursor++; | ||
this.list.push(Record.getInstance(roleId, gridId)) | ||
} | ||
|
||
clearRestOfNext(){ | ||
this.list.splice(this.cursor+1); | ||
} | ||
|
||
getCurrentRecords(){ | ||
return this.list.slice(0, this.cursor+1); | ||
} | ||
|
||
getRecords(){ | ||
return this.list; | ||
} | ||
} | ||
|
||
export const RecordManager = new RecordManagerFactory() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { getUid } from "../utils"; | ||
|
||
export const RoleTypeDef = { | ||
X: 1, | ||
O: 2 | ||
} | ||
|
||
export class Role { | ||
constructor( type ) { | ||
this.type = type; | ||
this.roleId = getUid(); | ||
} | ||
|
||
static getInstance( type ) { | ||
return new Role( type ) | ||
} | ||
|
||
getName() { | ||
return this.type === RoleTypeDef.X ? "X" : "O"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { Role, RoleTypeDef } from "./Role"; | ||
class RoleManagerFactor{ | ||
constructor() { | ||
this.list = []; | ||
let roleX = Role.getInstance(RoleTypeDef.X); | ||
let roleO = Role.getInstance(RoleTypeDef.O); | ||
this.list.push(roleO, roleX); | ||
} | ||
getCurrRole(){ | ||
return this.list[0] | ||
} | ||
getRole( roleId ) { | ||
return this.list.find( role => role.roleId === roleId ) | ||
} | ||
exchangeRoles(){ | ||
this.list.reverse(); | ||
return this.list[0]; | ||
} | ||
getRoles(){ | ||
return this.list; | ||
} | ||
|
||
} | ||
|
||
export const RoleManager = new RoleManagerFactor() |
Oops, something went wrong.