AutoHotKey实现局域网内答题游戏!

服务器端

#singleinstance force
OnExit, exit
;ip和端口
Network_Address = 0.0.0.0
Network_Port = 1000

;游戏数据
QA := []
QA.insert({"Question":"一天有多少个小时","Answer":"A","A":"24个小时","B":"12个小时","C":"30个小时","D":"365个小时"})
QA.insert({"Question":"中国居民用电的电压是多少伏","Answer":"D","A":"110V","B":"48V","C":"380V","D":"220V"})
QA.insert({"Question":"林俊杰是哪里人","Answer":"C","A":"台湾","B":"香港","C":"新加坡","D":"马来西亚"})
QA.insert({"Question":"一杯水测试PH值为8表示","Answer":"B","A":"酸性","B":"碱性","C":"辣的","D":"有毒"})

;创建窗口以接收数据
Gui, add, Edit, x0 y0 w400 h200 vshow,
Gui, add, Button, x0 y200 w400 h20 gchange, 换题
gui, add, text, x400 y0 w100 h20, 以下玩家加入:
gui, Add, ListBox, x400 y20 w100 h200 vlist
gui, Show, , 答题游戏局域网服务器
;准备传入连接
socket := PrepareForIncomingConnection(Network_Address, Network_Port)
if socket = -1
    ExitApp
Process, Exist
NotificationMsg := 0x5555,FD_Read := 1,FD_CLOSE := 32,FD_CONNECT := 20    ;消息号 大于0x1000;当消息可以读取时接收;当连接关闭后时接收
;设置接收消息的函数
OnMessage(NotificationMsg, "ReceiveData")
;设置接收关联
if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", A_ScriptHwnd, "UInt", NotificationMsg, "Int", FD_READ|FD_CONNECT)
{
    MsgBox % "WSAAsyncSelect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
    ExitApp
}
;循环获取新连入客户端
user := []
i=1
Loop
{
    VarSetCapacity(SocketAddress, SizeOfSocketAddress:=16)
    ;Socket连接
    conectioncheck%i% := DllCall("Ws2_32\accept", "UInt", socket, "UInt", &SocketAddress, "Int*", SizeOfSocketAddress)
    if conectioncheck%i% != -1
    {
        ;该客户端连接对象为conectioncheck%i% 发送数据时需要
        ;客户端IP:端口 xxx.xxx.xxx.xxx:xxxx
        peername := DllCall("Ws2_32\inet_ntoa", "uint", NumGet(SocketAddress,4), "str")
            . ":" NumGet(SocketAddress,2,"ushort")
        user["" peername] := conectioncheck%i%
        ;发送欢迎信息
        ;SendData(conectioncheck%i%,"欢迎" peername)
        ;添加到列表
        list =
        for k,v in user
            list .= "|" k
        GuiControl, , list, % list
        i++
    }
    sleep 500
}
return

;换题
change:
SendText = Clean
gosub, sendall
ct = 0
for k in QA
    ct++
