diff --git a/server/sample_data/sample_doudizhu.json b/server/sample_data/sample_doudizhu.json new file mode 100644 index 0000000..71585c6 --- /dev/null +++ b/server/sample_data/sample_doudizhu.json @@ -0,0 +1,150 @@ +{ + "initHands": [ + "S2 H2 HK DK HQ CQ DQ CJ S9 H9 D9 C7 S6 H6 C4 D4 S3", + "C2 HA CA DA SQ ST HT D8 S7 H7 C6 D6 S5 H5 C5 S4 H4", + "RJ BJ D2 SA SK CK SJ HJ DJ CT DT C9 S8 H8 C8 D7 D5 H3 S3 D3" + ], + "playerInfo": [ + { + "id": 0, + "index": 0, + "role": "peasant" + }, + { + "id": 1, + "index": 1, + "role": "peasant" + }, + { + "id": 2, + "index": 2, + "role": "landlord" + } + ], + "moveHistory": [ + { + "playerIdx": 2, + "move": "H3 S3 D3 D5" + }, + { + "playerIdx": 0, + "move": "S9 H9 D9 S3" + }, + { + "playerIdx": 1, + "move": "P" + }, + { + "playerIdx": 2, + "move": "SJ HJ DJ D7" + }, + { + "playerIdx": 0, + "move": "HQ CQ DQ C7" + }, + { + "playerIdx": 1, + "move": "P" + }, + { + "playerIdx": 2, + "move": "P" + }, + { + "playerIdx": 0, + "move": "C4 D4" + }, + { + "playerIdx": 1, + "move": "ST HT" + }, + { + "playerIdx": 2, + "move": "SK CK" + }, + { + "playerIdx": 0, + "move": "S2 H2" + }, + { + "playerIdx": 1, + "move": "P" + }, + { + "playerIdx": 2, + "move": "P" + }, + { + "playerIdx": 0, + "move": "S6 H6" + }, + { + "playerIdx": 1, + "move": "P" + }, + { + "playerIdx": 2, + "move": "CT DT" + }, + { + "playerIdx": 0, + "move": "HK DK" + }, + { + "playerIdx": 1, + "move": "P" + }, + { + "playerIdx": 2, + "move": "RJ BJ" + }, + { + "playerIdx": 0, + "move": "P" + }, + { + "playerIdx": 1, + "move": "P" + }, + { + "playerIdx": 2, + "move": "S8 H8 C8 C9" + }, + { + "playerIdx": 0, + "move": "P" + }, + { + "playerIdx": 1, + "move": "HA CA DA H5" + }, + { + "playerIdx": 2, + "move": "P" + }, + { + "playerIdx": 0, + "move": "P" + }, + { + "playerIdx": 1, + "move": "SQ" + }, + { + "playerIdx": 2, + "move": "D2" + }, + { + "playerIdx": 0, + "move": "P" + }, + { + "playerIdx": 1, + "move": "P" + }, + { + "playerIdx": 2, + "move": "SA" + } + ] +} \ No newline at end of file diff --git a/src/components/GameBoard/cards.css b/src/assets/cards.css similarity index 100% rename from src/components/GameBoard/cards.css rename to src/assets/cards.css diff --git a/src/components/GameBoard/index.scss b/src/assets/doudizhu.scss similarity index 100% rename from src/components/GameBoard/index.scss rename to src/assets/doudizhu.scss diff --git a/src/components/GameBoard/faces/JC.gif b/src/assets/faces/JC.gif similarity index 100% rename from src/components/GameBoard/faces/JC.gif rename to src/assets/faces/JC.gif diff --git a/src/components/GameBoard/faces/JD.gif b/src/assets/faces/JD.gif similarity index 100% rename from src/components/GameBoard/faces/JD.gif rename to src/assets/faces/JD.gif diff --git a/src/components/GameBoard/faces/JH.gif b/src/assets/faces/JH.gif similarity index 100% rename from src/components/GameBoard/faces/JH.gif rename to src/assets/faces/JH.gif diff --git a/src/components/GameBoard/faces/JS.gif b/src/assets/faces/JS.gif similarity index 100% rename from src/components/GameBoard/faces/JS.gif rename to src/assets/faces/JS.gif diff --git a/src/components/GameBoard/faces/KC.gif b/src/assets/faces/KC.gif similarity index 100% rename from src/components/GameBoard/faces/KC.gif rename to src/assets/faces/KC.gif diff --git a/src/components/GameBoard/faces/KD.gif b/src/assets/faces/KD.gif similarity index 100% rename from src/components/GameBoard/faces/KD.gif rename to src/assets/faces/KD.gif diff --git a/src/components/GameBoard/faces/KH.gif b/src/assets/faces/KH.gif similarity index 100% rename from src/components/GameBoard/faces/KH.gif rename to src/assets/faces/KH.gif diff --git a/src/components/GameBoard/faces/KS.gif b/src/assets/faces/KS.gif similarity index 100% rename from src/components/GameBoard/faces/KS.gif rename to src/assets/faces/KS.gif diff --git a/src/components/GameBoard/faces/QC.gif b/src/assets/faces/QC.gif similarity index 100% rename from src/components/GameBoard/faces/QC.gif rename to src/assets/faces/QC.gif diff --git a/src/components/GameBoard/faces/QD.gif b/src/assets/faces/QD.gif similarity index 100% rename from src/components/GameBoard/faces/QD.gif rename to src/assets/faces/QD.gif diff --git a/src/components/GameBoard/faces/QH.gif b/src/assets/faces/QH.gif similarity index 100% rename from src/components/GameBoard/faces/QH.gif rename to src/assets/faces/QH.gif diff --git a/src/components/GameBoard/faces/QS.gif b/src/assets/faces/QS.gif similarity index 100% rename from src/components/GameBoard/faces/QS.gif rename to src/assets/faces/QS.gif diff --git a/src/components/GameBoard/faces/README b/src/assets/faces/README similarity index 100% rename from src/components/GameBoard/faces/README rename to src/assets/faces/README diff --git a/src/components/GameBoard/faces/joker.gif b/src/assets/faces/joker.gif similarity index 100% rename from src/components/GameBoard/faces/joker.gif rename to src/assets/faces/joker.gif diff --git a/src/index.css b/src/assets/index.css similarity index 100% rename from src/index.css rename to src/assets/index.css diff --git a/src/components/GameBoard/index.js b/src/components/GameBoard/index.js index 404d64b..d434311 100644 --- a/src/components/GameBoard/index.js +++ b/src/components/GameBoard/index.js @@ -1,6 +1,6 @@ import React from 'react'; -import './index.scss'; +import '../../assets/doudizhu.scss'; class DoudizhuGameBoard extends React.Component { constructor(props) { @@ -15,9 +15,9 @@ class DoudizhuGameBoard extends React.Component { } translateCardData(card) { - let rankClass = ""; + let rankClass; let suitClass = ""; - let rankText = ""; + let rankText; let suitText = ""; // translate rank if(card === "RJ"){ @@ -51,7 +51,6 @@ class DoudizhuGameBoard extends React.Component { } computeSingleLineHand(cards) { - console.log(cards); if(cards === "P"){ return
Pass
}else{ @@ -68,7 +67,7 @@ class DoudizhuGameBoard extends React.Component { } computeSideHand(cards) { - let upCards = []; + let upCards; let downCards = []; if(cards.length > 10){ upCards = cards.slice(0, 10); @@ -107,7 +106,6 @@ class DoudizhuGameBoard extends React.Component { } playerDecisionArea(playerIdx){ - console.log(this.props.currentPlayer, playerIdx); if(this.props.currentPlayer === playerIdx){ return
{`Consideration Time: ${this.millisecond2Second(this.props.considerationTime)}s`}
}else{ @@ -115,6 +113,13 @@ class DoudizhuGameBoard extends React.Component { } } + componentDidUpdate(prevProps, prevState, snapshot) { + if(prevProps.turn !== this.props.turn){ + // new turn starts + this.props.runNewTurn(prevProps); + } + } + render() { // compute the id as well as index in list for every player const bottomId = this.props.mainPlayerId; @@ -140,7 +145,6 @@ class DoudizhuGameBoard extends React.Component { } return (
-
{`Current Player: ${this.props.currentPlayer} , Consideration Time: ${this.props.considerationTime}`}
diff --git a/src/index.js b/src/index.js index 87d1be5..0d8b9d7 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import './index.css'; +import './assets/index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; diff --git a/src/utils/index.js b/src/utils/index.js index da3f4ae..c45d893 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -19,3 +19,10 @@ export function removeCards(cards, hands){ // remove cards from hands, retur return remainedHands; } +export function doubleRaf (callback) { + // secure all the animation got rendered before callback function gets executed + requestAnimationFrame(() => { + requestAnimationFrame(callback) + }) +} + diff --git a/src/view/DoudizhuGameView.js b/src/view/DoudizhuGameView.js index 22e0aa4..35751a7 100644 --- a/src/view/DoudizhuGameView.js +++ b/src/view/DoudizhuGameView.js @@ -1,15 +1,15 @@ import React from 'react'; import DoudizhuGameBoard from '../components/GameBoard'; import webSocket from "socket.io-client"; -import {removeCards} from "../utils"; +import {removeCards, doubleRaf} from "../utils"; class DoudizhuGameView extends React.Component { constructor(props) { super(props); const mainViewerId = 0; // Id of the player at the bottom of screen - this.initConsiderationTime = 2000; - this.considerationTimeDeduction = 1000; + this.initConsiderationTime = 0; + this.considerationTimeDeduction = 100; this.gameStateTimeout = null; this.initGameState = { @@ -20,7 +20,7 @@ class DoudizhuGameView extends React.Component { turn: 0, currentPlayer: null, considerationTime: this.initConsiderationTime, - } + }; this.state = { ws: null, @@ -86,7 +86,6 @@ class DoudizhuGameView extends React.Component { break; case 1: // getting player actions - console.log(message.message); let res = message.message; if(res.turn === this.state.gameInfo.turn && res.playerIdx === this.state.gameInfo.currentPlayer){ let gameInfo = JSON.parse(JSON.stringify(this.state.gameInfo)); @@ -101,8 +100,9 @@ class DoudizhuGameView extends React.Component { console.log("Cannot find cards in move from player's hand"); } gameInfo.considerationTime = this.initConsiderationTime; - this.setState({gameInfo: gameInfo}); - this.gameStateTimer(); + this.setState({gameInfo: gameInfo}, ()=>{ + + }); }else{ console.log("Mismatched game turn or current player index", message); } @@ -116,6 +116,26 @@ class DoudizhuGameView extends React.Component { this.setState({ws: ws}); }; + runNewTurn(prevTurn){ + // check if the game ends + if(this.state.gameInfo.hands[prevTurn.currentPlayer].length === 0){ + doubleRaf(()=>{ + const winner = this.state.gameInfo.playerInfo.find(element => { + return element.index === prevTurn.currentPlayer; + }); + if(winner){ + if(winner.role === "landlord") + alert("Landlord Wins"); + else + alert("Peasants Win"); + }else{ + console.log("Error in finding winner"); + } + }); + }else + this.gameStateTimer(); + } + render(){ return (
@@ -127,12 +147,17 @@ class DoudizhuGameView extends React.Component { mainPlayerId={this.state.gameInfo.mainViewerId} currentPlayer={this.state.gameInfo.currentPlayer} considerationTime={this.state.gameInfo.considerationTime} + turn={this.state.gameInfo.turn} + runNewTurn={(prevTurn)=>this.runNewTurn(prevTurn)} />
{this.connectWebSocket()}} /> {this.startReplay()}} />
+
+ {`Current Player: ${this.state.gameInfo.currentPlayer} , Consideration Time: ${this.state.gameInfo.considerationTime}, Turn: ${this.state.gameInfo.turn}`} +
) }