react + nodejs 在线五子棋对战平台

gitee地址:https://gitee.com/alen_ou/Gobang
在线对战地址:http://106.52.176.106:8099/
核心代码:
server.js

var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
// var io = require('socket.io').listen(1314);
var userNum = 0; //记录在线人数
// var role=true;//用来分配下棋人角色 true:白旗;false:黑旗
var onlineUser = {}; //存储在线人的信息

io.on('connection', function(socket) {
    let name = "";
    socket.on('login', function(obj) {
        onlineUser[socket.id] = obj;
        //谁来的跟谁分配权限  下黑旗,白旗还是观战
        userNum++;
        if (userNum == 1) {
            onlineUser[socket.id] = Object.assign(obj, { role: false });
        } else if (userNum == 2) {
            onlineUser[socket.id] = Object.assign(obj, { role: true });
        } else if (userNum > 2) {
            onlineUser[socket.id] = obj;
        }
        var player = 0;
        var playRole = null;
        for (let key in onlineUser) {
            var user = onlineUser[key];
            // console.log("用户信息", user);
            if (user.hasOwnProperty("role")) {
                player++;
                playRole = user.role;
                // console.log("playRole=" + playRole);
            }
        }
        if (player < 2 && userNum >= 2) {
            console.log(1111)
            onlineUser[socket.id] = Object.assign(obj, { role: !playRole });
        }
        name = obj.username;
        io.to(socket.id).emit('role', onlineUser[socket.id]); //将身份信息(下黑旗还是白旗)传过去
        io.emit('online', onlineUser); //将在线人员名单带过去
        io.sockets.emit("systemMsg", { msg: "欢迎【" + name + "】加入群聊", type: 1 });
        // console.log(obj.username, 'is loginning');
        // console.log('在线用户', onlineUser);
    })
    socket.on('disconnect', function() {
        // console.log(socket.id, 'disconnected');
        var flag = null;
        if (onlineUser.hasOwnProperty(socket.id)) { //disconnect的时候,将它从onlineUser里删掉
            var user = onlineUser[socket.id];
            if (user.hasOwnProperty("role")) {
                flag = user.role;
            }
            delete onlineUser[socket.id];
            userNum--;
        }
        //若退出的用户是棋手角色,则判断是否还有用户没有角色,有则随机分配给没有角色的用户
        var player = null;
        for (let key in onlineUser) {
            if (!onlineUser[key].hasOwnProperty('role')) {
                onlineUser[key]['role'] = flag
            }
        }
        //用来同步数据在线人数   
        io.emit('online', onlineUser);
        if (name !== "" && name !== null) {
            io.emit("systemMsg", { msg: "用户【" + name + "】离开群聊", type: 0 });
        }
        //console.log('在线用户', onlineUser, '在线人数', userNum);
    });
    //聊天
    socket.on('chat', function(msg) {
        // 参数为下到什么坐标和目前是黑方or白方
        console.log(name + ":" + msg);
        // console.log(msg.player?'黑方':'白方','落子在: ' + msg.place);
        io.sockets.emit('chat', { name, msg });
    });
    //下棋
    socket.on("playChess", function(msg) {
        // console.log(msg.player ? '黑方' : '白方', '落子在: ' + msg.place);
        io.emit('playChess', msg);
    });
    socket.on('reset', function(msg) {
        //参数为目前黑旗or白旗
        // console.log('清除重来');
        io.emit('reset', msg);
    });
});

http.listen(1314, function() {
    console.log('listening on :1314');
});

前端核心代码:

import React from "react";
import Header from '../component/Header'
// import Control from '../component/Control'
import isSuccess from '../util/FiveSuccess'
import { message, Modal } from 'antd'

import common from '../util/common'
import io from 'socket.io-client';
var socket = io.connect('http://localhost:1314');

const getUsers = (users) => {
    var userArry = []
    var playerArry = []
    for (let key in users) {
        if (users[key].hasOwnProperty('role')) {
            playerArry.push(users[key]);
        }
        userArry.push(users[key]);
    }
    return {
        user: userArry,
        player: playerArry
    };
}

export default class Gobang extends React.Component {
    constructor() {
        super();
        this.state = this.initStart();
    }

    //初始化
    initStart() {
        var boardData = [];
        //棋盘大小
        for (var i = 0; i < 15; i++) {
            boardData.push(Array(15).fill(0));
        }
        this.history = [];

        return {
            //棋盘数据
            boardData,
            //胜负是否已分
            success: false,
            //是否黑子
            isBlack: false,
            currentUser: {},
            username: "",
            users: [],//登录用户
            sysmsg: [],//系统消息
            messages: []//聊天消息
        }
    }
    //悔棋
    unDo() {
        // console.log(this.history);
        // console.log(this.history.pop())
        if (this.history.length === 0) {
            message.warn("没有棋子了")
            return
        }
        this.setState(this.history.pop())
    }
    //重新开始
    reStart() {
        socket.emit("reset","重新开始")
        // var boardData = [];
        // //棋盘大小
        // for (var i = 0; i < 15; i++) {
        //     boardData.push(Array(15).fill(0));
        // }
        // this.setState({
        //     //棋盘数据
        //     boardData,
        //     //胜负是否已分
        //     success: false,
        //     //是否黑子
        //     isBlack: false,
        // })
    }

    //登录
    login(value) {
        //var value = e.target.value;
        if (!common.isChina(value)) {
            message.error("昵称必须包含中文");
            return;
        }
        socket.emit("login", { "username": value });
        // var _this = this;        
        this.setState({
            username: value
        })

        this.socketOn();
    }