Random, Q_id, 1, % ct
SendText := QA[Q_id]["Question"] "?nA:" QA[Q_id]["A"] "tB:" QA[Q_id]["B"] "tC:" QA[Q_id]["C"] "tD:" QA[Q_id]["D"] GuiControl, , show, % "当前题目:n" SendText "n答案:" QA[Q_id]["Answer"] gosub, sendall return ;给所有客户端发消息 sendall: Loop %i% { SendData(conectioncheck%A_Index%,SendText) } SendText= return ;准备传入连接函数 PrepareForIncomingConnection(IPAddress, Port) { VarSetCapacity(wsaData, 32) result := DllCall("Ws2_32\WSAStartup", "UShort", 0x0002, "UInt", &wsaData) ; Request Winsock 2.0 (0x0002)
if ErrorLevel
{
    MsgBox WSAStartup() could not be called due to error %ErrorLevel%. Winsock 2.0 or higher is required.
    return -1
}
if result
{
    MsgBox % "WSAStartup() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
    return -1
}

AF_INET = 2
SOCK_STREAM = 1
IPPROTO_TCP = 6
socket := DllCall("Ws2_32\socket", "Int", AF_INET, "Int", SOCK_STREAM, "Int", IPPROTO_TCP)
if socket = -1
{
    MsgBox % "socket() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
    return -1
}


SizeOfSocketAddress = 16
VarSetCapacity(SocketAddress, SizeOfSocketAddress)
InsertInteger(2, SocketAddress, 0, AF_INET)   ; sin_family
InsertInteger(DllCall("Ws2_32\htons", "UShort", Port), SocketAddress, 2, 2)   ; sin_port
InsertInteger(DllCall("Ws2_32\inet_addr", "Str", IPAddress), SocketAddress, 4, 4)   ; sin_addr.s_addr

if DllCall("Ws2_32\bind", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress)
{
    MsgBox % "bind() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") . "?"
    return -1
}
if DllCall("Ws2_32\listen", "UInt", socket, "UInt", "SOMAXCONN")
{
    MsgBox % "LISTEN() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") . "?"
    return -1
}
return socket

}

;接收消息函数
ReceiveData(wParam, lParam)
{
Critical
global ShowRecieved
socket := wParam
ReceivedDataSize = 4096
Loop
{
VarSetCapacity(ReceivedData, ReceivedDataSize, 0)
ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
if ReceivedDataLength = -1
{
WinsockError := DllCall("Ws2_32\WSAGetLastError")
if WinsockError = 10035
return 1
if WinsockError <> 10054
;MsgBox % "recv() indicated Winsock error " . WinsockError
return WinsockError
}
if ReceivedData
deal(ReceivedData)
}
return 1
}

deal(ReceivedData){
global QA,Q_id,SendText
GuiControlGet, show
if RegExMatch(ReceivedData,"(.*)_a(A|B|C|D)",m)
{
if (m2=QA[Q_id]["Answer"])
{
SendText := "正确答案:" m2 ",恭喜" m1 "回答正确!即将换题"
GuiControl, , show, % show ? show "n" SendText : SendText
gosub, sendall
Sleep, 2000
gosub, change
}
else
{
SendText := m1 "回答错误!"
GuiControl, , show, % show ? show "
n" SendText : SendText
gosub, sendall
}
}
}

SendData(WS2_Socket, StringToSend) {
WSA_send(WS2_Socket, &StringToSend, StrLen(StringToSend))
}

WSA_send(__WSA_Socket, __WSA_Data, __WSA_DataLen)
{
Result := DllCall("Ws2_32\send"
, "UInt", __WSA_Socket
, "UInt", __WSA_Data
, "Int", __WSA_DataLen
, "Int", 0)
Return Result
}

InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
{
Loop %pSize%
DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}

CloseSocket(Socket)
{
Result := DllCall("Ws2_32\closesocket"
, "UInt", Socket)
Return result
}

GuiClose:
exit:
;清除连接
Loop %i% {
CloseSocket(conectioncheck%A_Index%)
}
DllCall("Ws2_32\WSACleanup")
ExitApp

客户端

#singleinstance Off
OnExit, exit
;创建窗口以接收数据
Gui, add, Edit, x0 y0 w400 h200 vshow
Gui, add, button, x0 y200 w100 h20 gaA, A
Gui, add, button, x100 y200 w100 h20 gaB, B
Gui, add, button, x200 y200 w100 h20 gaC, C
Gui, add, button, x300 y200 w100 h20 gaD, D
Gui, show, , 答题游戏客户端
;客户端名称 服务器地址 端口
ClientName=%A_Computername%
;Network_Address = 218.31.127.210
Network_Address = 127.0.0.1
Network_Port = 1000
;连接到服务器
socket := ConnectToAddress(Network_Address, Network_Port)
if socket = -1
    ExitApp