    //聊天
    sendMsg(inpVal) {
        // var _this = this;
        // const inpVal = this.input.value;
        if (inpVal === "") {
            message.error("不能发送空消息")
            return;
        }
        socket.emit("chat", inpVal);
    }

    //监听
    socketOn() {
        var _this = this;
        //监听 更新在线人数据
        socket.on("online", function (res) {
            _this.setState({
                users: res
            })
        })
        //监听系统广播消息,主要提示用户有谁加入群聊了
        socket.on("systemMsg", function (res) {
            // console.log(res);
            var messages = [];
            var index = 0;
            if (_this.state.sysmsg.length > 0) {
                index = _this.state.sysmsg.length + 1;
                _this.state.sysmsg.map((item, idx) => {
                    messages.push(item);
                })
            }
            if (res.type === 0) {
                messages.push(<div key={index} className="sys-msg" style={{ color: 'red' }}>{new Date().toLocaleString() + "  " + res.msg}</div>);
            } else {
                messages.push(<div key={index} className="sys-msg">{new Date().toLocaleString() + "  " + res.msg}</div>);
            }

            //_this.state.sysmsg.push()
            _this.setState({
                sysmsg: messages
            })
        })
        //监听 广播聊天消息
        socket.on("chat", function (res) {
            var messages = []
            var index = 0;
            if (_this.state.messages.length > 0) {
                index = _this.state.messages.length + 1;
                _this.state.messages.map((item, idx) => {
                    messages.push(item);
                })
            }
            console.log(res)
            if (res.name == _this.state.username) {
                messages.push(<div key={index} className="rightd">
                    <span className="rightd_h">
                        {res.name}
                    </span>
                    <div className="speech right">
                        {res.msg}
                    </div>
                </div>)
            } else {
                messages.push(
                    <div key={index} className="leftd">
                        <span className="leftd_h">
                            {res.name}
                        </span>
                        <div className="speech left">
                            {res.msg}
                        </div>
                    </div>
                )
            }
            // console.log(messages);
            _this.setState({
                messages: messages
            })
        })
        //监听下棋
        socket.on("playChess", function (res) {
            const { boardData } = _this.state; //isBlack, success

            _this.history.push(JSON.parse(JSON.stringify(_this.state)));
            var row = res.place.row;
            var col = res.place.col;
            var isBlack = res.place.isBlack;
            boardData[row][col] = !isBlack ? 1 : 2;

            var isFiveSuccess = isSuccess(boardData, row, col);

            _this.setState({
                boardData,
                isBlack: !isBlack,
                success: isFiveSuccess
            })
        })

        //监听,重新开始
        socket.on("reset", (res) => {
            var boardData = [];
            //棋盘大小
            for (var i = 0; i < 15; i++) {
                boardData.push(Array(15).fill(0));
            }
            _this.setState({
                //棋盘数据
                boardData,
                //胜负是否已分
                success: false,
                //是否黑子
                isBlack: false,
            })
        })
    }

    componentWillUnmount() {
        // 卸载异步操作设置状态
        clearTimeout(this.timeouter)
        this.setState = (state, callback) => {
            return
        }
    }

    componentDidUpdate() {
        if (this.state.success) {
            Modal.success({
                // icon: <ExclamationCircleOutlined/>,
                content: `恭喜【${this.state.isBlack ? '白棋' : '黑棋'}】获得游戏胜利`,
                // cancelText: "取消",
                okText: "确定",
                // onOk() {
                //     console.log('OK');
                // },
                // onCancel() {
                //     console.log('Cancel');
                // },
            });
        }
    }
    //下棋
    playPress(row, col) {
        if (this.state.username === "") {
            message.warn("来者何人?还不速速报上名来!");
            return;
        }
        //判断是否有下棋权限
        var user = this.state.users[socket.id];
        if (user.username === this.state.username && !user.hasOwnProperty("role")) {
            message.warn("你只能观战!");
            return;
        }
        //判断黑白棋手是否都在线,若没有则不能下棋了
        var users = getUsers(this.state.users);
        if (users.player.length < 2) {
            message.warn("没有对手,胜之无趣!");
            return;
        }

        //判断是否该当前用户下
        if (user.role !== this.state.isBlack) {
            message.warn("猴急啥,还没到你呢!");
            return;
        }

        const { success } = this.state;//boardData, isBlack,

        if (success) {
            message.warn("本局已结束,请开始下一局");
            return;
        }

        //socket
        var dd = {
            place: {
                row,
                col,
                isBlack: user.role
            },
            player: socket.id
        }
        socket.emit("playChess", dd)
        // console.log(this.history);

        // boardData[row][col]=!isBlack?1:2;

        // var isFiveSuccess = isSuccess(boardData,row,col);

        // this.setState({
        //     boardData,
        //     isBlack:!isBlack,
        //     success:isFiveSuccess
        // })
    }

    render() {
        // console.log(this.history);
        return (
            <div>
                <Header
                    history={this.history}
                    unDo={this.unDo.bind(this)}
                    reStart={this.reStart.bind(this)}
                    isBlack={this.state.isBlack}
                    username={this.state.username}
                    users={this.state.users}
                    messages={this.state.messages}
                    sysmsg={this.state.sysmsg}
                    login={this.login.bind(this)}
                    sendMsg={this.sendMsg.bind(this)}
                    boardData={this.state.boardData}
                    playPress={this.playPress.bind(this)}
                />
                {/* <Control boardData={this.state.boardData} playPress={this.playPress.bind(this)}/> */}
            </div>
        )
    }
}

注意:前后端的socket版本必须一致!!!在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个程序猿cc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值