;获取窗口句柄
;获取窗口句柄
otificationMsg := 0x5555,FD_Read := 1,FD_CLOSE := 32,FD_CONNECT := 20    ;消息号 大于0x1000;当消息可以读取时接收;当连接关闭后时接收
;设置接收消息的函数
OnMessage(NotificationMsg, "ReceiveData")
;设置接收关联
if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", A_ScriptHwnd, "UInt", NotificationMsg, "Int", FD_READ|FD_CONNECT)
{
    MsgBox % "WSAAsyncSelect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
    ExitApp
}
;发送连接好消息
;SendData(socket,ClientName " Login!")
return

aA:
aB:
aC:
aD:
SendData(socket, ClientName "_" A_ThisLabel)
return

;连接服务器函数
ConnectToAddress(IPAddress, Port)
{
    VarSetCapacity(wsaData, 32)
    result := DllCall("Ws2_32\WSAStartup", "UShort", 0x0002, "UInt", &wsaData)
    if ErrorLevel
    {
        MsgBox WSAStartup() could not be called due to error %ErrorLevel%. Winsock 2.0 or higher is required.
        return -1
    }
    if result
    {
        MsgBox % "WSAStartup() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
        return -1
    }
AF_INET = 2
SOCK_STREAM = 1
IPPROTO_TCP = 6
socket := DllCall("Ws2_32\socket", "Int", AF_INET, "Int", SOCK_STREAM, "Int", IPPROTO_TCP)
if socket = -1
{
    MsgBox % "socket() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
    return -1
}


SizeOfSocketAddress = 16
VarSetCapacity(SocketAddress, SizeOfSocketAddress)
InsertInteger(2, SocketAddress, 0, AF_INET)
InsertInteger(DllCall("Ws2_32\htons", "UShort", Port), SocketAddress, 2, 2)
InsertInteger(DllCall("Ws2_32\inet_addr", "Str", IPAddress), SocketAddress, 4, 4)


if DllCall("Ws2_32\connect", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress)
{
    MsgBox % "connect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") . "?"
    return -1
}
return socket

}

;接收函数
ReceiveData(wParam, lParam)
{
Critical
global ShowRecieved
socket := wParam
ReceivedDataSize = 4096
Loop
{
VarSetCapacity(ReceivedData, ReceivedDataSize, 0)
ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
if ReceivedDataLength = 0
ExitApp
if ReceivedDataLength = -1
{
WinsockError := DllCall("Ws2_32\WSAGetLastError")
if WinsockError = 10035
return 1
if WinsockError <> 10054

          MsgBox % "recv() indicated Winsock error " . WinsockError
        ExitApp
    }
    if ReceivedData
    deal(ReceivedData)
}
return 1

}

deal(ReceivedData){
if ReceivedData = Clean
GuiControl, , show,
else
{
GuiControlGet, show
GuiControl, , show, % show ? show "`n" ReceivedData : ReceivedData
}
}

InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)

{
Loop %pSize%
DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}

CloseSocket(Socket)
{
Result := DllCall("Ws2_32\closesocket"
, "UInt", Socket)
Return result
}

SendData(WS2_Socket, StringToSend) {
WSA_send(WS2_Socket, &StringToSend, StrLen(StringToSend))
}

WSA_send(__WSA_Socket, __WSA_Data, __WSA_DataLen)
{
Result := DllCall("Ws2_32\send"
, "UInt", __WSA_Socket
, "UInt", __WSA_Data
, "Int", __WSA_DataLen
, "Int", 0)
Return Result
}

GuiClose:
exit:
;清除连接
if socket
CloseSocket(socket)
DllCall("Ws2_32\WSACleanup")
ExitApp

给TA捐赠
共{{data.count}}人
人已捐赠
AHKV1游戏

[AHK游戏]AHKRoid

2018-2-2 19:41:28

游戏

[剑灵]剑灵各职业卡刀宏

2018-2-5 11:20:35

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索